采用 NPOI 和 Epplus 方式读取Excel,因为之前测试NPOI的时候发现对于 .xlsx 格式的文件读取不是很友好,所以才结合了两个。
废话少说,直接上代码:
public static class ExcelRead {
/// <summary> /// Excel表格列标识 /// </summary> public enum ExcelColumns { Column_1 = 1, Column_2 = 2, Column_3 = 3, Column_4 = 4, Column_5 = 5, Column_6 = 6, Column_7 = 7, Column_8 = 8, Column_9 = 9, Column_10 = 10, Column_11 = 11, Column_12 = 12, Column_13 = 13, Column_14 = 14, Column_15 = 15, Column_16 = 16, Column_17 = 17, Column_18 = 18, Column_19 = 19, Column_20 = 20, Column_21 = 21, Column_22 = 22, Column_23 = 23, Column_24 = 24, Column_25 = 25, Column_26 = 26, Column_27 = 27, Column_28 = 28, Column_29 = 29, Column_30 = 30, Column_31 = 31, Column_32 = 32, Column_33 = 33, Column_34 = 34, Column_35 = 35, Column_36 = 36, Column_37 = 37, Column_38 = 38, Column_39 = 39, Column_40 = 40, Column_41 = 41, Column_42 = 42, Column_43 = 43, Column_44 = 44, Column_45 = 45, Column_46 = 46, Column_47 = 47, Column_48 = 48, Column_49 = 49, Column_50 = 50, Column_51 = 51, Column_52 = 52, Column_53 = 53, Column_54 = 54, Column_55 = 55, Column_56 = 56, Column_57 = 57, Column_58 = 58, Column_59 = 59, Column_60 = 60, Column_61 = 61, Column_62 = 62, Column_63 = 63, Column_64 = 64, Column_65 = 65, Column_66 = 66, Column_67 = 67, Column_68 = 68, Column_69 = 69, Column_70 = 70, Column_71 = 71, Column_72 = 72, Column_73 = 73, Column_74 = 74, Column_75 = 75, Column_76 = 76, Column_77 = 77, Column_78 = 78, Column_79 = 79, Column_80 = 80, Column_81 = 81, Column_82 = 82, Column_83 = 83, Column_84 = 84, Column_85 = 85, Column_86 = 86, Column_87 = 87, Column_88 = 88, Column_89 = 89, Column_90 = 90, Column_91 = 91, Column_92 = 92, Column_93 = 93, Column_94 = 94, Column_95 = 95, Column_96 = 96, Column_97 = 97, Column_98 = 98, Column_99 = 99, Column_100 = 100, Sys_NewGuid, Sys_DateTime, Sys_Empty }
/// <summary> /// 表格列数据类型 /// </summary> public enum DataTableColumnType { //Sys_String = "System.String"; //Sys_Int32 = "System.Int32"; //Sys_Decimal = "System.Decimal"; //Sys_DateTime = "System.DateTime"; //Sys_Long = "System.Int64"; //Sys_Bool = "System.Boolean"; Sys_String, Sys_Int32, Sys_Decimal, Sys_DateTime, Sys_Long, Sys_Bool } /// <summary> /// 获取表格列数据类型 /// </summary> /// <param name="dataTableColumnType"></param> /// <returns></returns> private static string GetDataTableColumnType(DataTableColumnType dataTableColumnType) { string columnType = string.Empty; switch (dataTableColumnType) { case DataTableColumnType.Sys_String: columnType = "System.String"; break; case DataTableColumnType.Sys_Int32: columnType = "System.Int32"; break; case DataTableColumnType.Sys_Decimal: columnType = "System.Decimal"; break; case DataTableColumnType.Sys_DateTime: columnType = "System.DateTime"; break; case DataTableColumnType.Sys_Long: columnType = "System.Int64"; break; case DataTableColumnType.Sys_Bool: columnType = "System.Boolean"; break; default: break; } return columnType; }
/// <summary> /// 读取Excel文件,返回DataTable /// </summary> /// <param name="filePath">文件路径</param> /// <param name="sheetIndex">sheet页下标,从1开始</param> /// <param name="startRow">开始行</param> /// <param name="tableName">对应数据库的表名</param> /// <param name="dtColumns">DataTable列定义</param> /// <param name="dtExcelMap">DataTable和Excel的映射关系</param> /// <returns></returns> public static DataTable GetExcelContent(string filePath, int sheetIndex, int startRow, string tableName, Dictionary<string, DataTableColumnType> dtColumns, Dictionary<string, ExcelColumns> dtExcelMap) { //声明表格控件,初始化表格列 DataTable tblDatas = new DataTable(tableName); foreach (var item in dtColumns) tblDatas.Columns.Add(item.Key, Type.GetType(GetDataTableColumnType(item.Value))); FileStream fs = null; ExcelPackage package = null; try { // 2007版本 epplus 读取 if (filePath.IndexOf(".xlsx") > 0) { #region 2007 fs = new FileStream(filePath, FileMode.Open); using (package = new ExcelPackage(fs)) { ExcelWorksheet sheet = package.Workbook.Worksheets[1]; for (int i = startRow; i <= sheet.Dimension.End.Row; i++) { //定义获取列值的委托 Func<ExcelColumns, object> func = delegate (ExcelColumns excelColumns) { return sheet.GetValue(i, (int)excelColumns);//读取第i行第excelColumns列数据 }; //获取与表格列对应的 行值 集合 object[] arrValue = GetDataTableRow(tblDatas, dtExcelMap, func); //添加到表格中 tblDatas.Rows.Add(arrValue); } } #endregion } // 2003版本 else if (filePath.IndexOf(".xls") > 0) { #region 2003 using (fs = File.OpenRead(filePath)) { IWorkbook workbook = new HSSFWorkbook(fs); if (workbook != null) { //读取第一个sheet,当然也可以循环读取每个sheet ISheet sheet = workbook.GetSheetAt(sheetIndex - 1); if (sheet != null) { int rowCount = sheet.LastRowNum;//总行数 for (int i = startRow - 1; rowCount > 0 && i <= rowCount; ++i) { //定义获取列值的委托 Func<ExcelColumns, object> func = delegate (ExcelColumns excelColumns) { IRow row = sheet.GetRow(i); return row.GetCell((int)excelColumns - 1);//读取第i行第excelColumns列数据 }; //获取与表格列对应的 行值 集合 object[] arrValue = GetDataTableRow(tblDatas, dtExcelMap, func); //添加到表格中 tblDatas.Rows.Add(arrValue); } } } } #endregion } return tblDatas; } catch (Exception ex) { return null; } finally { if (package != null) { package.Dispose(); } if (fs != null) { fs.Close(); } } }
/// <summary> /// 获取表格行数据 /// </summary> /// <param name="tblDatas"></param> /// <param name="dtExcelMap"></param> /// <param name="getExcelCellValue"></param> /// <returns></returns> private static object[] GetDataTableRow(DataTable tblDatas, Dictionary<string, ExcelColumns> dtExcelMap, Func<ExcelColumns, object> getExcelCellValue) { int arrIndex = 0; object[] arrValue = new object[tblDatas.Columns.Count]; //循环表格所有列 foreach (DataColumn item in tblDatas.Columns) { //根据表格列和值枚举映射关系,由列得到值枚举 ExcelColumns excelColumns = dtExcelMap[item.ColumnName]; //判断值枚举是否为Guid if (excelColumns == ExcelColumns.Sys_NewGuid) arrValue[arrIndex] = Guid.NewGuid(); //判断值枚举是否为DateTime else if (excelColumns == ExcelColumns.Sys_DateTime) arrValue[arrIndex] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); //根据值枚举下标,获取对应列的值 else arrValue[arrIndex] = getExcelCellValue(excelColumns); arrIndex++; } return arrValue; }
}
代码总体上没有达到完全体,还有非常多的优化空间,先Mark一下,赶下项目进度,后期进行优化了再更新。
具体使用方式如下:
string filePath = "文件完整的路径"; int sheetIndex = 1;//将要读取的Sheet页,从1开始 int startRow = 1;//开始读取的数据行,不包含表头,从1开始 string tableName = "对应数据库的名称,方便后续插入到数据库中"; //表格的列定义,想要输出多少列,就定义多少列 Dictionary<string, ExcelRead.DataTableColumnType> dtCols = new Dictionary<string, ExcelRead.DataTableColumnType>(); deMap.Add("列名", ExcelRead.ExcelColumns.Sys_DateTime); //表格列 和 Excel表格列 的对应关系,必须和“表格的列定义”数量一致,且列名相同 //表格列 可以对应非 Excel表格列 的内容,目前仅支持 Guid 和 DataTime Dictionary<string, ExcelRead.ExcelColumns> colsMap = new Dictionary<string, ExcelRead.ExcelColumns>(); deMap.Add("列名", ExcelRead.ExcelColumns.Column_1); //开始调用,获取表格 DataTable data = ExcelRead.GetExcelContent(filePath, sheetIndex, startRow, tableName, dtCols, colsMap);
以上。