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

為江川等地區(qū)用戶提供了全套網(wǎng)頁設計制作服務,及江川網(wǎng)站建設行業(yè)解決方案。主營業(yè)務為成都做網(wǎng)站、網(wǎng)站設計、江川網(wǎng)站設計,以傳統(tǒng)方式定制建設網(wǎng)站,并提供域名空間備案等一條龍服務,秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務。我們深信只要達到每一位用戶的要求,就會得到認可,從而選擇與我們長期合作。這樣,我們也可以走得更遠!
這種方式將Excel作為一個數(shù)據(jù)源,直接用Sql語句獲取數(shù)據(jù)了。所以讀取之前要知道此次要讀取的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的連接字符串也不一樣的,可以根據(jù)文件的后綴來區(qū)別。這里需要注意的一點,Excel里面只有一個Sheet,但通過這種方式讀取Sheet可能會大于一個。原因已經(jīng)有人在別的網(wǎng)站說過了,偷一下懶O(∩_∩)O,下面文段來自【cdwolfling】
【在使用過程中發(fā)現(xiàn)取出的Sheet和實際excel不一致, 會多出不少。目前總結后有兩種情況:
1. 取出的名稱中,包括了XL命名管理器中的名稱(參見XL2007的公式--命名管理器, 快捷鍵Crtl+F3);
2. 取出的名稱中,包括了FilterDatabase后綴的, 這是XL用來記錄Filter范圍的, 參見http://www.mrexcel.com/forum/showthread.php?t=27225;
對于***點比較簡單, 刪除已有命名管理器中的內(nèi)容即可;第二點處理起來比較麻煩, Filter刪除后這些名稱依然保留著,簡單的做法是新增sheet然后將原sheet Copy進去】
---------------------------------
但實際情況并不能為每個Excel做以上檢查【cdwolfling】也給出了過濾的方案,當時還是有點問題,本來補充了一點??傊瓤创a吧
- 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)$',所以判斷***一個字符是不是$之前***過濾一下單引號。
優(yōu)點:讀取方式簡單、讀取速度快
缺點:除了讀取過程不太靈活之外,這種讀取方式還有個弊端就是,當Excel數(shù)據(jù)量很大時。會非常占用內(nèi)存,當內(nèi)存不夠時會拋出內(nèi)存溢出的異常。
不過一般情況下還是非常不錯的
讀取Excel完整代碼:
- ///
- /// 讀取Excel文件到DataSet中
- ///
- /// 文件路徑
- ///
- 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();
- // 獲取數(shù)據(jù)源的表定義元數(shù)據(jù)
- 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;
- }
#p#
(2):Com組件的方式讀取Excel
這種方式需要先引用 Microsoft.Office.Interop.Excel 。***說下這種方式的優(yōu)缺點
優(yōu)點:可以非常靈活的讀取Excel中的數(shù)據(jù)
缺點:如果是Web站點部署在IIS上時,還需要服務器機子已安裝了Excel,有時候還需要為配置IIS權限。最重要的一點因為是基于單元格方式讀取的,所以數(shù)據(jù)很慢(曾做過試驗,直接讀取千行、200多列的文件,直接讀取耗時15分鐘。即使采用多線程分段讀取來提高CPU的利用率也需要8分鐘。PS:CPU I3)
需要讀取大文件的的童鞋們慎重。
附上單線程和多線程讀取類:
- public class ExcelOptions
- {
- private Stopwatch wath = new Stopwatch();
- ///
- /// 使用COM讀取Excel
- ///
- /// 路徑
- ///
DataTabel - 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);
- //將數(shù)據(jù)讀入到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;
- //將數(shù)據(jù)讀入到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();
- }
- }
- ///
- /// 使用COM,多線程讀取Excel(1 主線程、4 副線程)
- ///
- /// 路徑
- ///
DataTabel - 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);
- //將數(shù)據(jù)讀入到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
- //數(shù)據(jù)大于500條,使用多進程進行讀取數(shù)據(jù)
- if (iRowCount - 1 > 500)
- {
- //開始多線程讀取數(shù)據(jù)
- //新建線程
- 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();
- //主線程讀取剩余數(shù)據(jù)
- 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();
- //將多個線程讀取出來的數(shù)據(jù)追加至 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;
- //將數(shù)據(jù)讀入到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;
-  
分享名稱:C#讀取Excel幾種方法的體會
文章起源:http://fisionsoft.com.cn/article/dpidsgg.html


咨詢
建站咨詢
