国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

C#讀取Excel的三種方式以及比較分析

2019-10-29 21:36:32
字體:
來源:轉載
供稿:網友

這篇文章主要介紹了C#讀取Excel的三種方式以及比較分析,需要的朋友可以參考下

(1)OleDB方式

優點:將Excel直接當做數據源處理,通過SQL直接讀取內容,讀取速度較快。

缺點:讀取數據方式不夠靈活,無法直接讀取某一個單元格,只有將整個Sheet頁讀取出來后(結果為Datatable)再在Datatable中根據行列數來獲取指定的值。

當Excel數據量很大時。會非常占用內存,當內存不夠時會拋出內存溢出的異常。

讀取代碼如下:

 

 
  1. public DataTable GetExcelTableByOleDB(string strExcelPath, string tableName) 
  2. try 
  3. DataTable dtExcel = new DataTable(); 
  4. //數據表 
  5. DataSet ds = new DataSet(); 
  6. //獲取文件擴展名 
  7. string strExtension = System.IO.Path.GetExtension(strExcelPath); 
  8. string strFileName = System.IO.Path.GetFileName(strExcelPath); 
  9. //Excel的連接 
  10. OleDbConnection objConn = null
  11. switch (strExtension) 
  12. case ".xls"
  13. objConn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + strExcelPath + ";" + "Extended Properties=/"Excel 8.0;HDR=NO;IMEX=1;/""); 
  14. break
  15. case ".xlsx"
  16. objConn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + strExcelPath + ";" + "Extended Properties=/"Excel 12.0;HDR=NO;IMEX=1;/""); 
  17. break
  18. default
  19. objConn = null
  20. break
  21. if (objConn == null
  22. return null
  23. objConn.Open(); 
  24. //獲取Excel中所有Sheet表的信息 
  25. //System.Data.DataTable schemaTable = objConn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, null); 
  26. //獲取Excel的第一個Sheet表名 
  27. //string tableName = schemaTable.Rows[0][2].ToString().Trim(); 
  28. string strSql = "select * from [" + tableName + "]"
  29. //獲取Excel指定Sheet表中的信息 
  30. OleDbCommand objCmd = new OleDbCommand(strSql, objConn); 
  31. OleDbDataAdapter myData = new OleDbDataAdapter(strSql, objConn); 
  32. myData.Fill(ds, tableName);//填充數據 
  33. objConn.Close(); 
  34. //dtExcel即為excel文件中指定表中存儲的信息 
  35. dtExcel = ds.Tables[tableName]; 
  36. return dtExcel; 
  37. catch 
  38. return null

下面說明一下連接字符串

HDR=Yes,這代表第一行是標題,不做為數據使用(但是我在實際使用中,如果第一行存在復雜數值,那么讀取得到的Datatable列標題會自動設置為F1、F2等方式命名,與實際應用不符,所以當時是通過HDR=No方式將所有內容讀取到Datatable中,然后手動將第一行設置成標題的);IMEX ( IMport EXport mode )設置

IMEX 有三種模式:

0 is Export mode

1 is Import mode

2 is Linked mode (full update capabilities)

我這里特別要說明的就是 IMEX 參數了,因為不同的模式代表著不同的讀寫行為:

當 IMEX=0 時為“匯出模式”,這個模式開啟的 Excel 檔案只能用來做“寫入”用途。

當 IMEX=1 時為“匯入模式”,這個模式開啟的 Excel 檔案只能用來做“讀取”用途。

當 IMEX=2 時為“鏈接模式”,這個模式開啟的 Excel 檔案可同時支援“讀取”與“寫入”用途。

---------------------------------

另外,讀取Excel2007版本的文件時,版本應該從8.0改為12.0,同時驅動不能再用Jet,而應該用ACE。負責會造成“找不到可安裝的 ISAM”的錯誤。

---------------------------------

在網上還發現采用這種方式存在取出的Sheet表的個數多于實際Excel表中的Sheet表個數的情況,其原因有二:

1. 取出的名稱中,包括了XL命名管理器中的名稱(參見XL2007的公式--命名管理器, 快捷鍵Crtl+F3);

2. 取出的名稱中,包括了FilterDatabase后綴的, 這是XL用來記錄Filter范圍的。

對于第一點比較簡單, 刪除已有命名管理器中的內容即可;第二點處理起來比較麻煩, Filter刪除后這些名稱依然保留著,簡單的做法是新增Sheet然后將原Sheet Copy進去。但實際情況并不能為每個Excel做以上檢查。下面給出了過濾的方案。(此問題我們有驗證過,大家自己驗證一下吧)

 

 
  1. //objConn為讀取Excel的鏈接,下面通過過濾來獲取有效的Sheet頁名稱集合 
  2. System.Data.DataTable schemaTable = objConn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, null); 
  3. List<string> lstSheetNames = new List<string>(); 
  4. for (int i = 0; i < schemaTable.Rows.Count; i++) 
  5. string strSheetName = (string)dtSheetName.Rows[i]["TABLE_NAME"]; 
  6. if (strSheetName.Contains("$") && !strSheetName.Replace("'""").EndsWith("$")) 
  7. //過濾無效SheetName完畢.... 
  8. continue
  9. if (lstSheetNames != null && !lstSheetNames.Contains(strSheetName)) 
  10. lstSheetNames.Add(strSheetName); 

因為讀取出來無效SheetName一般情況最后一個字符都不會是$。如果SheetName有一些特殊符號,讀取出來的SheetName會自動加上單引號。比如在Excel中將SheetName編輯成MySheet(1),此時讀取出來的SheetName就為:'MySheet(1)$',所以判斷最后一個字符是不是$之前最好過濾一下單引號。

---------------------------------

(2)Com組件的方式(通過添加 Microsoft.Office.Interop.Excel引用實現)

優點:能夠非常靈活的讀取Excel中的數據,用戶可以靈活的調用各種函數進行處理。

缺點:基于單元格的處理,讀取速度較慢,對于數據量較大的文件最好不要使用此種方式讀取。

需要添加相應的DLL引用,必須存在此引用才可使用,如果是Web站點部署在IIS上時,還需要服務器機子已安裝了Excel,有時候還需要為配置IIS權限。

讀取代碼如下:

 

 
  1. private Stopwatch wath = new Stopwatch(); 
  2. /// <summary> 
  3. /// 使用COM讀取Excel 
  4. /// </summary> 
  5. /// <param name="excelFilePath">路徑</param> 
  6. /// <returns>DataTabel</returns> 
  7. public System.Data.DataTable GetExcelData(string excelFilePath) 
  8. Excel.Application app = new Excel.Application(); 
  9. Excel.Sheets sheets; 
  10. Excel.Workbook workbook = null
  11. object oMissiong = System.Reflection.Missing.Value; 
  12. System.Data.DataTable dt = new System.Data.DataTable(); 
  13. wath.Start(); 
  14. try 
  15. if (app == null
  16. return null
  17. workbook = app.Workbooks.Open(excelFilePath, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong,  
  18. oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong); 
  19. //將數據讀入到DataTable中——Start  
  20. sheets = workbook.Worksheets; 
  21. Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1);//讀取第一張表 
  22. if (worksheet == null
  23. return null
  24. string cellContent; 
  25. int iRowCount = worksheet.UsedRange.Rows.Count; 
  26. int iColCount = worksheet.UsedRange.Columns.Count; 
  27. Excel.Range range; 
  28. //負責列頭Start 
  29. DataColumn dc; 
  30. int ColumnID = 1; 
  31. range = (Excel.Range)worksheet.Cells[1, 1]; 
  32. while (range.Text.ToString().Trim() != ""
  33. dc = new DataColumn(); 
  34. dc.DataType = System.Type.GetType("System.String"); 
  35. dc.ColumnName = range.Text.ToString().Trim(); 
  36. dt.Columns.Add(dc); 
  37.  
  38. range = (Excel.Range)worksheet.Cells[1, ++ColumnID]; 
  39. //End 
  40. for (int iRow = 2; iRow <= iRowCount; iRow++) 
  41. DataRow dr = dt.NewRow(); 
  42. for (int iCol = 1; iCol <= iColCount; iCol++) 
  43. range = (Excel.Range)worksheet.Cells[iRow, iCol]; 
  44. cellContent = (range.Value2 == null) ? "" : range.Text.ToString(); 
  45. dr[iCol - 1] = cellContent; 
  46. dt.Rows.Add(dr); 
  47. wath.Stop(); 
  48. TimeSpan ts = wath.Elapsed; 
  49. //將數據讀入到DataTable中——End 
  50. return dt; 
  51. catch 
  52. return null
  53. finally 
  54. workbook.Close(false, oMissiong, oMissiong); 
  55. System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook); 
  56. workbook = null
  57. app.Workbooks.Close(); 
  58. app.Quit(); 
  59. System.Runtime.InteropServices.Marshal.ReleaseComObject(app); 
  60. app = null
  61. GC.Collect(); 
  62. GC.WaitForPendingFinalizers(); 
  63. /// <summary> 
  64. /// 使用COM,多線程讀取Excel(1 主線程、4 副線程) 
  65. /// </summary> 
  66. /// <param name="excelFilePath">路徑</param> 
  67. /// <returns>DataTabel</returns> 
  68. public System.Data.DataTable ThreadReadExcel(string excelFilePath) 
  69. Excel.Application app = new Excel.Application(); 
  70. Excel.Sheets sheets = null
  71. Excel.Workbook workbook = null
  72. object oMissiong = System.Reflection.Missing.Value; 
  73. System.Data.DataTable dt = new System.Data.DataTable(); 
  74. wath.Start(); 
  75. try 
  76. if (app == null
  77. return null
  78. workbook = app.Workbooks.Open(excelFilePath, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong,  
  79. oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong); 
  80. //將數據讀入到DataTable中——Start  
  81. sheets = workbook.Worksheets; 
  82. Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1);//讀取第一張表 
  83. if (worksheet == null
  84. return null
  85. string cellContent; 
  86. int iRowCount = worksheet.UsedRange.Rows.Count; 
  87. int iColCount = worksheet.UsedRange.Columns.Count; 
  88. Excel.Range range; 
  89. //負責列頭Start 
  90. DataColumn dc; 
  91. int ColumnID = 1; 
  92. range = (Excel.Range)worksheet.Cells[1, 1]; 
  93. while (iColCount >= ColumnID) 
  94. dc = new DataColumn(); 
  95. dc.DataType = System.Type.GetType("System.String"); 
  96. string strNewColumnName = range.Text.ToString().Trim(); 
  97. if (strNewColumnName.Length == 0) strNewColumnName = "_1"
  98. //判斷列名是否重復 
  99. for (int i = 1; i < ColumnID; i++) 
  100. if (dt.Columns[i - 1].ColumnName == strNewColumnName) 
  101. strNewColumnName = strNewColumnName + "_1"
  102. dc.ColumnName = strNewColumnName; 
  103. dt.Columns.Add(dc); 
  104. range = (Excel.Range)worksheet.Cells[1, ++ColumnID]; 
  105. //End 
  106. //數據大于500條,使用多進程進行讀取數據 
  107. if (iRowCount - 1 > 500) 
  108. //開始多線程讀取數據 
  109. //新建線程 
  110. int b2 = (iRowCount - 1) / 10; 
  111. DataTable dt1 = new DataTable("dt1"); 
  112. dt1 = dt.Clone(); 
  113. SheetOptions sheet1thread = new SheetOptions(worksheet, iColCount, 2, b2 + 1, dt1); 
  114. Thread othread1 = new Thread(new ThreadStart(sheet1thread.SheetToDataTable)); 
  115. othread1.Start(); 
  116. //阻塞 1 毫秒,保證第一個讀取 dt1 
  117. Thread.Sleep(1); 
  118. DataTable dt2 = new DataTable("dt2"); 
  119. dt2 = dt.Clone(); 
  120. SheetOptions sheet2thread = new SheetOptions(worksheet, iColCount, b2 + 2, b2 * 2 + 1, dt2); 
  121. Thread othread2 = new Thread(new ThreadStart(sheet2thread.SheetToDataTable)); 
  122. othread2.Start(); 
  123. DataTable dt3 = new DataTable("dt3"); 
  124. dt3 = dt.Clone(); 
  125. SheetOptions sheet3thread = new SheetOptions(worksheet, iColCount, b2 * 2 + 2, b2 * 3 + 1, dt3); 
  126. Thread othread3 = new Thread(new ThreadStart(sheet3thread.SheetToDataTable)); 
  127. othread3.Start(); 
  128. DataTable dt4 = new DataTable("dt4"); 
  129. dt4 = dt.Clone(); 
  130. SheetOptions sheet4thread = new SheetOptions(worksheet, iColCount, b2 * 3 + 2, b2 * 4 + 1, dt4); 
  131. Thread othread4 = new Thread(new ThreadStart(sheet4thread.SheetToDataTable)); 
  132. othread4.Start(); 
  133. //主線程讀取剩余數據 
  134. for (int iRow = b2 * 4 + 2; iRow <= iRowCount; iRow++) 
  135. DataRow dr = dt.NewRow(); 
  136. for (int iCol = 1; iCol <= iColCount; iCol++) 
  137. range = (Excel.Range)worksheet.Cells[iRow, iCol]; 
  138. cellContent = (range.Value2 == null) ? "" : range.Text.ToString(); 
  139. dr[iCol - 1] = cellContent; 
  140. dt.Rows.Add(dr); 
  141. othread1.Join(); 
  142. othread2.Join(); 
  143. othread3.Join(); 
  144. othread4.Join(); 
  145. //將多個線程讀取出來的數據追加至 dt1 后面 
  146. foreach (DataRow dr in dt.Rows) 
  147. dt1.Rows.Add(dr.ItemArray); 
  148. dt.Clear(); 
  149. dt.Dispose(); 
  150. foreach (DataRow dr in dt2.Rows) 
  151. dt1.Rows.Add(dr.ItemArray); 
  152. dt2.Clear(); 
  153. dt2.Dispose(); 
  154. foreach (DataRow dr in dt3.Rows) 
  155. dt1.Rows.Add(dr.ItemArray); 
  156. dt3.Clear(); 
  157. dt3.Dispose(); 
  158. foreach (DataRow dr in dt4.Rows) 
  159. dt1.Rows.Add(dr.ItemArray); 
  160. dt4.Clear(); 
  161. dt4.Dispose(); 
  162. return dt1; 
  163. else 
  164. for (int iRow = 2; iRow <= iRowCount; iRow++) 
  165. DataRow dr = dt.NewRow(); 
  166. for (int iCol = 1; iCol <= iColCount; iCol++) 
  167. range = (Excel.Range)worksheet.Cells[iRow, iCol]; 
  168. cellContent = (range.Value2 == null) ? "" : range.Text.ToString(); 
  169. dr[iCol - 1] = cellContent; 
  170. dt.Rows.Add(dr); 
  171. wath.Stop(); 
  172. TimeSpan ts = wath.Elapsed; 
  173. //將數據讀入到DataTable中——End 
  174. return dt; 
  175. catch 
  176. return null
  177. finally 
  178. workbook.Close(false, oMissiong, oMissiong); 
  179. System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook); 
  180. System.Runtime.InteropServices.Marshal.ReleaseComObject(sheets); 
  181. workbook = null
  182. app.Workbooks.Close(); 
  183. app.Quit(); 
  184. System.Runtime.InteropServices.Marshal.ReleaseComObject(app); 
  185. app = null
  186. GC.Collect(); 
  187. GC.WaitForPendingFinalizers(); 

(3)NPOI方式讀取Excel(此方法未經過測試)

NPOI 是 POI 項目的 .NET 版本。POI是一個開源的Java讀寫Excel、WORD等微軟OLE2組件文檔的項目。使用 NPOI 你就可以在沒有安裝 Office 或者相應環境的機器上對 WORD/EXCEL 文檔進行讀寫。

優點:讀取Excel速度較快,讀取方式操作靈活性

缺點:需要下載相應的插件并添加到系統引用當中。

 

 
  1. /// <summary> 
  2. /// 將excel中的數據導入到DataTable中 
  3. /// </summary> 
  4. /// <param name="sheetName">excel工作薄sheet的名稱</param> 
  5. /// <param name="isFirstRowColumn">第一行是否是DataTable的列名</param> 
  6. /// <returns>返回的DataTable</returns> 
  7. public DataTable ExcelToDataTable(string sheetName, bool isFirstRowColumn) 
  8. ISheet sheet = null
  9. DataTable data = new DataTable(); 
  10. int startRow = 0; 
  11. try 
  12. fs = new FileStream(fileName, FileMode.Open, FileAccess.Read); 
  13. if (fileName.IndexOf(".xlsx") > 0) // 2007版本 
  14. workbook = new XSSFWorkbook(fs); 
  15. else if (fileName.IndexOf(".xls") > 0) // 2003版本 
  16. workbook = new HSSFWorkbook(fs); 
  17. if (sheetName != null
  18. sheet = workbook.GetSheet(sheetName); 
  19. else 
  20. sheet = workbook.GetSheetAt(0); 
  21. if (sheet != null
  22. IRow firstRow = sheet.GetRow(0); 
  23. int cellCount = firstRow.LastCellNum; //一行最后一個cell的編號 即總的列數 
  24. if (isFirstRowColumn) 
  25. for (int i = firstRow.FirstCellNum; i < cellCount; ++i) 
  26. DataColumn column = new DataColumn(firstRow.GetCell(i).StringCellValue); 
  27. data.Columns.Add(column); 
  28. startRow = sheet.FirstRowNum + 1; 
  29. else 
  30. startRow = sheet.FirstRowNum; 
  31. //最后一列的標號 
  32. int rowCount = sheet.LastRowNum; 
  33. for (int i = startRow; i <= rowCount; ++i) 
  34. IRow row = sheet.GetRow(i); 
  35. if (row == nullcontinue//沒有數據的行默認是null        
  36.  
  37. DataRow dataRow = data.NewRow(); 
  38. for (int j = row.FirstCellNum; j < cellCount; ++j) 
  39. if (row.GetCell(j) != null//同理,沒有數據的單元格都默認是null 
  40. dataRow[j] = row.GetCell(j).ToString(); 
  41. data.Rows.Add(dataRow); 
  42. return data; 
  43. catch (Exception ex) 
  44. Console.WriteLine("Exception: " + ex.Message); 
  45. return null

下面是一些相關的文章,大家可以參考下


注:相關教程知識閱讀請移步到c#教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 永兴县| 积石山| 章丘市| 马山县| 湟中县| 中西区| 古浪县| 元阳县| 诸暨市| 青川县| 石渠县| 治多县| 金溪县| 聊城市| 咸丰县| 微山县| 邯郸市| 塔城市| 玉门市| 蕉岭县| 镇江市| 彰化县| 苍溪县| 金堂县| 永安市| 腾冲县| 马公市| 长武县| 西乡县| 渭南市| 凌云县| 海南省| 嘉义市| 琼海市| 康平县| 延庆县| 来凤县| 广饶县| 万宁市| 城口县| 易门县|