1. 程式人生 > >C#讀取Excel幾種方法的體會

C#讀取Excel幾種方法的體會

(1) OleDb: 用這種方法讀取Excel速度還是非常的快的,但這種方式讀取資料的時候不太靈活,不過可以在 DataTable 中對資料進行一些刪減修改

這種方式將Excel作為一個數據源,直接用Sql語句獲取資料了。所以讀取之前要知道此次要讀取的Sheet(當然也可以用序號,類似dt.Row[0][0]。這樣倒是不需要知道Sheet)

?
if (fileType == ".xls") connStr = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + fileName + ";"
+ ";Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1\""; else connStr = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + fileName + ";" + ";Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\""; OleDbConnection conn new OleDbConnection(connStr); DataTable dtSheetName = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables,
new object[] { null, null, null, "TABLE" });

以上是讀取Excel的Sheet名,xls和xlsx的連線字串也不一樣的,可以根據檔案的字尾來區別。這裡需要注意的一點,Excel裡面只有一個Sheet,但通過這種方式讀取Sheet可能會大於一個。原因已經有人在別的網站說過了,偷一下懶O(∩_∩)O,下面文段來自【cdwolfling

【在使用過程中發現取出的Sheet和實際excel不一致, 會多出不少。目前總結後有兩種情況:

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

對於第一點比較簡單, 刪除已有命名管理器中的內容即可;第二點處理起來比較麻煩, Filter刪除後這些名稱依然保留著,簡單的做法是新增sheet然後將原sheet Copy進去】

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

但實際情況並不能為每個Excel做以上檢查,【cdwolfling】也給出了過濾的方案,當時還是有點問題,本來補充了一點。總之先看程式碼吧

for (int i = 0; i < dtSheetName.Rows.Count; i++)

{

?
SheetName = (string)dtSheetName.Rows[i]["TABLE_NAME"]; if (SheetName .Contains("$") && !SheetName .Replace("'", "").EndsWith("$"))continue;//過濾無效SheetName完畢....

da.SelectCommand = new OleDbCommand(String.Format(sql_F, tblName), conn);
DataSet dsItem = new DataSet();
da.Fill(dsItem, tblName);

?
}

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

優點:讀取方式簡單、讀取速度快

缺點:除了讀取過程不太靈活之外,這種讀取方式還有個弊端就是,當Excel資料量很大時。會非常佔用記憶體,當記憶體不夠時會丟擲記憶體溢位的異常。

不過一般情況下還是非常不錯的

 讀取Excel完整程式碼:

?
/// <summary> /// 讀取Excel檔案到DataSet中 /// </summary> /// <param name="filePath">檔案路徑</param> /// <returns></returns> public static DataSet ToDataTable(string filePath) { string connStr = "";            string fileType = System.IO.Path.GetExtension(fileName); if (string.IsNullOrEmpty(fileType)) return null; if (fileType == ".xls") connStr = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + filePath+ ";" + ";Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1\""; else connStr = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + filePath+ ";" + ";Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\""; string sql_F = "Select * FROM [{0}]"; OleDbConnection conn = null; OleDbDataAdapter da = null; DataTable dtSheetName= null; DataSet ds = new DataSet(); try { // 初始化連線,並開啟 conn = new OleDbConnection(connStr); conn.Open(); // 獲取資料來源的表定義元資料                        string SheetName = ""; dtSheetName= conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" }); // 初始化介面卡 da = new OleDbDataAdapter(); for (int i = 0; i < dtSheetName.Rows.Count; i++) { SheetName = (string)dtSheetName.Rows[i]["TABLE_NAME"]; if (SheetName .Contains("$") && !SheetName .Replace("'", "").EndsWith("$")) { continue; } da.SelectCommand = new OleDbCommand(String.Format(sql_F, SheetName ), conn); DataSet dsItem = new DataSet(); da.Fill(dsItem, tblName); ds.Tables.Add(dsItem.Tables[0].Copy()); } } catch (Exception ex) { } finally { // 關閉連線 if (conn.State == ConnectionState.Open) { conn.Close(); da.Dispose(); conn.Dispose(); } } return ds; }

(2):Com元件的方式讀取Excel

這種方式需要先引用 Microsoft.Office.Interop.Excel 。首選說下這種方式的優缺點

優點:可以非常靈活的讀取Excel中的資料

缺點:如果是Web站點部署在IIS上時,還需要伺服器機子已安裝了Excel,有時候還需要為配置IIS許可權。最重要的一點因為是基於單元格方式讀取的,所以資料很慢(曾做過試驗,直接讀取千行、200多列的檔案,直接讀取耗時15分鐘。即使採用多執行緒分段讀取來提高CPU的利用率也需要8分鐘。PS:CPU I3)

需要讀取大檔案的的童鞋們慎重。。。

附上單執行緒和多執行緒讀取類:

?
public class ExcelOptions { private Stopwatch wath = new Stopwatch(); /// <summary> /// 使用COM讀取Excel /// </summary> /// <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 workbook = null; object oMissiong = System.Reflection.Missing.Value; System.Data.DataTable dt = new System.Data.DataTable(); wath.Start(); try { if (app == null) { return null; } workbook = app.Workbooks.Open(excelFilePath, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong); //將資料讀入到DataTable中——Start   sheets = workbook.Worksheets; Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1);//讀取第一張表 if (worksheet == null) return null; string cellContent; int iRowCount = worksheet.UsedRange.Rows.Count; int iColCount = worksheet.UsedRange.Columns.Count; Excel.Range range; //負責列頭Start DataColumn dc; int ColumnID = 1; range = (Excel.Range)worksheet.Cells[1, 1]; while (range.Text.ToString().Trim() != "") { dc = new DataColumn(); dc.DataType = System.Type.GetType("System.String"); dc.ColumnName = range.Text.ToString().Trim(); dt.Columns.Add(dc); range = (Excel.Range)worksheet.Cells[1, ++ColumnID]; } //End for (int iRow = 2; iRow <= iRowCount; iRow++) { DataRow dr = dt.NewRow(); for (int iCol = 1; iCol <= iColCount; iCol++) { range = (Excel.Range)worksheet.Cells[iRow, iCol]; cellContent = (range.Value2 == null) ? "" : range.Text.ToString(); //if (iRow == 1) //{ //    dt.Columns.Add(cellContent); //} //else //{ dr[iCol - 1] = cellContent; //} } //if (iRow != 1) dt.Rows.Add(dr); } wath.Stop(); TimeSpan ts = wath.Elapsed; //將資料讀入到DataTable中——End return dt; } catch { return null; } finally { workbook.Close(false, oMissiong, oMissiong); System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook); workbook = null; app.Workbooks.Close(); app.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(app); app = null; GC.Collect(); GC.WaitForPendingFinalizers(); } } /// <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(); 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) { return null; } workbook = app.Workbooks.Open(excelFilePath, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong); //將資料讀入到DataTable中——Start   sheets = workbook.Worksheets; Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1);//讀取第一張表 if (worksheet == null) return null; string cellContent; int iRowCount = worksheet.UsedRange.Rows.Count; int iColCount = worksheet.UsedRange.Columns.Count; Excel.Range range; //負責列頭Start DataColumn dc; int ColumnID = 1; range = (Excel.Range)worksheet.Cells[1, 1]; //while (range.Text.ToString().Trim() != "") while (iColCount >= ColumnID) { dc = new DataColumn(); dc.DataType = System.Type.GetType("System.String"); string strNewColumnName = range.Text.ToString().Trim(); if (strNewColumnName.Length == 0) strNewColumnName = "_1"; //判斷列名是否重複 for (int i = 1; i < ColumnID; i++) { if (dt.Columns[i - 1].ColumnName == strNewColumnName) strNewColumnName = strNewColumnName + "_1"; } dc.ColumnName = strNewColumnName; dt.Columns.Add(dc); range = (Excel.Range)worksheet.Cells[1, ++ColumnID]; } //End //資料大於500條,使用多程序進行讀取資料 if (iRowCount - 1 > 500) { //開始多執行緒讀取資料 //新建執行緒 int b2 = (iRowCount - 1) / 10; DataTable dt1 = new DataTable("dt1"); dt1 = dt.Clone(); SheetOptions sheet1thread = new SheetOptions(worksheet, iColCount, 2, b2 + 1, dt1); Thread othread1 = new Thread(new ThreadStart(sheet1thread.SheetToDataTable)); othread1.Start(); //阻塞 1 毫秒,保證第一個讀取 dt1 Thread.Sleep(1); DataTable dt2 = new DataTable("dt2"); dt2 = dt.Clone(); SheetOptions sheet2thread = new SheetOptions(worksheet, iColCount, b2 + 2, b2 * 2 + 1, dt2); Thread othread2 = new Thread(new ThreadStart(sheet2thread.SheetToDataTable)); othread2.Start(); DataTable dt3 = new DataTable("dt3"); dt3 = dt.Clone(); SheetOptions sheet3thread = new SheetOptions(worksheet, iColCount, b2 * 2 + 2, b2 * 3 + 1, dt3); Thread othread3 = new Thread(new ThreadStart(sheet3thread.SheetToDataTable)); othread3.Start(); DataTable dt4 = new DataTable("dt4"); dt4 = dt.Clone(); SheetOptions sheet4thread = new SheetOptions(worksheet, iColCount, b2 * 3 + 2, b2 * 4 + 1, dt4); Thread othread4 = new Thread(new ThreadStart(sheet4thread.SheetToDataTable)); othread4.Start(); //主執行緒讀取剩餘資料 for (int iRow = b2 * 4 + 2; iRow <= iRowCount; iRow++) { DataRow dr = dt.NewRow(); for (int iCol = 1; iCol <= iColCount; iCol++) { range = (Excel.Range)worksheet.Cells[iRow, iCol]; cellContent = (range.Value2 == null) ? "" : range.Text.ToString(); dr[iCol - 1] = cellContent; } dt.Rows.Add(dr); } othread1.Join(); othread2.Join(); othread3.Join(); othread4.Join(); //將多個執行緒讀取出來的資料追加至 dt1 後面 foreach (DataRow dr in dt.Rows) dt1.Rows.Add(dr.ItemArray); dt.Clear(); dt.Dispose(); foreach (DataRow dr in dt2.Rows) dt1.Rows.Add(dr.ItemArray); dt2.Clear(); dt2.Dispose(); foreach (DataRow dr in dt3.Rows) dt1.Rows.Add(dr.ItemArray); dt3.Clear(); dt3.Dispose(); foreach (DataRow dr in dt4.Rows) dt1.Rows.Add(dr.ItemArray); dt4.Clear(); dt4.Dispose(); return dt1; } else { for (int iRow = 2; iRow <= iRowCount; iRow++) { DataRow dr = dt.NewRow(); for (int iCol = 1; iCol <= iColCount; iCol++) { range = (Excel.Range)worksheet.Cells[iRow, iCol]; cellContent = (range.Value2 == null) ? "" : range.Text.ToString(); dr[iCol - 1] = cellContent; } dt.Rows.Add(dr); } } wath.Stop(); TimeSpan ts = wath.Elapsed; //將資料讀入到DataTable中——End return dt; } catch { return null; } finally { workbook.Close(false, oMissiong, oMissiong); System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook); System.Runtime.InteropServices.Marshal.ReleaseComObject(sheets); workbook = null; app.Workbooks.Close(); app.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(app); app = null; GC.Collect(); GC.WaitForPendingFinalizers(); /* object objmissing = System.Reflection.Missing.Value; Excel.ApplicationClass application = new ApplicationClass(); Excel.Workbook book = application.Workbooks.Add(objmissing); Excel.Worksheet sheet = (Excel.Worksheet)book.Worksheets.Add(objmissing,objmissing,objmissing,objmissing); //操作過程 ^&%&×&……&%&&…… //釋放 sheet.SaveAs(path,objmissing,objmissing,objmissing,objmissing,objmissing,objmissing,objmissing,objmissing); System.Runtime.InteropServices.Marshal.ReleaseComObject((object)sheet); System.Runtime.InteropServices.Marshal.ReleaseComObject((object)book); application.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject((object)application); System.GC.Collect(); */ } } /// <summary> /// 刪除Excel行 /// </summary> /// <param name="excelFilePath">Excel路徑</param> /// <param name="rowStart">開始行</param> /// <param name="rowEnd">結束行</param> /// <param name="designationRow">指定行</param> /// <returns></returns> public string DeleteRows(string excelFilePath, int rowStart, int rowEnd, int designationRow) { string result = ""; Excel.Application app = new Excel.Application(); Excel.Sheets sheets; Excel.Workbook workbook = null; object oMissiong = System.Reflection.Missing.Value; try { if (app == null) { return "分段讀取Excel失敗"; } workbook = app.Workbooks.Open(excelFilePath, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong); sheets = workbook.Worksheets; Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1);//讀取第一張表 if (worksheet == null) return result; Excel.Range range; //先刪除指定行,一般為列描述 if (designationRow != -1) { range = (Excel.Range)worksheet.Rows[designationRow, oMissiong]; range.Delete(Excel.XlDeleteShiftDirection.xlShiftUp); } Stopwatch sw = new Stopwatch(); sw.Start(); int i = rowStart; for (int iRow = rowStart; iRow <= rowEnd; iRow++, i++) { range = (Excel.Range)worksheet.Rows[rowStart, oMissiong]; range.Delete(Excel.XlDeleteShiftDirection.xlShiftUp); } sw.Stop(); TimeSpan ts = sw.Elapsed; workbook.Save(); //將資料讀入到DataTable中——End return result; } catch { return "分段讀取Excel失敗"; } finally { workbook.Close(false, oMissiong, oMissiong); System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook); workbook = null; app.Workbooks.Close(); app.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(app); app = null; GC.Collect(); GC.WaitForPendingFinalizers(); } } public void ToExcelSheet(DataSet ds, string fileName) { Excel.Application appExcel = new Excel.Application(); Excel.Workbook workbookData = null; Excel.Worksheet worksheetData; Excel.Range range; try { workbookData = appExcel.Workbooks.Add(System.Reflection.Missing.Value); appExcel.DisplayAlerts = false;//不顯示警告 //xlApp.Visible = true;//excel是否可見 // //for (int i = workbookData.Worksheets.Count; i > 0; i--) //{ //    Microsoft.Office.Interop.Excel.Worksheet oWorksheet = (Microsoft.Office.Interop.Excel.Worksheet)workbookData.Worksheets.get_Item(i); //    oWorksheet.Select(); //    oWorksheet.Delete(); //} for (int k = 0; k < ds.Tables.Count; k++) { worksheetData = (Excel.Worksheet)workbookData.Worksheets.Add(System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value); // testnum--; if (ds.Tables[k] != null) {

相關推薦

C#讀取Excel方法體會

(1) OleDb: 用這種方法讀取Excel速度還是非常的快的,但這種方式讀取資料的時候不太靈活,不過可以在 DataTable 中對資料進行一些刪減修改 這種方式將Excel作為一個數據源,直接用Sql語句獲取資料了。所以讀取之前要知道此次要讀取的Sheet(當然也可以用序號,類似dt.Row[0]

C#讀取Excel方式及比較

1、OleDb方式 優點:把excel檔案當做一個數據源,利用sql來進行資料的讀取操作 缺點:不能讀取到某一個單元格 注:這個方法我沒有進行過實驗。故具體程式碼無法展示給大家 2、COM元件(即新增Microsoft.Office.Interop.Excel引用) 優點:

Linux Ubuntu 下編譯Opencv c++專案的方法

Table of Contents 4.瞭解 1.使用g++命令列 pkg-config引數方法 新建一個cpp檔案:main.cpp,功能是輸入一幅影象檔案的路徑並顯示該影象: #include<opencv2/opencv.hpp>

C語言從stdin讀取一行字串的方法

C語言從stdin讀取一行字串的幾種方法 gets gets函式的標頭檔案是<stdio.h>,原型如下: char *gets(char *s); gets從stdin中讀入一行內容到s指定的buffer中,當遇到換行符或EOF時讀取結束。讀取成功時,返

C#讀取路徑的方法

//獲取包含清單的已載入檔案的路徑或 UNC 位置。        public static string sApplicationPath = Assembly.GetExecutingAssembly ().Location;        //result: X:

C#讀取網絡卡地址的方法

 轉自:http://www.cnblogs.com/diulela/archive/2012/04/07/2436111.html  以下是收集的幾種C#程式讀取MAC地址的方法,示例中是讀取所有網絡卡的MAC地址,如果僅需要讀取其中一個,稍作修改即可。 1 通過IPCo

c#匯出Excel檔案的方法

using System; using System.Collections.Generic; using System.Text; using System.Data; using System.Windows.Forms; using System.Re

C++讀取配置檔案的方法

ini檔案的話讀取更方便點。C++中有寫ini檔案和讀ini檔案的函式(應該是VC環境提供的,標準C++沒有。)windows下就直接用函式讀取ini檔案 看的你配置檔案是什麼型別了,如果是xml檔案的話,可以用TinyXML解析器去解析,看這裡:http://www.c

C#由DataSet匯出Excel檔案的方法

裡面的方法很多。 我只成功運行了下面四種(稍作修改並添加了一些總結),其他的方法,沒能成功執行。 不過感興趣的可以看一下,因為即使不能執行(不能執行的原因有很多,差一點都不行),其思路還是值得參考學習的。 //法一 private void ToExcel(Da

C#多線程的方法

task start invoke 數組 erl method 並行計算 bsp nbsp 1、Theard2、TheardPool 線程池3、Task 在Theard上做了優化和改進,建議使用 .start();4、Task.Factory.Start(method)

C#啟動外部程序以及等待外部程序關閉的方法

string C# main 無限 完成 nbsp text enable geb 1. 啟動外部程序,不等待其退出。 2. 啟動外部程序,等待其退出。 3. 啟動外部程序,無限等待其退出。 4. 啟動外部程序,通過事件監視其退出。 // using Sy

C#中實現並發的方法的性能測試

返回 也不會 thead syn image 9.png 結果 次數 存在 原文地址:https://www.cnblogs.com/durow/p/4837746.html 0x00 起因 去年寫的一個程序因為需要在局域網發送消息支持一些命令和簡單數據的傳輸,所以寫了

c#除掉字符串最後一個字符方法

要去 參數 aaa style log int print mov www 有一數組;轉換為字符串後為 aaa|bbb|ccc|ddd|現要去掉最後一個|第一種方法:語句為:str1=aaa|bbb|ccc|ddd|str=str1.substring(0,lastinde

C# 移動分分彩平臺搭建無標題欄窗體的方法

msdn sage pro 使用 protected wpa 方便 sdn cap 第一種,手工分分彩平臺搭建論壇:haozbbs.com Q1446595067 移動。 該方法根據鼠標位置實現窗體的移動。網上有很多相關的例子,這裏不再多講。 第二種,調用系統API原理:是

C#線程同步的方法

sso 代碼 services 讀寫 基於 star 代碼段 不能 命名   在網上也看過一些關於線程同步的文章,其實線程同步有好幾種方法,下面我就簡單的做一下歸納。   一、volatile關鍵字   volatile是最簡單的一種同步方法,當然簡單是要付出代價的。它

C#獲取當前路徑的方法

size start orm name uri path ant tom 當前 //1.獲取模塊的完整路徑。 string path1 = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileNam

python os 設定讀取環境變數的方法

專案中的跳板機是用的使用者公私鑰鑑權的,登入跳板機需要使用的每個人的name,因此如果將封裝的MySQL或者Redis方法中傳入USERNAME作為引數的話,感覺有點傻。因此,考慮將名字寫入環境變數。 兩種方法: 1、使用os.environ.setdefault方法寫入(或者直接

求組合數C(n,m) % mod的方法

演算法一:乘法逆元,在m,n和mod比較小的情況下適用 乘法逆元:(a/b)% mod = a * b^(mod-2),mod為素數   #include<iostream> #include<cstdio> #include<cmath>

歸納一下:C#執行緒同步的方法

 我們在程式設計的時候,有時會使用多執行緒來解決問題,比如你的程式需要在後臺處理一大堆資料,但還要使使用者介面處於可操作狀態;或者你的程式需要訪問一些外部資源如資料庫或網路檔案等。這些情況你都可以建立一個子執行緒去處理,然而,多執行緒不可避免地會帶來一個問題,就是執行緒同步的問題。如果這個問題處理不好,我們就

[轉]C/C++定義全域性變數/常量方法的區別

在討論全域性變數之前我們先要明白幾個基本的概念: 原文章地址:https://www.cnblogs.com/wanghetao/p/4492582.html 1. 編譯單元(模組):     在IDE開發工具大行其道的今天,