C讀取Excel的三種方式以及比較分析_第1頁(yè)
C讀取Excel的三種方式以及比較分析_第2頁(yè)
C讀取Excel的三種方式以及比較分析_第3頁(yè)
C讀取Excel的三種方式以及比較分析_第4頁(yè)
C讀取Excel的三種方式以及比較分析_第5頁(yè)
已閱讀5頁(yè),還剩5頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、C#讀取Excel的三種方式以及比較分析投稿:mdxy-dxy 字體:增加 減小 類型:轉(zhuǎn)載 時(shí)間:2015-11-08 我要評(píng)論這篇文章主要介紹了C#讀取Excel的三種方式以及比較分析,需要的朋友可以參考下(1)OleDB方式優(yōu)點(diǎn):將Excel直接當(dāng)做數(shù)據(jù)源處理,通過(guò)SQL直接讀取內(nèi)容,讀取速度較快。缺點(diǎn):讀取數(shù)據(jù)方式不夠靈活,無(wú)法直接讀取某一個(gè)單元格,只有將整個(gè)Sheet頁(yè)讀取出來(lái)后(結(jié)果為Datatable)再在Datatable中根據(jù)行列數(shù)來(lái)獲取指定的值。當(dāng)Excel數(shù)據(jù)量很大時(shí)。會(huì)非常占用內(nèi)存,當(dāng)內(nèi)存不夠時(shí)會(huì)拋出內(nèi)存溢出的異常。讀取代碼如下:?1234567891011121314

2、15161718192021222324252627282930313233343536373839404142434445464748public DataTable GetExcelTableByOleDB(string strExcelPath, string tableName)  try      DataTable dtExcel = new DataTable();    /數(shù)據(jù)表    DataSet ds = new

3、DataSet();    /獲取文件擴(kuò)展名    string strExtension = System.IO.Path.GetExtension(strExcelPath);    string strFileName = System.IO.Path.GetFileName(strExcelPath);    /Excel的連接    OleDbConnection objConn = n

4、ull;    switch (strExtension)          case ".xls":        objConn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + strExcelPath + "" + &

5、quot;Extended Properties="Excel 8.0;HDR=NO;IMEX=1;"");        break;      case ".xlsx":        objConn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;

6、Data Source=" + strExcelPath + "" + "Extended Properties="Excel 12.0;HDR=NO;IMEX=1;"");        break;      default:        objConn = null;   

7、;     break;        if (objConn = null)          return null;        objConn.Open();    /獲取Excel中所有Sheet表的信息   

8、; /System.Data.DataTable schemaTable = objConn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, null);    /獲取Excel的第一個(gè)Sheet表名    /string tableName = schemaTable.Rows02.ToString().Trim();    string strSql = "select * f

9、rom " + tableName + ""    /獲取Excel指定Sheet表中的信息    OleDbCommand objCmd = new OleDbCommand(strSql, objConn);    OleDbDataAdapter myData = new OleDbDataAdapter(strSql, objConn);    myData.Fill(ds, tableName);

10、/填充數(shù)據(jù)    objConn.Close();    /dtExcel即為excel文件中指定表中存儲(chǔ)的信息    dtExcel = ds.TablestableName;    return dtExcel;    catch      return null;  下面說(shuō)明一下連接字符串HDR=Yes,這代表第

11、一行是標(biāo)題,不做為數(shù)據(jù)使用(但是我在實(shí)際使用中,如果第一行存在復(fù)雜數(shù)值,那么讀取得到的Datatable列標(biāo)題會(huì)自動(dòng)設(shè)置為F1、F2等方式命名,與實(shí)際應(yīng)用不符,所以當(dāng)時(shí)是通過(guò)HDR=No方式將所有內(nèi)容讀取到Datatable中,然后手動(dòng)將第一行設(shè)置成標(biāo)題的);IMEX ( IMport EXport mode )設(shè)置 IMEX 有三種模式: 0 is Export mode 1 is Import mode 2 is Linked mode (full update capabilities) 我這里特別要說(shuō)明的就是 IMEX 參數(shù)了,因?yàn)椴煌哪J酱碇煌淖x寫行為: 當(dāng) IMEX=0 時(shí)

12、為“匯出模式”,這個(gè)模式開啟的 Excel 檔案只能用來(lái)做“寫入”用途。 當(dāng) IMEX=1 時(shí)為“匯入模式”,這個(gè)模式開啟的 Excel 檔案只能用來(lái)做“讀取”用途。 當(dāng) IMEX=2 時(shí)為“鏈接模式”,這個(gè)模式開啟的 Excel 檔案可同時(shí)支援“讀取”與“寫入”用途。-另外,讀取Excel2007版本的文件時(shí),版本應(yīng)該從8.0改為12.0,同時(shí)驅(qū)動(dòng)不能再用Jet,而應(yīng)該用ACE。負(fù)責(zé)會(huì)造成“找不到可安裝的 ISAM”的錯(cuò)誤。-在網(wǎng)上還發(fā)現(xiàn)采用這種方式存在取出的Sheet表的個(gè)數(shù)多于實(shí)際Excel表中的Sheet表個(gè)數(shù)的情況,其原因有二:1. 取出的名稱中,包括了XL命名管理器中的名稱(參見X

13、L2007的公式-命名管理器, 快捷鍵Crtl+F3);2. 取出的名稱中,包括了FilterDatabase后綴的, 這是XL用來(lái)記錄Filter范圍的。對(duì)于第一點(diǎn)比較簡(jiǎn)單, 刪除已有命名管理器中的內(nèi)容即可;第二點(diǎn)處理起來(lái)比較麻煩, Filter刪除后這些名稱依然保留著,簡(jiǎn)單的做法是新增Sheet然后將原Sheet Copy進(jìn)去。但實(shí)際情況并不能為每個(gè)Excel做以上檢查。下面給出了過(guò)濾的方案。(此問(wèn)題我們有驗(yàn)證過(guò),大家自己驗(yàn)證一下吧)?1234567891011121314/objConn為讀取Excel的鏈接,下面通過(guò)過(guò)濾來(lái)獲取有效的Sheet頁(yè)名稱集合 System.Data

14、.DataTable schemaTable = objConn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, null); List<string> lstSheetNames = new List<string>(); for (int i = 0; i < schemaTable.Rows.Count; i+)    string strSheetName = (string)dtSheetName.Rowsi"

15、TABLE_NAME"   if (strSheetName.Contains("$") && !strSheetName.Replace("'", "").EndsWith("$")        /過(guò)濾無(wú)效SheetName完畢.     continue;     &#

16、160;if (lstSheetNames != null && !lstSheetNames.Contains(strSheetName)     lstSheetNames.Add(strSheetName); 因?yàn)樽x取出來(lái)無(wú)效SheetName一般情況最后一個(gè)字符都不會(huì)是$。如果SheetName有一些特殊符號(hào),讀取出來(lái)的SheetName會(huì)自動(dòng)加上單引號(hào)。比如在Excel中將SheetName編輯成MySheet(1),此時(shí)讀取出來(lái)的SheetName就為:'MySheet(1)$',所以判斷最

17、后一個(gè)字符是不是$之前最好過(guò)濾一下單引號(hào)。-(2)Com組件的方式(通過(guò)添加 Microsoft.Office.Interop.Excel引用實(shí)現(xiàn))優(yōu)點(diǎn):能夠非常靈活的讀取Excel中的數(shù)據(jù),用戶可以靈活的調(diào)用各種函數(shù)進(jìn)行處理。缺點(diǎn):基于單元格的處理,讀取速度較慢,對(duì)于數(shù)據(jù)量較大的文件最好不要使用此種方式讀取。需要添加相應(yīng)的DLL引用,必須存在此引用才可使用,如果是Web站點(diǎn)部署在IIS上時(shí),還需要服務(wù)器機(jī)子已安裝了Excel,有時(shí)候還需要為配置IIS權(quán)限。讀取代碼如下:?1234567891011121314151617181920212223242526272829303132333435

18、363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561

19、57158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229private Stopwatch wath = new Stopwatch();/ <summary>/ 使用COM讀取Excel/ </sum

20、mary>/ <param name="excelFilePath">路徑</param>/ <returns>DataTabel</returns>public System.Data.DataTable GetExcelData(string excelFilePath)  Excel.Application app = new Excel.Application();  Excel.Sheets sheets;  Excel.Workbook workbo

21、ok = null;  object oMissiong = System.Reflection.Missing.Value;  System.Data.DataTable dt = new System.Data.DataTable();  wath.Start();  try      if (app = null)          return nu

22、ll;        workbook = app.Workbooks.Open(excelFilePath, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong,       oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong);  &#

23、160; /將數(shù)據(jù)讀入到DataTable中Start      sheets = workbook.Worksheets;    Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1);/讀取第一張表    if (worksheet = null)      return null;   &#

24、160;string cellContent;    int iRowCount = worksheet.UsedRange.Rows.Count;    int iColCount = worksheet.UsedRange.Columns.Count;    Excel.Range range;    /負(fù)責(zé)列頭Start    DataColumn dc;   

25、 int ColumnID = 1;    range = (Excel.Range)worksheet.Cells1, 1;    while (range.Text.ToString().Trim() != "")          dc = new DataColumn();      dc.DataType = Syst

26、em.Type.GetType("System.String");      dc.ColumnName = range.Text.ToString().Trim();      dt.Columns.Add(dc);       range = (Excel.Range)worksheet.Cells1, +ColumnID;     

27、   /End    for (int iRow = 2; iRow <= iRowCount; iRow+)          DataRow dr = dt.NewRow();      for (int iCol = 1; iCol <= iColCount; iCol+)      

28、60;       range = (Excel.Range)worksheet.CellsiRow, iCol;        cellContent = (range.Value2 = null) ? "" : range.Text.ToString();          driCol - 1 = cellContent;

29、            dt.Rows.Add(dr);        wath.Stop();    TimeSpan ts = wath.Elapsed;    /將數(shù)據(jù)讀入到DataTable中End    return dt;    

30、;catch      return null;    finally      workbook.Close(false, oMissiong, oMissiong);    System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);    workbook = null; 

31、;   app.Workbooks.Close();    app.Quit();    System.Runtime.InteropServices.Marshal.ReleaseComObject(app);    app = null;    GC.Collect();    GC.WaitForPendingFinalizers();  /

32、 <summary>/ 使用COM,多線程讀取Excel(1 主線程、4 副線程)/ </summary>/ <param name="excelFilePath">路徑</param>/ <returns>DataTabel</returns>public System.Data.DataTable ThreadReadExcel(string excelFilePath)  Excel.Application app = new Excel.Application(); 

33、; Excel.Sheets sheets = null;  Excel.Workbook workbook = null;  object oMissiong = System.Reflection.Missing.Value;  System.Data.DataTable dt = new System.Data.DataTable();  wath.Start();  try      if (app = null)&#

34、160;         return null;        workbook = app.Workbooks.Open(excelFilePath, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong,       oMissiong, oMissiong, oMissiong, oM

35、issiong, oMissiong, oMissiong, oMissiong, oMissiong);    /將數(shù)據(jù)讀入到DataTable中Start      sheets = workbook.Worksheets;    Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1);/讀取第一張表    if (worksheet = null)&

36、#160;     return null;    string cellContent;    int iRowCount = worksheet.UsedRange.Rows.Count;    int iColCount = worksheet.UsedRange.Columns.Count;    Excel.Range range;    

37、;/負(fù)責(zé)列頭Start    DataColumn dc;    int ColumnID = 1;    range = (Excel.Range)worksheet.Cells1, 1;    while (iColCount >= ColumnID)          dc = new DataColumn(); &

38、#160;    dc.DataType = System.Type.GetType("System.String");      string strNewColumnName = range.Text.ToString().Trim();      if (strNewColumnName.Length = 0) strNewColumnName = "_1"   

39、;   /判斷列名是否重復(fù)      for (int i = 1; i < ColumnID; i+)              if (dt.Columnsi - 1.ColumnName = strNewColumnName)          strNew

40、ColumnName = strNewColumnName + "_1"            dc.ColumnName = strNewColumnName;      dt.Columns.Add(dc);      range = (Excel.Range)worksheet.Cells1, +ColumnID; 

41、60;      /End    /數(shù)據(jù)大于500條,使用多進(jìn)程進(jìn)行讀取數(shù)據(jù)    if (iRowCount - 1 > 500)          /開始多線程讀取數(shù)據(jù)      /新建線程      int b2 = (iRow

42、Count - 1) / 10;      DataTable dt1 = new DataTable("dt1");      dt1 = dt.Clone();      SheetOptions sheet1thread = new SheetOptions(worksheet, iColCount, 2, b2 + 1, dt1);     

43、; Thread othread1 = new Thread(new ThreadStart(sheet1thread.SheetToDataTable);      othread1.Start();      /阻塞 1 毫秒,保證第一個(gè)讀取 dt1      Thread.Sleep(1);      DataTable dt2 = new

44、DataTable("dt2");      dt2 = dt.Clone();      SheetOptions sheet2thread = new SheetOptions(worksheet, iColCount, b2 + 2, b2 * 2 + 1, dt2);      Thread othread2 = new Thread(new ThreadStart(sheet2threa

45、d.SheetToDataTable);      othread2.Start();      DataTable dt3 = new DataTable("dt3");      dt3 = dt.Clone();      SheetOptions sheet3thread = new SheetOptions(worksheet,

46、 iColCount, b2 * 2 + 2, b2 * 3 + 1, dt3);      Thread othread3 = new Thread(new ThreadStart(sheet3thread.SheetToDataTable);      othread3.Start();      DataTable dt4 = new DataTable("dt4");  

47、;    dt4 = dt.Clone();      SheetOptions sheet4thread = new SheetOptions(worksheet, iColCount, b2 * 3 + 2, b2 * 4 + 1, dt4);      Thread othread4 = new Thread(new ThreadStart(sheet4thread.SheetToDataTable);  &#

48、160;   othread4.Start();      /主線程讀取剩余數(shù)據(jù)      for (int iRow = b2 * 4 + 2; iRow <= iRowCount; iRow+)              DataRow dr = dt.NewRow();  &#

49、160;     for (int iCol = 1; iCol <= iColCount; iCol+)                  range = (Excel.Range)worksheet.CellsiRow, iCol;          cell

50、Content = (range.Value2 = null) ? "" : range.Text.ToString();          driCol - 1 = cellContent;                dt.Rows.Add(dr);     &#

51、160;      othread1.Join();      othread2.Join();      othread3.Join();      othread4.Join();      /將多個(gè)線程讀取出來(lái)的數(shù)據(jù)追加至 dt1 后面     

52、; foreach (DataRow dr in dt.Rows)        dt1.Rows.Add(dr.ItemArray);      dt.Clear();      dt.Dispose();      foreach (DataRow dr in dt2.Rows)    

53、;    dt1.Rows.Add(dr.ItemArray);      dt2.Clear();      dt2.Dispose();      foreach (DataRow dr in dt3.Rows)        dt1.Rows.Add(dr.ItemArray); &

54、#160;    dt3.Clear();      dt3.Dispose();      foreach (DataRow dr in dt4.Rows)        dt1.Rows.Add(dr.ItemArray);      dt4.Clear();   

55、   dt4.Dispose();      return dt1;        else          for (int iRow = 2; iRow <= iRowCount; iRow+)          &#

56、160;   DataRow dr = dt.NewRow();        for (int iCol = 1; iCol <= iColCount; iCol+)                  range = (Excel.Range)worksheet.CellsiRow, iCol;

57、60;         cellContent = (range.Value2 = null) ? "" : range.Text.ToString();          driCol - 1 = cellContent;              

58、;  dt.Rows.Add(dr);              wath.Stop();    TimeSpan ts = wath.Elapsed;    /將數(shù)據(jù)讀入到DataTable中End    return dt;    catch   

59、;   return null;    finally      workbook.Close(false, oMissiong, oMissiong);    System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);    System.Runtime.InteropServices.Marshal.Relea

60、seComObject(sheets);    workbook = null;    app.Workbooks.Close();    app.Quit();    System.Runtime.InteropServices.Marshal.ReleaseComObject(app);    app = null;    GC.Collect();&#

61、160;   GC.WaitForPendingFinalizers();  (3)NPOI方式讀取Excel(此方法未經(jīng)過(guò)測(cè)試)NPOI 是 POI 項(xiàng)目的 .NET 版本。POI是一個(gè)開源的Java讀寫Excel、WORD等微軟OLE2組件文檔的項(xiàng)目。使用 NPOI 你就可以在沒(méi)有安裝 Office 或者相應(yīng)環(huán)境的機(jī)器上對(duì) WORD/EXCEL 文檔進(jìn)行讀寫。優(yōu)點(diǎn):讀取Excel速度較快,讀取方式操作靈活性缺點(diǎn):需要下載相應(yīng)的插件并添加到系統(tǒng)引用當(dāng)中。?12345678910111213141516171819202122232425262

62、728293031323334353637383940414243444546474849505152535455565758596061626364656667/ <summary>/ 將excel中的數(shù)據(jù)導(dǎo)入到DataTable中/ </summary>/ <param name="sheetName">excel工作薄sheet的名稱</param>/ <param name="isFirstRowColumn">第一行是否是DataTable的列名</param>/ <

63、returns>返回的DataTable</returns>public DataTable ExcelToDataTable(string sheetName, bool isFirstRowColumn)  ISheet sheet = null;  DataTable data = new DataTable();  int startRow = 0;  try      fs = new FileStream(fileName,

64、FileMode.Open, FileAccess.Read);    if (fileName.IndexOf(".xlsx") > 0) / 2007版本      workbook = new XSSFWorkbook(fs);    else if (fileName.IndexOf(".xls") > 0) / 2003版本      

65、workbook = new HSSFWorkbook(fs);    if (sheetName != null)          sheet = workbook.GetSheet(sheetName);        else          sheet = workbook.GetSheetAt(0);        if (sheet != null)          IRow firstRow = sheet.GetRow(0);     

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論