Excel轉化成DataTable實現:NPOI和OLEDb
阿新 • • 發佈:2017-12-24
hdr get typeof rop gpo 文件存儲 lis bre excel2003
使用兩種方式實現的excel數據轉化成DataSet,再結合前一篇的DataTable轉化為實體,就可以解決excel到實體之間的轉化。
代碼如下:
首先定義一個接口:
public interface IExcelAccess { DataSet Load(ExcelConfig config); }
public class ExcelConfig { /// <summary> /// 文件存儲路徑 /// </summary> publicstring Path { get; set; } /// <summary> /// 文件表頭所在行索引 /// </summary> public int HeaderIndex { get; set; } }
再來看一下使用NPOI的實現:
public class NpoiExcelAccess : IExcelAccess { /// <summary> /// 根據文件擴展名,獲取workbook實例 /// </summary>/// <param name="ext"></param> /// <returns></returns> private IWorkbook GetWorkBook(string ext, Stream stream) { IWorkbook workbook = null; switch (ext) { case ".xlsx": workbook= new XSSFWorkbook(stream); break; case ".xls": workbook = new HSSFWorkbook(stream); break; default: break; } return workbook; } /// <summary> /// 加載數據,可設置跳過前幾行 /// </summary> /// <param name="path"></param> /// <param name="skipRows"></param> /// <returns></returns> public DataSet Load(ExcelConfig config) { using (var fileStream = new FileStream(config.Path, FileMode.Open, FileAccess.Read)) { var ds = new DataSet(); var ext = Path.GetExtension(config.Path); // 新建IWorkbook對象 var workbook = this.GetWorkBook(ext, fileStream); for (int i = 0; i < workbook.NumberOfSheets; i++) { ISheet sheet = workbook.GetSheetAt(i); DataTable dt = GetDataTable(sheet, config.HeaderIndex); ds.Tables.Add(dt); } return ds; } } private DataTable GetDataTable(ISheet sheet, int headerIndex) { var dt = new DataTable(); // 獲取表頭行 var headerRow = sheet.GetRow(headerIndex); var cellCount = GetCellCount(sheet, headerIndex); // 設置表頭 for (int i = 0; i < cellCount; i++) { if (headerRow.GetCell(i) != null) { dt.Columns.Add(headerRow.GetCell(i).StringCellValue, typeof(string)); } } for (int i = headerIndex + 1; i <= sheet.LastRowNum; i++) { IRow row = sheet.GetRow(i); DataRow dr = dt.NewRow(); FillDataRow(row, ref dr); dt.Rows.Add(dr); } dt.TableName = sheet.SheetName; return dt; } private void FillDataRow(IRow row, ref DataRow dr) { if (row != null) { for (int j = 0; j < dr.Table.Columns.Count; j++) { ICell cell = row.GetCell(j); if (cell != null) { switch (cell.CellType) { case CellType.Blank: dr[j] = DBNull.Value; break; case CellType.Boolean: dr[j] = cell.BooleanCellValue; break; case CellType.Numeric: if (DateUtil.IsCellDateFormatted(cell)) { dr[j] = cell.DateCellValue; } else { dr[j] = cell.NumericCellValue; } break; case CellType.String: dr[j] = cell.StringCellValue; break; case CellType.Error: dr[j] = cell.ErrorCellValue; break; case CellType.Formula: // cell = evaluator.EvaluateInCell(cell) as HSSFCell; dr[j] = cell.ToString(); break; default: throw new NotSupportedException(string.Format("Catched unhandle CellType[{0}]", cell.CellType)); } } } } } /// <summary> /// 獲取表頭列數 /// </summary> /// <param name="sheet"></param> /// <param name="skipRows"></param> /// <returns></returns> private int GetCellCount(ISheet sheet, int headerIndex) { var headerRow = sheet.GetRow(headerIndex); return headerRow.LastCellNum; } }
最後看一下使用OLEDB的實現,這裏,我只實現了excel2003的版本,07版本的總是失敗,查了原因,是需要在本機安裝一個組件才能支持導入.xlsx文件。
public class OleDbExcelAccess : IExcelAccess { private string strConn; public OleDbExcelAccess() { //TODO 需要根據擴展名,來決定 使用哪一種連接字符串 strConn = " Provider = Microsoft.Jet.OLEDB.4.0 ; Data Source = {0};Extended Properties=‘Excel 8.0;IMEX=1;HDR=NO‘"; } public DataSet Load(ExcelConfig config) { var ds = new DataSet(); var sheets = GetSheetNames(config.Path); var strConnTmp = string.Format(strConn, config.Path); foreach (string sheet in sheets) { using (var oleConn = new OleDbConnection(strConnTmp)) { var strsql = "SELECT * FROM [" + sheet + "]"; var oleDaExcel = new OleDbDataAdapter(strsql, oleConn); oleConn.Open(); oleDaExcel.Fill(ds, sheet); } } return ds; } /// <summary> /// 獲取Excel的所有的sheet /// </summary> /// <param name="path"></param> /// <returns></returns> private string[] GetSheetNames(string path) { DataTable dt = new DataTable(); if (File.Exists(path)) { string strConnTmp = string.Format(strConn, path); using (var conn = new OleDbConnection(strConnTmp)) { conn.Open(); //返回Excel的架構,包括各個sheet表的名稱,類型,創建時間和修改時間等 dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "Table" }); } //包含excel中表名的字符串數組 var sheetNames = new List<string>(); for (int k = 0; k < dt.Rows.Count; k++) { string tableName = dt.Rows[k]["TABLE_NAME"].ToString(); //修正出現兼容性視圖名稱時過濾表名 if (!tableName.Substring(tableName.Length - 1).Equals("_")) { sheetNames.Add(tableName); } } return sheetNames.ToArray(); } return null; } }
最後看一下客戶端的調用 :
private void TestExcelImport() { var excelFile = Path.Combine("C:\\Users\\hankk\\Desktop\\ICON", "2003版本.xls"); ExcelConfig config = new ExcelConfig() { Path = excelFile, HeaderIndex = 1 }; IExcelAccess npoiAccess = new NpoiExcelAccess(); var npoiDs = npoiAccess.Load(config); IExcelAccess oleDbAccess = new OleDbExcelAccess(); var oleDs = oleDbAccess.Load(config); }
代碼已上傳到github: https://github.com/hankuikuide/ExcelAccessor
Excel轉化成DataTable實現:NPOI和OLEDb