zoukankan      html  css  js  c++  java
  • DataSet导出到Excel比较完整的解决方案(二)服务器端生成文件(downmoon)

    前一篇文章中,介绍了DataSet导出到Excel时客户端生成文件的几种思路,接着往下说,服务器端生成文件,用户直接下载,应该格式是可以保证的!

    于是直接调用Excel的API生成。代码如下:


     public static void DataSetToLocalExcel(DataSet dataSet, string outputPath, bool deleteOldFile)
            
    {
                
    if (deleteOldFile)
                
    {
                    
    if (System.IO.File.Exists(outputPath)) { System.IO.File.Delete(outputPath); }
                }

                
    // Create the Excel Application object
                ApplicationClass excelApp = new ApplicationClass();

                
    // Create a new Excel Workbook
                Workbook excelWorkbook = excelApp.Workbooks.Add(Type.Missing);

                
    int sheetIndex = 0;

                
    // Copy each DataTable
                foreach (System.Data.DataTable dt in dataSet.Tables)
                
    {

                    
    // Copy the DataTable to an object array
                    object[,] rawData = new object[dt.Rows.Count + 1, dt.Columns.Count];

                    
    // Copy the column names to the first row of the object array
                    for (int col = 0; col < dt.Columns.Count; col++)
                    
    {
                        rawData[
    0, col] = dt.Columns[col].ColumnName;
                    }


                    
    // Copy the values to the object array
                    for (int col = 0; col < dt.Columns.Count; col++)
                    
    {
                        
    for (int row = 0; row < dt.Rows.Count; row++)
                        
    {
                            rawData[row 
    + 1, col] = dt.Rows[row].ItemArray[col];
                        }

                    }


                    
    // Calculate the final column letter
                    string finalColLetter = string.Empty;
                    
    string colCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                    
    int colCharsetLen = colCharset.Length;

                    
    if (dt.Columns.Count > colCharsetLen)
                    
    {
                        finalColLetter 
    = colCharset.Substring(
                            (dt.Columns.Count 
    - 1/ colCharsetLen - 11);
                    }


                    finalColLetter 
    += colCharset.Substring(
                            (dt.Columns.Count 
    - 1% colCharsetLen, 1);

                    
    // Create a new Sheet
                    Worksheet excelSheet = (Worksheet)excelWorkbook.Sheets.Add(
                        excelWorkbook.Sheets.get_Item(
    ++sheetIndex),
                        Type.Missing, 
    1, XlSheetType.xlWorksheet);

                    excelSheet.Name 
    = dt.TableName;

                    
    // Fast data export to Excel
                    string excelRange = string.Format("A1:{0}{1}",
                        finalColLetter, dt.Rows.Count 
    + 1);

                    excelSheet.get_Range(excelRange, Type.Missing).Value2 
    = rawData;

                    
    // Mark the first row as BOLD
                    ((Range)excelSheet.Rows[1, Type.Missing]).Font.Bold = true;
                }

                
    //excelApp.Application.AlertBeforeOverwriting = false;
                excelApp.Application.DisplayAlerts = false;
                
    // Save and Close the Workbook
                excelWorkbook.SaveAs(outputPath, XlFileFormat.xlWorkbookNormal, Type.Missing,
                    Type.Missing, Type.Missing, Type.Missing, XlSaveAsAccessMode.xlExclusive,
                    Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
                excelWorkbook.Close(
    true, Type.Missing, Type.Missing);
                excelWorkbook 
    = null;

                
    // Release the Application object
                excelApp.Quit();
                excelApp 
    = null;

                
    // Collect the unreferenced objects
                GC.Collect();
                GC.WaitForPendingFinalizers();

            }

    说明下,其中的  xlsApp.Application.DisplayAlerts   =   false;  的作用是不显示确认对话框    

    也可以逐Cell读取,那样可能会慢。本方法速度还过得去。

    生成Winform代码测试没错,部署时,以为只要引用两个dll就可以了

    Microsoft.Office.Interop.Excel.dll

    Office.dll


    那成想,问题接着来了,当在WebForm下调用时, 提示“检索   COM   类工厂中   CLSID   为   {00024500-0000-0000-C000-000000000046}   的组件时失败,原因是出现以下错误:   8000401a

    晕! Google下,解决方案是在服务器上安装Office,并配置DCOM权限。步骤如下:


    配置  DCOM  中  EXCEL  应用程序:
    要在交互式用户帐户下设置  Office  自动化服务器,请按照下列步骤操作: 
    1.  以管理员身份登录到计算机,并使用完整安装来安装(或重新安装)Office。为了实现系统的可靠性,建议您将  Office  CD-ROM  中的内容复制到本地驱动器并从此位置安装  Office。 
    2.  启动要自动运行的  Office  应用程序。这会强制该应用程序进行自我注册。 
    3.  运行该应用程序后,请按  Alt+F11  以加载  Microsoft  Visual  Basic  for  Applications  (VBA)  编辑器。这会强制  VBA  进行初始化。 
    4.  关闭应用程序,包括  VBA。 
    5.  单击开始,单击运行,然后键入  DCOMCNFG。选择要自动运行的应用程序。应用程序名称如下所示: 
    Microsoft  Access  97  -  Microsoft  Access  数据库
    Microsoft  Access  2000/2002  -  Microsoft  Access  应用程序
    Microsoft  Excel  97/2000/2002  -  Microsoft  Excel  应用程序
    Microsoft  Word  97  -  Microsoft  Word  Basic
    Microsoft  Word  2000/2002  -  Microsoft  Word  文档 
    单击属性打开此应用程序的属性对话框。
    6.  单击安全选项卡。验证使用默认的访问权限和使用默认的启动权限已选中。 
    7.  单击标识选项卡,然后选择交互式用户。 
    8.  单击确定,关闭属性对话框并返回主应用程序列表对话框。 
    9.  在  DCOM  配置对话框中,单击默认安全性选项卡。 
    10.  单击访问权限的编辑默认值。验证访问权限中是否列出下列用户,如果没有列出,则添加这些用户: 
    SYSTEM
    INTERACTIVE
    Everyone
    Administrators
    IUSR_ 
    <machinename> *
    IWAM_ 
    <machinename> *
    *  这些帐户仅在计算机上安装了  Internet  Information  Server  (IIS)  的情况下才存在。 
    11.  确保允许每个用户访问,然后单击确定。 
    12.  单击启动权限的编辑默认值。验证启动权限中是否列出下列用户,如果没有列出,则添加这些用户: 
    SYSTEM
    INTERACTIVE
    Everyone
    Administrators
    IUSR_ 
    <machinename> *
    IWAM_ 
    <machinename> *
    *  这些帐户仅在计算机上安装有  IIS  的情况下才存在。 
    13.  确保允许每个用户访问,然后单击确定。 
    14.  单击确定关闭  DCOMCNFG。 
    如果你之前起用了身份模拟  (在  web.config  中配置了  
    <identity  impersonate= "true "/>  )  ,需要删除之! 
    15.更新安装office,把.net可编程组件安装到本机(excel组件)
    如果还是不行.干脃把交互式用户 换成"启动用户" 

     
    折腾了一番,总算可以用了!·只是服务器上装Office总感觉不爽,于是再尝试下别的方法:

    Reading and Writing Excel using OLEDB

    主要的类文件如下:

     /// <summary>
        
    /// Summary description for ExcelReader.
        
    /// </summary>

        public class ExcelReader : IDisposable
        
    {
            
    Variables

            
    properties

            
    Methods

            
    public

            
    Dispose / Destructor

            
    CTOR
        }

    思路:通过读出Excel模板文件到DataTale,再把数据填充到DataTable,文件另存下就OK了!

     调用代码如下:


     public static string path = @"TempExcel\STemp.xls";
            
    public static string path2 = "TestUser.xls";
            
    public static string PreFilePath = @"C:\Excel\";
            
    public static void DataSetToLocalExcel(DataSet ds, string srcPath, string outputPath, bool deleteOldFile)
            
    {
                
    if (ds == null || ds.Tables[0== null && ds.Tables[0].Rows.Count == 0return; }
                
    if (deleteOldFile)
                
    {
                    
    if (System.IO.File.Exists(outputPath)) { System.IO.File.Delete(outputPath); }
                }

                System.IO.File.Copy(srcPath, outputPath, 
    true);
                ExcelReader exr 
    = new ExcelReader();
                exr.ExcelFilename 
    = outputPath;
                exr.Headers 
    = true;
                exr.MixedData 
    = true;
                exr.KeepConnectionOpen 
    = true;
                
    string[] sheetnames = exr.GetExcelSheetNames();
                exr.SheetName 
    = sheetnames[0];
                DataTable dt 
    = exr.GetTable();
                
    if (dt == nullreturn;
                exr.SetPrimaryKey(
    0);
                
    //dt.PrimaryKey = new DataColumn[] { dt.Columns["编号"] };
                DataTable dt2 = ds.Tables[0].Copy();
                dt.Rows.Clear();
                
    for (int i = 0; i < dt2.Rows.Count; i++)
                
    // Copy the values to the object array
                    DataRow dr = dt.NewRow();
                    
    for (int col = 0; col < dt.Columns.Count; col++)
                    
    {
                        dr[col] 
    = dt2.Rows[i][col];
                    }

                    dt.Rows.Add(dr);
                }

                exr.SetTable(dt);
                
    #region WriteFile
               
                
    #endregion

                exr.Close();
                exr.Dispose();
                exr 
    = null;
            }

            
    private DataSet Get_AllPrices()
            
    {
                
    try
                
    {
                    
    // Get the employee details
                    string strSql = "SELECT [CustomID] as 编号,[C_Name] as 品名,0 as 最高价格,0 as 最低价格,0 as 平均价格,'元/公斤' as 计量单位,'' as 备注  FROM [PriceCategory] WHERE ( 1=1 AND ([Puser] = 'tuser') )";
                    SqlConnection objConn 
    = new SqlConnection(@"Data Source=AP6;Initial Catalog=testdb2009 ;Persist Security Info=True;User ID=sa;Password=sa");
                    SqlDataAdapter daEmp 
    = new SqlDataAdapter(strSql, objConn);
                    daEmp.Fill(dsPrice, 
    "price");
                    
    return dsPrice;
                }

                
    catch (Exception Ex)
                
    {
                    
    throw Ex;
                }

            }


            DataSet dsPrice 
    = new DataSet();
            
    protected void btnGetData_Click(object sender, EventArgs e)
            
    {
                DataSetToLocalExcel(Get_AllPrices(), PreFilePath 
    + path, PreFilePath + path2, true);
            }

     

    这里有点强调下:OleDbConnection特别要注意, 刚开始用http://www.connectionstrings.com/excel

      提供的标准串:

    "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:"MyExcel.xls;Extended Properties="Excel 8.0;HDR=Yes;IMEX=1";

    结果提示:“操作必须使用一个可更新的查询”。因为读取结果正常,以为是excel没有写权限所致,增加了相应权限后,结果依然如故。这下火了! Google下, 有解决方案

    http://www.cnblogs.com/richinger/archive/2008/09/28/1301170.html

    A: HDR ( HeaDer Row )设置
        若指定值为Yes,代表 Excel 档中的工作表第一行是栏位名称

        若指定值為 No,代表 Excel 档中的工作表第一行就是資料了,沒有栏位名称

        B:IMEX ( IMport EXport mode )设置

         IMEX 有三种模式,各自引起的读写行为也不同,容後再述:
         0 is Export mode
         1 is Import mode
         2 is Linked mode (full update capabilities)

        

    于是修改为:


    Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:"MyExcel.xls;Extended Properties="Excel 8.0;HDR=Yes;IMEX=2";
  • 相关阅读:
    jsp转向
    什么是 XDoclet?
    tomcat中的几点配置说明
    mysql5问题
    POJ 3734 Blocks
    POJ 2409 Let it Bead
    HDU 1171 Big Event in HDU
    POJ 3046 Ant Counting
    HDU 2082 找单词
    POJ 1286 Necklace of Beads
  • 原文地址:https://www.cnblogs.com/liufei88866/p/1376765.html
Copyright © 2011-2022 走看看