C#讀取Excel幾種方法的體會
轉載地址:http://developer.51cto.com/art/201302/380622.htm
(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);
2. 取出的名稱中,包括了FilterDatabase後綴的, 這是XL用來記錄Filter範圍的, 參見http://www.mrexcel.com/forum/showthread.php?t=27225;
對於第一點比較簡單, 刪除已有命名管理器中的內容即可;第二點處理起來比較麻煩, 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;
- }