使用NPOI讀取Excel數據到DataTable
阿新 • • 發佈:2017-05-06
交換 tac sin 沒有 != region csharp edi XML
調用的方法例如以下:
如今XML文件的存儲格式大行其道,可是也不是適用於全部情況,非常多單位的數據交換還是使用Excel的形式。這就使得我們須要讀取Excel內的數據。載入到程序中進行處理。可是如何有效率的讀取,如何使程序保持健壯,這須要非常大的努力。
我們假設要寫一個動態鏈接庫會非常花費時間和精力。這就使得開源項目是個非常有效率的選擇。
在各類關於Excel的開源項目中NPOI是中國的程序猿發起的。他的一大優點是直接處理Ole文件,用戶不必安裝Office。如今發展到2.0還能夠自己主動推斷Excel文件版本號,我們自己推斷文件後綴名的方式不是非常準確(用戶可能自己更改)。我認為對於讀取文件這個是非常方便的一個功能!
不足之處:對於大文件的讀取速度還是有些慢,做了下測試,載入20W數據。大約10+M的Excel文件大約須要16S。轉化數據須要6S,這個略微有些慢。讀取文件流的地方還應該能夠優化。
好了,廢話少說,一下是我自己寫的一個使用NPOI讀取Excel數據的幫助類
using System; using System.Collections.Generic; using System.Data; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Threading; using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; namespace Vevisoft.Excel.Core { /// <summary> /// 使用NOPI讀取Excel數據 /// </summary> public class ExcelImportCore { private IWorkbook _workbook; private string _filePath; public List<string> SheetNames { get; set; } public ExcelImportCore() { SheetNames = new List<string>(); //LoadFile(_filePath); } #region Excel信息 /// <summary> /// 獲取Excel信息 /// </summary> /// <param name="filePath"></param> public List<string> LoadFile(string filePath) { var prevCulture = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; var stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); _filePath = filePath; SheetNames = new List<string>(); using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { _workbook = WorkbookFactory.Create(fs); } stopwatch.Stop(); Console.WriteLine("ReadFile:" + stopwatch.ElapsedMilliseconds/1000 + "s"); return GetSheetNames(); } /// <summary> /// 獲取SHeet名稱 /// </summary> /// <returns></returns> private List<string> GetSheetNames() { var count = _workbook.NumberOfSheets; for (int i = 0; i < count; i++) { SheetNames.Add(_workbook.GetSheetName(i)); } return SheetNames; } #endregion #region 獲取數據源 /// <summary> /// 獲取全部數據,全部sheet的數據轉化為datatable。 /// </summary> /// <param name="isFirstRowCoumn">是否將第一行作為列標題</param> /// <returns></returns> public DataSet GetAllTables(bool isFirstRowCoumn) { var stopTime = new System.Diagnostics.Stopwatch(); stopTime.Start(); var ds = new DataSet(); foreach (var sheetName in SheetNames) { ds.Tables.Add(ExcelToDataTable(sheetName, isFirstRowCoumn)); } stopTime.Stop(); Console.WriteLine("GetData:" + stopTime.ElapsedMilliseconds/1000 + "S"); return ds; } /// <summary> /// 獲取第<paramref name="idx"/>的sheet的數據 /// </summary> /// <param name="idx">Excel文件的第幾個sheet表</param> /// <param name="isFirstRowCoumn">是否將第一行作為列標題</param> /// <returns></returns> public DataTable GetTable(int idx, bool isFirstRowCoumn) { if (idx >= SheetNames.Count || idx < 0) throw new Exception("Do not Get This Sheet"); return ExcelToDataTable(SheetNames[idx], isFirstRowCoumn); } /// <summary> /// 獲取sheet名稱為<paramref name="sheetName"/>的數據 /// </summary> /// <param name="sheetName">Sheet名稱</param> /// <param name="isFirstRowColumn">是否將第一行作為列標題</param> /// <returns></returns> public DataTable GetTable(string sheetName, bool isFirstRowColumn) { return ExcelToDataTable(sheetName, isFirstRowColumn); } #endregion #region 方法 /// <summary> /// 將excel中的數據導入到DataTable中 /// </summary> /// <param name="sheetName">excel工作薄sheet的名稱</param> /// <param name="isFirstRowColumn">第一行是否是DataTable的列名</param> /// <returns>返回的DataTable</returns> public DataTable ExcelToDataTable(string sheetName, bool isFirstRowColumn) { ISheet sheet = null; var data = new DataTable(); data.TableName = sheetName; int startRow = 0; try { sheet = sheetName != null ? _workbook.GetSheet(sheetName) : _workbook.GetSheetAt(0); if (sheet != null) { var firstRow = sheet.GetRow(0); if (firstRow == null) return data; int cellCount = firstRow.LastCellNum; //一行最後一個cell的編號 即總的列數 startRow = isFirstRowColumn ? sheet.FirstRowNum + 1 : sheet.FirstRowNum; for (int i = firstRow.FirstCellNum; i < cellCount; ++i) { //.StringCellValue; var column = new DataColumn(Convert.ToChar(((int) ‘A‘) + i).ToString()); if (isFirstRowColumn) { var columnName = firstRow.GetCell(i).StringCellValue; column = new DataColumn(columnName); } data.Columns.Add(column); } //最後一列的標號 int rowCount = sheet.LastRowNum; for (int i = startRow; i <= rowCount; ++i) { IRow row = sheet.GetRow(i); if (row == null) continue; //沒有數據的行默認是null DataRow dataRow = data.NewRow(); for (int j = row.FirstCellNum; j < cellCount; ++j) { if (row.GetCell(j) != null) //同理,沒有數據的單元格都默認是null dataRow[j] = row.GetCell(j, MissingCellPolicy.RETURN_NULL_AND_BLANK).ToString(); } data.Rows.Add(dataRow); } } else throw new Exception("Don not have This Sheet"); return data; } catch (Exception ex) { Console.WriteLine("Exception: " + ex.Message); return null; } } #endregion } }
private void toolStripButton1_Click(object sender, EventArgs e) { var importCore = new ExcelImportCore(); var opdiag=new OpenFileDialog(); tabControl1.TabPages.Clear(); if (opdiag.ShowDialog() == DialogResult.OK) { importCore.LoadFile(opdiag.FileName); var ds = importCore.GetAllTables(false); // for (int i = 0; i < importCore.SheetNames.Count; i++) { var tp=new TabPage {Text= Name = importCore.SheetNames[i]}; tabControl1.TabPages.Add(tp); //加入數據源 var dgv=new DataGridView { //AutoGenerateColumns = false, DataSource = ds.Tables[i], Dock = DockStyle.Fill }; tp.Controls.Add(dgv); } } }
使用NPOI讀取Excel數據到DataTable