/// <summary> /// 按照給定的Excel流組織成Datatable /// </summary> /// <param name="stream">Excel文件流</param> /// <param name="sheetName">須要讀取的Sheet</param> /// <returns>組織好的DataTable</returns> private DataTable ReadExcel(string sheetName, Stream stream) { using (SpreadsheetDocument document = SpreadsheetDocument.Open(stream, false)) {//打開Stream IEnumerable<Sheet> sheets = document.WorkbookPart.Workbook.Descendants<Sheet>().Where(s => s.Name == sheetName); if (sheets.Count() == 0) {//找出合適前提的sheet,沒有則返回 return null; } WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(sheets.First().Id); //獲取Excel中共享數據 SharedStringTable stringTable = document.WorkbookPart.SharedStringTablePart.SharedStringTable; IEnumerable<Row> rows = worksheetPart.Worksheet.Descendants<Row>();//獲得Excel中得數據行 DataTable dt = new DataTable("Excel"); //因為須要將數據導入到DataTable中,所以我們假定Excel的第一行是列名,從第二行開端是行數據 foreach (Row row in rows) { if (row.RowIndex == 1) {//Excel第一行動列名 GetDataColumn(row, stringTable, ref dt); } else GetDataRow(row, stringTable, ref dt);//Excel第二行同時為DataTable的第一行數據 } return dt; } } /// <summary> /// 構建DataTable的列 /// </summary> /// <param name="row">OpenXML定義的Row對象</param> /// <param name="stringTablePart"></param> /// <param name="dt">須要返回的DataTable對象</param> /// <returns></returns> public void GetDataColumn(Row row, SharedStringTable stringTable, ref DataTable dt) { DataColumn col = new DataColumn(); Dictionary<string, int> columnCount = new Dictionary<string, int>(); foreach (Cell cell in row) { string cellVal = GetValue(cell, stringTable); col = new DataColumn(cellVal); if (IsContainsColumn(dt, col.ColumnName)) { if(!columnCount.ContainsKey(col.ColumnName)) columnCount.Add(col.ColumnName, 0); col.ColumnName = col.ColumnName + (columnCount[col.ColumnName]++); } dt.Columns.Add(col); } } /// <summary> /// 構建DataTable的每一行數據,並返回該Datatable /// </summary> /// <param name="row">OpenXML的行</param> /// <param name="stringTablePart"></param> /// <param name="dt">DataTable</param> private void GetDataRow(Row row, SharedStringTable stringTable, ref DataTable dt) { // 讀取算法:按行一一讀取單位格,若是整行均是空數據 // 則忽視改行(因為本人的工作內容不須要空行)-_- DataRow dr = dt.NewRow(); int i = 0; int nullRowCount = i; foreach (Cell cell in row) { string cellVal = GetValue(cell, stringTable); if (cellVal == string.Empty) { nullRowCount++; } dr[i] = cellVal; i++; } if (nullRowCount != i) { dt.Rows.Add(dr); } } /// <summary> /// 獲取單位格的值 /// </summary> /// <param name="cell"></param> /// <param name="stringTablePart"></param> /// <returns></returns> private string GetValue(Cell cell, SharedStringTable stringTable) { //因為Excel的數據存儲在SharedStringTable中,須要獲取數據在SharedStringTable 中的索引 string value = string.Empty; try { if (cell.ChildElements.Count == 0) return value; value = double.Parse(cell.CellValue.InnerText).ToString(); if ((cell.DataType != null) && (cell.DataType == CellValues.SharedString)) { value = stringTable.ChildElements[Int32.Parse(value)].InnerText; } } catch (Exception) { value = "N/A"; } return value; } /// <summary> /// 判斷網格是否存在列 /// </summary> /// <param name="dt">網格</param> /// <param name="columnName">列名</param> /// <returns></returns> public bool IsContainsColumn(DataTable dt, string columnName) { if (dt == null || columnName == null) { return false; } return dt.Columns.Contains(columnName); }
前言:前面的幾篇文章簡單的介紹了如何使用OpenXML創建Excel文檔。由於在平時的工作中需要經常使用到Excel的讀寫操作,簡單的介紹下使用OpenXML讀取Excel中得數據。當然使用OpenXML將數據讀取成什么格式並不重要,本文僅僅介紹如何讀取到DataTable中。
准備工作:
1. Excel2007文檔一個;
2. OpenXML庫:DocumentFormat.OpenXml.dll;
3. Console項目一個,添加對OpenXML庫和WindowsBase.dll的引用。
廢話不多說,進入正題.
本文介紹的讀取Excel的思路如下:
1. 將Excel加載到流Stream;
2. 使用OpenXML操作Stream,並寫入DataTable中。
將文件加載到Stream中有很多種方式,這里就不贅述,本文主要介紹第二步。
使用:

1 FileStream fs =
new FileStream(
@"
D:\工作簿1.xlsx
", FileMode.Open, FileAccess.Read, FileShare.Read);
2 DataTable dt=ReadExcel( " Sheet1 ",fs);
2 DataTable dt=ReadExcel( " Sheet1 ",fs);