1. 程式人生 > >DataSet匯出到Excel比較完整的解決方案 二 --伺服器端生成檔案 downmoon

DataSet匯出到Excel比較完整的解決方案 二 --伺服器端生成檔案 downmoon

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

 

 

前一篇文章中,介紹了DataSet匯出到Excel時客戶端生成檔案的幾種思路,接著往下說,伺服器端生成檔案,使用者直接下載,應該格式是可以保證的!

於是直接呼叫Excel的API生成。程式碼如下:

[c-sharp] view plain copy print ?
  1. public static void DataSetToLocalExcel(DataSet dataSet, string outputPath, bool deleteOldFile)  
  2.        {  
  3.            if (deleteOldFile)  
  4.            {  
  5.                if (System.IO.File.Exists(outputPath)) { System.IO.File.Delete(outputPath); }  
  6.            }  
  7.            // Create the Excel Application object  
  8.            ApplicationClass excelApp = new ApplicationClass();  
  9.            // Create a new Excel Workbook  
  10.            Workbook excelWorkbook = excelApp.Workbooks.Add(Type.Missing);  
  11.            int sheetIndex = 0;  
  12.            // Copy each DataTable  
  13.            foreach (System.Data.DataTable dt in dataSet.Tables)  
  14.            {  
  15.                // Copy the DataTable to an object array  
  16.                object[,] rawData = new object[dt.Rows.Count + 1, dt.Columns.Count];  
  17.                // Copy the column names to the first row of the object array  
  18.                for (int col = 0; col < dt.Columns.Count; col++)  
  19.                {  
  20.                    rawData[0, col] = dt.Columns[col].ColumnName;  
  21.                }  
  22.                // Copy the values to the object array  
  23.                for (int col = 0; col < dt.Columns.Count; col++)  
  24.                {  
  25.                    for (int row = 0; row < dt.Rows.Count; row++)  
  26.                    {  
  27.                        rawData[row + 1, col] = dt.Rows[row].ItemArray[col];  
  28.                    }  
  29.                }  
  30.                // Calculate the final column letter  
  31.                string finalColLetter = string.Empty;  
  32.                string colCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";  
  33.                int colCharsetLen = colCharset.Length;  
  34.                if (dt.Columns.Count > colCharsetLen)  
  35.                {  
  36.                    finalColLetter = colCharset.Substring(  
  37.                        (dt.Columns.Count - 1) / colCharsetLen - 1, 1);  
  38.                }  
  39.                finalColLetter += colCharset.Substring(  
  40.                        (dt.Columns.Count - 1) % colCharsetLen, 1);  
  41.                // Create a new Sheet  
  42.                Worksheet excelSheet = (Worksheet)excelWorkbook.Sheets.Add(  
  43.                    excelWorkbook.Sheets.get_Item(++sheetIndex),  
  44.                    Type.Missing, 1, XlSheetType.xlWorksheet);  
  45.                excelSheet.Name = dt.TableName;  
  46.                // Fast data export to Excel  
  47.                string excelRange = string.Format("A1:{0}{1}",  
  48.                    finalColLetter, dt.Rows.Count + 1);  
  49.                excelSheet.get_Range(excelRange, Type.Missing).Value2 = rawData;  
  50.                // Mark the first row as BOLD  
  51.                ((Range)excelSheet.Rows[1, Type.Missing]).Font.Bold = true;  
  52.            }  
  53.            //excelApp.Application.AlertBeforeOverwriting = false;  
  54.            excelApp.Application.DisplayAlerts = false;  
  55.            // Save and Close the Workbook  
  56.            excelWorkbook.SaveAs(outputPath, XlFileFormat.xlWorkbookNormal, Type.Missing,  
  57.                Type.Missing, Type.Missing, Type.Missing, XlSaveAsAccessMode.xlExclusive,  
  58.                Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);  
  59.            excelWorkbook.Close(true, Type.Missing, Type.Missing);  
  60.            excelWorkbook = null;  
  61.            // Release the Application object  
  62.            excelApp.Quit();  
  63.            excelApp = null;  
  64.            // Collect the unreferenced objects  
  65.            GC.Collect();  
  66.            GC.WaitForPendingFinalizers();  
  67.        }  
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 - 1, 1);                }                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許可權。步驟如下:

 

[css] view plain copy print ?
  1. 配置  DCOM  中  EXCEL  應用程式:  
  2. 要在互動式使用者帳戶下設定  Office  自動化伺服器,請按照下列步驟操作:   
  3. 1.  以管理員身份登入到計算機,並使用完整安裝來安裝(或重新安裝)Office。為了實現系統的可靠性,建議您將  Office  CD-ROM  中的內容複製到本地驅動器並從此位置安裝  Office。   
  4. 2.  啟動要自動執行的  Office  應用程式。這會強制該應用程式進行自我註冊。   
  5. 3.  執行該應用程式後,請按  Alt+F11  以載入  Microsoft  Visual  Basic  for  Applications  (VBA)  編輯器。這會強制  VBA  進行初始化。   
  6. 4.  關閉應用程式,包括  VBA。   
  7. 5.  單擊開始,單擊執行,然後鍵入  DCOMCNFG。選擇要自動執行的應用程式。應用程式名稱如下所示:   
  8. Microsoft  Access  97  -  Microsoft  Access  資料庫  
  9. Microsoft  Access  2000/2002  -  Microsoft  Access  應用程式  
  10. Microsoft  Excel  97/2000/2002  -  Microsoft  Excel  應用程式  
  11. Microsoft  Word  97  -  Microsoft  Word  Basic  
  12. Microsoft  Word  2000/2002  -  Microsoft  Word  文件   
  13. 單擊屬性開啟此應用程式的屬性對話方塊。  
  14. 6.  單擊安全選項卡。驗證使用預設的訪問許可權和使用預設的啟動許可權已選中。   
  15. 7.  單擊標識選項卡,然後選擇互動式使用者。   
  16. 8.  單擊確定,關閉屬性對話方塊並返回主應用程式列表對話方塊。   
  17. 9.  在  DCOM  配置對話方塊中,單擊預設安全性選項卡。   
  18. 10.  單擊訪問許可權的編輯預設值。驗證訪問許可權中是否列出下列使用者,如果沒有列出,則新增這些使用者:   
  19. SYSTEM  
  20. INTERACTIVE  
  21. Everyone  
  22. Administrators  
  23. IUSR_ <machinename> *  
  24. IWAM_ <machinename> *  
  25. *  這些帳戶僅在計算機上安裝了  Internet  Information  Server  (IIS)  的情況下才存在。   
  26. 11.  確保允許每個使用者訪問,然後單擊確定。   
  27. 12.  單擊啟動許可權的編輯預設值。驗證啟動許可權中是否列出下列使用者,如果沒有列出,則新增這些使用者:   
  28. SYSTEM  
  29. INTERACTIVE  
  30. Everyone  
  31. Administrators  
  32. IUSR_ <machinename> *  
  33. IWAM_ <machinename> *  
  34. *  這些帳戶僅在計算機上安裝有  IIS  的情況下才存在。   
  35. 13.  確保允許每個使用者訪問,然後單擊確定。   
  36. 14.  單擊確定關閉  DCOMCNFG。   
  37. 如果你之前起用了身份模擬  (在  web.config  中配置了  <identity  impersonate= "true "/>  )  ,需要刪除之!   
  38. 15.更新安裝office,把.net可程式設計元件安裝到本機(excel元件)  
  39. 如果還是不行.幹脃把互動式使用者 換成"啟動使用者"   
配置  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  BasicMicrosoft  Word  2000/2002  -  Microsoft  Word  文件 單擊屬性開啟此應用程式的屬性對話方塊。6.  單擊安全選項卡。驗證使用預設的訪問許可權和使用預設的啟動許可權已選中。 7.  單擊標識選項卡,然後選擇互動式使用者。 8.  單擊確定,關閉屬性對話方塊並返回主應用程式列表對話方塊。 9.  在  DCOM  配置對話方塊中,單擊預設安全性選項卡。 10.  單擊訪問許可權的編輯預設值。驗證訪問許可權中是否列出下列使用者,如果沒有列出,則新增這些使用者: SYSTEMINTERACTIVEEveryoneAdministratorsIUSR_ <machinename> *IWAM_ <machinename> **  這些帳戶僅在計算機上安裝了  Internet  Information  Server  (IIS)  的情況下才存在。 11.  確保允許每個使用者訪問,然後單擊確定。 12.  單擊啟動許可權的編輯預設值。驗證啟動許可權中是否列出下列使用者,如果沒有列出,則新增這些使用者: SYSTEMINTERACTIVEEveryoneAdministratorsIUSR_ <machinename> *IWAM_ <machinename> **  這些帳戶僅在計算機上安裝有  IIS  的情況下才存在。 13.  確保允許每個使用者訪問,然後單擊確定。 14.  單擊確定關閉  DCOMCNFG。 如果你之前起用了身份模擬  (在  web.config  中配置了  <identity  impersonate= "true "/>  )  ,需要刪除之! 15.更新安裝office,把.net可程式設計元件安裝到本機(excel元件)如果還是不行.幹脃把互動式使用者 換成"啟動使用者"

 

折騰了一番,總算可以用了!·只是伺服器上裝Office總感覺不爽,於是再嘗試下別的方法:

 

Reading and Writing Excel using OLEDB

主要的類檔案如下:

[c-sharp] view plain copy print ?
  1. /**//// <summary>  
  2.     /// Summary description for ExcelReader.  
  3.     /// </summary>  
  4.     public class ExcelReader : IDisposable  
  5.     {  
  6.         Variables#region Variables  
  7.         private int[] _PKCol;  
  8.         private string _strExcelFilename;  
  9.         private bool _blnMixedData = true;  
  10.         private bool _blnHeaders = false;  
  11.         private string _strSheetName;  
  12.         private string _strSheetRange;  
  13.         private bool _blnKeepConnectionOpen = false;  
  14.         private OleDbConnection _oleConn;  
  15.         private OleDbCommand _oleCmdSelect;  
  16.         private OleDbCommand _oleCmdUpdate;  
  17.         #endregion  
  18.         properties#region properties  
  19.         public int[] PKCols  
  20.         {  
  21.             get { return _PKCol; }  
  22.             set { _PKCol = value; }  
  23.         }  
  24.         public string ColName(int intCol)  
  25.         {  
  26.             string sColName = "";  
  27.             if (intCol < 26)  
  28.                 sColName = Agronet.Common.Framework.Util.SQLParser.StringParse(Convert.ToChar((Convert.ToByte((char)'A') + intCol)));  
  29.             else  
  30.             {  
  31.                 int intFirst = ((int)intCol / 26);  
  32.                 int intSecond = ((int)intCol % 26);  
  33.                 sColName = Agronet.Common.Framework.Util.SQLParser.StringParse(Convert.ToByte((char)'A') + intFirst);  
  34.                 sColName += Agronet.Common.Framework.Util.SQLParser.StringParse(Convert.ToByte((char)'A') + intSecond);  
  35.             }  
  36.             return sColName;  
  37.         }  
  38.         public int ColNumber(string strCol)  
  39.         {  
  40.             strCol = strCol.ToUpper();  
  41.             int intColNumber = 0;  
  42.             if (strCol.Length > 1)  
  43.             {  
  44.                 intColNumber = Agronet.Common.Framework.Util.SQLParser.ShortParse(Convert.ToByte(strCol[1]) - 65);  
  45.                 intColNumber += Agronet.Common.Framework.Util.SQLParser.ShortParse(Convert.ToByte(strCol[1]) - 64) * 26;  
  46.             }  
  47.             else  
  48.                 intColNumber = Agronet.Common.Framework.Util.SQLParser.ShortParse(Convert.ToByte(strCol[0]) - 65);  
  49.             return intColNumber;  
  50.         }  
  51.         public String[] GetExcelSheetNames()  
  52.         {  
  53.             System.Data.DataTable dt = null;  
  54.             try  
  55.             {  
  56.                 if (_oleConn == null) Open();  
  57.                 // Get the data table containing the schema  
  58.                 dt = _oleConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);  
  59.                 if (dt == null) { return null; }  
  60.                 String[] excelSheets = new String[dt.Rows.Count];  
  61.                 int i = 0;  
  62.                 // Add the sheet name to the string array.  
  63.                 foreach (DataRow row in dt.Rows)  
  64.                 {  
  65.                     string strSheetTableName = row["TABLE_NAME"].ToString();  
  66.                     excelSheets[i] = strSheetTableName.Substring(0, strSheetTableName.Length - 1);  
  67.                     i++;  
  68.                 }  
  69.                 return excelSheets;  
  70.             }  
  71.             catch (Exception ex)//tony 2008.12.31 update  
  72.             {  
  73.                 string s = ex.Message; return null;  
  74.             }  
  75.             finally  
  76.             {  
  77.                 // Clean up.  
  78.                 if (this.KeepConnectionOpen == false)  
  79.                 {  
  80.                     this.Close();  
  81.                 }  
  82.                 if (dt != null)  
  83.                 {  
  84.                     dt.Dispose();  
  85.                     dt = null;  
  86.                 }  
  87.             }  
  88.         }  
  89.         public string ExcelFilename  
  90.         {  
  91.             get { return _strExcelFilename; }  
  92.             set { _strExcelFilename = value; }  
  93.         }  
  94.         public string SheetName  
  95.         {  
  96.             get { return _strSheetName; }  
  97.             set { _strSheetName = value; }  
  98.         }  
  99.         public string SheetRange  
  100.         {  
  101.             get { return _strSheetRange; }  
  102.             set  
  103.             {  
  104.                 if (value.IndexOf(":") == -1) throw new Exception("Invalid range length");  
  105.                 _strSheetRange = value;  
  106.             }  
  107.         }  
  108.         public bool KeepConnectionOpen  
  109.         {  
  110.             get { return _blnKeepConnectionOpen; }  
  111.             set { _blnKeepConnectionOpen = value; }  
  112.         }  
  113.         public bool Headers  
  114.         {  
  115.             get { return _blnHeaders; }  
  116.             set { _blnHeaders = value; }  
  117.         }  
  118.         public bool MixedData  
  119.         {  
  120.             get { return _blnMixedData; }  
  121.             set { _blnMixedData = value; }  
  122.         }  
  123.         #endregion  
  124.         Methods#region Methods  
  125.         Excel Connection#region Excel Connection  
  126.         private string ExcelConnectionOptions()  
  127.         {  
  128.             string strOpts = "";  
  129.             if (this.MixedData == true)  
  130.                 strOpts += "Imex=1;";  
  131.             if (this.Headers == true)  
  132.                 strOpts += "HDR=Yes;";  
  133.             else  
  134.                 strOpts += "HDR=No;";  
  135.             return strOpts;  
  136.         }  
  137.         private string ExcelConnection()  
  138.         {  
  139.             return  
  140.                 @"Provider=Microsoft.Jet.OLEDB.4.0;" +  
  141.                 @"Data Source=" + _strExcelFilename + ";" +  
  142.                 @"Extended Properties=" + Convert.ToChar(34).ToString() +  
  143.                 @"Excel 8.0;" + ExcelConnectionOptions() + Convert.ToChar(34).ToString();  
  144.         }  
  145.         #endregion  
  146.         Open / Close#region Open / Close  
  147.         public void Open()  
  148.         {  
  149.             try  
  150.             {  
  151.                 if (_oleConn != null)  
  152.                 {  
  153.                     if (_oleConn.State == ConnectionState.Open)  
  154.                     {  
  155.                         _oleConn.Close();  
  156.                     }  
  157.                     _oleConn = null;  
  158.                 }  
  159.