using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.SS.Util; using NPOI.XSSF.UserModel; using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Data.OleDb; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace SysBaseLibs { public class ExcelHelper { /// /// 将数据导出至Excel文件 /// /// DataTable对象 /// Excel文件路径 public static bool OutputToExcel(DataTable Table, string ExcelFilePath) { if (File.Exists(ExcelFilePath)) { throw new Exception("该文件已经存在!"); } if ((Table.TableName.Trim().Length == 0) || (Table.TableName.ToLower() == "table")) { Table.TableName = "Sheet1"; } //数据表的列数 int ColCount = Table.Columns.Count; //用于记数,实例化参数时的序号 int i = 0; //创建参数 OleDbParameter[] para = new OleDbParameter[ColCount]; //创建表结构的SQL语句 string TableStructStr = @"Create Table " + Table.TableName + "("; //连接字符串 string connString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + ExcelFilePath + ";Extended Properties=Excel 8.0;"; OleDbConnection objConn = new OleDbConnection(connString); //创建表结构 OleDbCommand objCmd = new OleDbCommand(); //数据类型集合 ArrayList DataTypeList = new ArrayList(); DataTypeList.Add("System.Decimal"); DataTypeList.Add("System.Double"); DataTypeList.Add("System.Int16"); DataTypeList.Add("System.Int32"); DataTypeList.Add("System.Int64"); DataTypeList.Add("System.Single"); //遍历数据表的所有列,用于创建表结构 foreach (DataColumn col in Table.Columns) { //如果列属于数字列,则设置该列的数据类型为double if (DataTypeList.IndexOf(col.DataType.ToString()) >= 0) { para[i] = new OleDbParameter("@" + col.ColumnName, OleDbType.Double); objCmd.Parameters.Add(para[i]); //如果是最后一列 if (i + 1 == ColCount) { TableStructStr += col.ColumnName + " double)"; } else { TableStructStr += col.ColumnName + " double,"; } } else { para[i] = new OleDbParameter("@" + col.ColumnName, OleDbType.VarChar); objCmd.Parameters.Add(para[i]); //如果是最后一列 if (i + 1 == ColCount) { TableStructStr += col.ColumnName + " varchar)"; } else { TableStructStr += col.ColumnName + " varchar,"; } } i++; } //创建Excel文件及文件结构 try { objCmd.Connection = objConn; objCmd.CommandText = TableStructStr; if (objConn.State == ConnectionState.Closed) { objConn.Open(); } objCmd.ExecuteNonQuery(); } catch (Exception exp) { throw exp; } //插入记录的SQL语句 string InsertSql_1 = "Insert into " + Table.TableName + " ("; string InsertSql_2 = " Values ("; string InsertSql = ""; //遍历所有列,用于插入记录,在此创建插入记录的SQL语句 for (int colID = 0; colID < ColCount; colID++) { if (colID + 1 == ColCount) //最后一列 { InsertSql_1 += Table.Columns[colID].ColumnName + ")"; InsertSql_2 += "@" + Table.Columns[colID].ColumnName + ")"; } else { InsertSql_1 += Table.Columns[colID].ColumnName + ","; InsertSql_2 += "@" + Table.Columns[colID].ColumnName + ","; } } InsertSql = InsertSql_1 + InsertSql_2; //遍历数据表的所有数据行 for (int rowID = 0; rowID < Table.Rows.Count; rowID++) { for (int colID = 0; colID < ColCount; colID++) { if (para[colID].DbType == DbType.Double && Table.Rows[rowID][colID].ToString().Trim() == "") { para[colID].Value = 0; } else { para[colID].Value = Table.Rows[rowID][colID].ToString().Trim(); } } try { objCmd.CommandText = InsertSql; objCmd.ExecuteNonQuery(); } catch (Exception exp) { string str = exp.Message; } } try { if (objConn.State == ConnectionState.Open) { objConn.Close(); } } catch (Exception exp) { throw exp; } return true; } /// /// 将数据导出至Excel文件 /// /// DataTable对象 /// 要导出的数据列集合 /// Excel文件路径 public static bool OutputToExcel(DataTable Table, ArrayList Columns, string ExcelFilePath) { if (File.Exists(ExcelFilePath)) { throw new Exception("该文件已经存在!"); } //如果数据列数大于表的列数,取数据表的所有列 if (Columns.Count > Table.Columns.Count) { for (int s = Table.Columns.Count + 1; s <= Columns.Count; s++) { Columns.RemoveAt(s); //移除数据表列数后的所有列 } } //遍历所有的数据列,如果有数据列的数据类型不是 DataColumn,则将它移除 DataColumn column = new DataColumn(); for (int j = 0; j < Columns.Count; j++) { try { column = (DataColumn)Columns[j]; } catch (Exception) { Columns.RemoveAt(j); } } if ((Table.TableName.Trim().Length == 0) || (Table.TableName.ToLower() == "table")) { Table.TableName = "Sheet1"; } //数据表的列数 int ColCount = Columns.Count; //创建参数 OleDbParameter[] para = new OleDbParameter[ColCount]; //创建表结构的SQL语句 string TableStructStr = @"Create Table " + Table.TableName + "("; //连接字符串 string connString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + ExcelFilePath + ";Extended Properties=Excel 8.0;"; OleDbConnection objConn = new OleDbConnection(connString); //创建表结构 OleDbCommand objCmd = new OleDbCommand(); //数据类型集合 ArrayList DataTypeList = new ArrayList(); DataTypeList.Add("System.Decimal"); DataTypeList.Add("System.Double"); DataTypeList.Add("System.Int16"); DataTypeList.Add("System.Int32"); DataTypeList.Add("System.Int64"); DataTypeList.Add("System.Single"); DataColumn col = new DataColumn(); //遍历数据表的所有列,用于创建表结构 for (int k = 0; k < ColCount; k++) { col = (DataColumn)Columns[k]; //列的数据类型是数字型 if (DataTypeList.IndexOf(col.DataType.ToString().Trim()) >= 0) { para[k] = new OleDbParameter("@" + col.Caption.Trim(), OleDbType.Double); objCmd.Parameters.Add(para[k]); //如果是最后一列 if (k + 1 == ColCount) { TableStructStr += col.Caption.Trim() + " Double)"; } else { TableStructStr += col.Caption.Trim() + " Double,"; } } else { para[k] = new OleDbParameter("@" + col.Caption.Trim(), OleDbType.VarChar); objCmd.Parameters.Add(para[k]); //如果是最后一列 if (k + 1 == ColCount) { TableStructStr += col.Caption.Trim() + " VarChar)"; } else { TableStructStr += col.Caption.Trim() + " VarChar,"; } } } //创建Excel文件及文件结构 try { objCmd.Connection = objConn; objCmd.CommandText = TableStructStr; if (objConn.State == ConnectionState.Closed) { objConn.Open(); } objCmd.ExecuteNonQuery(); } catch (Exception exp) { throw exp; } //插入记录的SQL语句 string InsertSql_1 = "Insert into " + Table.TableName + " ("; string InsertSql_2 = " Values ("; string InsertSql = ""; //遍历所有列,用于插入记录,在此创建插入记录的SQL语句 for (int colID = 0; colID < ColCount; colID++) { if (colID + 1 == ColCount) //最后一列 { InsertSql_1 += Columns[colID].ToString().Trim() + ")"; InsertSql_2 += "@" + Columns[colID].ToString().Trim() + ")"; } else { InsertSql_1 += Columns[colID].ToString().Trim() + ","; InsertSql_2 += "@" + Columns[colID].ToString().Trim() + ","; } } InsertSql = InsertSql_1 + InsertSql_2; //遍历数据表的所有数据行 DataColumn DataCol = new DataColumn(); for (int rowID = 0; rowID < Table.Rows.Count; rowID++) { for (int colID = 0; colID < ColCount; colID++) { //因为列不连续,所以在取得单元格时不能用行列编号,列需得用列的名称 DataCol = (DataColumn)Columns[colID]; if (para[colID].DbType == DbType.Double && Table.Rows[rowID][DataCol.Caption].ToString().Trim() == "") { para[colID].Value = 0; } else { para[colID].Value = Table.Rows[rowID][DataCol.Caption].ToString().Trim(); } } try { objCmd.CommandText = InsertSql; objCmd.ExecuteNonQuery(); } catch (Exception exp) { string str = exp.Message; } } try { if (objConn.State == ConnectionState.Open) { objConn.Close(); } } catch (Exception exp) { throw exp; } return true; } /// /// 获取Excel文件数据表列表 /// public static ArrayList GetExcelTables(string ExcelFileName) { DataTable dt = new DataTable(); ArrayList TablesList = new ArrayList(); if (File.Exists(ExcelFileName)) { using (OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=Excel 8.0;Data Source=" + ExcelFileName)) { try { conn.Open(); dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" }); } catch (Exception exp) { throw exp; } //获取数据表个数 int tablecount = dt.Rows.Count; for (int i = 0; i < tablecount; i++) { string tablename = dt.Rows[i][2].ToString().Trim().TrimEnd('$'); if (TablesList.IndexOf(tablename) < 0) { TablesList.Add(tablename); } } } } return TablesList; } /// /// 将Excel文件导出至DataTable(第一行作为表头) /// /// Excel文件路径 /// 数据表名,如果数据表名错误,默认为第一个数据表名 public static DataTable InputFromExcel(string ExcelFilePath, string TableName) { if (!File.Exists(ExcelFilePath)) { throw new Exception("Excel文件不存在!"); } //如果数据表名不存在,则数据表名为Excel文件的第一个数据表 ArrayList TableList = new ArrayList(); TableList = GetExcelTables(ExcelFilePath); if (TableName.IndexOf(TableName) < 0) { TableName = TableList[0].ToString().Trim(); } DataTable table = new DataTable(); OleDbConnection dbcon = new OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + ExcelFilePath + ";Extended Properties=Excel 8.0"); OleDbCommand cmd = new OleDbCommand("select * from [" + TableName + "$]", dbcon); OleDbDataAdapter adapter = new OleDbDataAdapter(cmd); try { if (dbcon.State == ConnectionState.Closed) { dbcon.Open(); } adapter.Fill(table); } catch (Exception exp) { throw exp; } finally { if (dbcon.State == ConnectionState.Open) { dbcon.Close(); } } return table; } /// /// 获取Excel文件指定数据表的数据列表 /// /// Excel文件名 /// 数据表名 public static ArrayList GetExcelTableColumns(string ExcelFileName, string TableName) { DataTable dt = new DataTable(); ArrayList ColsList = new ArrayList(); if (File.Exists(ExcelFileName)) { using (OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=Excel 8.0;Data Source=" + ExcelFileName)) { conn.Open(); dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Columns, new object[] { null, null, TableName, null }); //获取列个数 int colcount = dt.Rows.Count; for (int i = 0; i < colcount; i++) { string colname = dt.Rows[i]["Column_Name"].ToString().Trim(); ColsList.Add(colname); } } } return ColsList; } public static bool dataTableToCsv(DataTable table, string file) { bool lcRetval = false; if (File.Exists(file)) { throw new Exception("该文件已经存在!"); } try { string title = ""; FileStream fs = new FileStream(file, FileMode.OpenOrCreate); //FileStream fs1 = File.Open(file, FileMode.Open, FileAccess.Read); StreamWriter sw = new StreamWriter(new BufferedStream(fs), System.Text.Encoding.Default); for (int i = 0; i < table.Columns.Count; i++) { title += table.Columns[i].ColumnName + "\t"; //栏位:自动跳到下一单元格 } title = title.Substring(0, title.Length - 1) + "\n"; sw.Write(title); foreach (DataRow row in table.Rows) { string line = ""; for (int i = 0; i < table.Columns.Count; i++) { line += row[i].ToString().Trim() + "\t"; //内容:自动跳到下一单元格 } line = line.Substring(0, line.Length - 1) + "\n"; sw.Write(line); } sw.Close(); fs.Close(); lcRetval = true; }catch(Exception err) { ThreadLog.LogException(err); } return lcRetval; } } public static class ExcelHelper2 { #region Excel导入 /// /// 从Excel取数据并记录到List集合里 /// /// 单元头的值和名称:{ { "UserName", "姓名" }, { "Age", "年龄" } }; /// 保存文件绝对路径 /// 错误信息 /// 数据行开始序列,默认为1(即第二列,从0开始) /// 转换后的List对象集合 public static List ExcelToEntityList(this Dictionary cellHeader, string filePath, out string errMsg, int startIndex = 1) where T : new() { List enlist = new List(); var errorMsg = new StringBuilder(); try { if (Regex.IsMatch(filePath, ".xls$")) // 2003 { enlist = Excel2003ToEntityList(cellHeader, filePath, out errorMsg, startIndex); } else if (Regex.IsMatch(filePath, ".xlsx$")) // 2007 { enlist = Excel2007ToEntityList(cellHeader, filePath, out errorMsg, startIndex); } } catch (Exception ex) { errMsg = ex.Message; //typeof(ExcelHelper).LogError(ex); return default(List); } errMsg = errorMsg.ToString(); return enlist; } /// /// 从Excel2003取数据并记录到List集合里 /// /// 单元头的Key和Value:{ { "UserName", "姓名" }, { "Age", "年龄" } }; /// 保存文件绝对路径 /// 错误信息 /// /// 转换好的List对象集合 private static List Excel2003ToEntityList(this Dictionary cellHeader, string filePath, out StringBuilder errorMsg, int startIndex = 1) where T : new() { errorMsg = new StringBuilder(); // 错误信息,Excel转换到实体对象时,会有格式的错误信息 List enlist = new List(); // 转换后的集合 try { using (FileStream fs = File.OpenRead(filePath)) { HSSFWorkbook workbook = new HSSFWorkbook(fs); HSSFSheet sheet = (HSSFSheet)workbook.GetSheetAt(0); // 获取此文件第一个Sheet页 for (int rowIndex = startIndex; rowIndex <= sheet.LastRowNum; rowIndex++) { // 1.判断当前行是否空行,若空行就不在进行读取下一行操作,结束Excel读取操作 IRow row = sheet.GetRow(rowIndex); if (row == null) { break; } // 2.每一个Excel row转换为一个实体对象 T en = new T(); ExcelRowToEntity(cellHeader, row, rowIndex, en, ref errorMsg); enlist.Add(en); } } return enlist; } catch (Exception ex) { //typeof(ExcelHelper).LogError(ex); return default(List); } } /// /// 从Excel2007取数据并记录到List集合里 /// /// 单元头的Key和Value:{ { "UserName", "姓名" }, { "Age", "年龄" } }; /// 保存文件绝对路径 /// 错误信息 /// 数据行开始序列,默认为1(即第二列,从0开始) /// 转换好的List对象集合 private static List Excel2007ToEntityList(this Dictionary cellHeader, string filePath, out StringBuilder errorMsg, int startIndex = 1) where T : new() { errorMsg = new StringBuilder(); // 错误信息,Excel转换到实体对象时,会有格式的错误信息 List enlist = new List(); // 转换后的集合 try { using (FileStream fs = File.OpenRead(filePath)) { XSSFWorkbook workbook = new XSSFWorkbook(fs); XSSFSheet sheet = (XSSFSheet)workbook.GetSheetAt(0); // 获取此文件第一个Sheet页 for (int rowIndex = startIndex; rowIndex <= sheet.LastRowNum; rowIndex++) { // 1.判断当前行是否空行,若空行就不在进行读取下一行操作,结束Excel读取操作 IRow row = sheet.GetRow(rowIndex); if (row == null) { break; } // 2.每一个Excel row转换为一个实体对象 T en = new T(); ExcelRowToEntity(cellHeader, row, rowIndex, en, ref errorMsg); enlist.Add(en); } } return enlist; } catch (Exception ex) { //typeof(ExcelHelper).LogError(ex); return default(List); } } #endregion Excel导入 #region Excel导出 /// /// 实体类集合导出到EXCEL2003 /// /// 单元头的Key和Value:{ { "UserName", "姓名" }, { "Age", "年龄" } }; /// 数据源 /// 工作表名称 /// 文件的下载地址 /// public static string EntityListToExcel2003(this Dictionary cellHeader, IList enList, string sheetName, string filePath) { var lcRetVal = "error@"; try { string fileName = $"D-{sheetName}-{DateTime.Now:yyyyMMddHHmmssfff}.xls"; // 文件名称 filePath = filePath.StartsWith("/") ? filePath : ("/" + filePath); filePath = filePath.EndsWith("/") ? filePath : (filePath + "/"); string path = $"{AppDomain.CurrentDomain.BaseDirectory}{filePath}"; if (!Directory.Exists(path)) Directory.CreateDirectory(path); // 2.解析单元格头部,设置单元头的中文名称 HSSFWorkbook workbook = new HSSFWorkbook(); // 工作簿 ISheet sheet = workbook.CreateSheet(sheetName); // 工作表 IRow row = sheet.CreateRow(0); List keys = cellHeader.Keys.ToList(); for (int i = 0; i < keys.Count; i++) { row.CreateCell(i).SetCellValue(cellHeader[keys[i]]); // 列名为Key的值 } // 3.List对象的值赋值到Excel的单元格里 int rowIndex = 1; // 从第二行开始赋值(第一行已设置为单元头) object propertyValue = null; foreach (var en in enList) { IRow rowTmp = sheet.CreateRow(rowIndex); for (int i = 0; i < keys.Count; i++) // 根据指定的属性名称,获取对象指定属性的值 { string cellValue = ""; PropertyInfo propertyInfo = null; // 属性的信息 // 3.1 若属性头的名称包含'.',就表示是子类里的属性,那么就要遍历子类,eg:UserEn.UserName string[] propertyArray = keys[i].Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries); if (keys[i].IndexOf(".", StringComparison.Ordinal) >= 0) { // 3.1.1 解析子类属性(这里只解析1层子类,多层子类未处理) string subClassName = propertyArray[0]; // '.'前面的为子类的名称 string subClassPropertyName = propertyArray[1]; // '.'后面的为子类的属性名称 PropertyInfo subClassInfo = en.GetType().GetProperty(subClassName); // 获取子类的类型 if (subClassInfo != null) { // 3.1.2 获取子类的实例 var subClassEn = en.GetType().GetProperty(subClassName)?.GetValue(en, null); // 3.1.3 根据属性名称获取子类里的属性类型 propertyInfo = subClassInfo.PropertyType.GetProperty(subClassPropertyName); if (propertyInfo != null) { propertyValue = propertyInfo.GetValue(subClassEn, null); // 获取子类属性的值 } } } else { // 3.2 若不是子类的属性,直接根据属性名称获取对象对应的属性 propertyInfo = en.GetType().GetProperty(keys[i]); if (propertyInfo != null) { propertyValue = propertyInfo.GetValue(en, null); } } // 3.3 属性值经过转换赋值给单元格值 if (propertyValue != null) { if (propertyInfo?.PropertyType.Name == "int" || propertyInfo?.PropertyType.Name == "float" || propertyInfo?.PropertyType.Name == "double" || propertyInfo?.PropertyType.Name == "decimal") { var value = Convert.ToDouble(propertyValue); rowTmp.CreateCell(i).SetCellValue(value); } else if (propertyInfo?.PropertyType.Name == "bool") { var value = Convert.ToBoolean(propertyValue); rowTmp.CreateCell(i).SetCellValue(value); } else { cellValue = propertyValue.ToString(); // 3.3.1 对时间初始值赋值为空 if (cellValue.Trim() == "0001/1/1 0:00:00" || cellValue.Trim() == "0001/1/1 23:59:59") { cellValue = ""; } // 3.4 填充到Excel的单元格里 rowTmp.CreateCell(i).SetCellValue(cellValue); } } else { // 3.4 填充到Excel的单元格里 rowTmp.CreateCell(i).SetCellValue(cellValue); } } rowIndex++; } // 4.生成文件 FileStream file = new FileStream($"{path}{fileName}", FileMode.Create); workbook.Write(file); file.Close(); lcRetVal = $"{filePath}{fileName}"; } catch (Exception ex) { lcRetVal += ex.Message; //typeof(ExcelHelper).LogError(ex); } return lcRetVal; } public static string EntityListToExcel2003(this HSSFWorkbook workbook, string sheetName, string filePath) { var lcRetVal = "error@"; try { string fileName = $"D-{sheetName}-{DateTime.Now:yyyyMMddHHmmssfff}.xls"; // 文件名称 filePath = filePath.StartsWith("/") ? filePath : ("/" + filePath); filePath = filePath.EndsWith("/") ? filePath : (filePath + "/"); string path = $"{AppDomain.CurrentDomain.BaseDirectory}{filePath}"; if (!Directory.Exists(path)) Directory.CreateDirectory(path); FileStream file = new FileStream($"{path}{fileName}", FileMode.Create); workbook.Write(file); file.Close(); lcRetVal = $"{filePath}{fileName}"; } catch (Exception ex) { lcRetVal += ex.Message; //typeof(ExcelHelper).LogError(ex); } return lcRetVal; } public static HSSFWorkbook EntityListToExcel2003Book(this Dictionary cellHeader, IList enList, string sheetName) { HSSFWorkbook workbook = new HSSFWorkbook(); // 工作簿 ISheet sheet = workbook.CreateSheet(sheetName); // 工作表 IRow row = sheet.CreateRow(0); List keys = cellHeader.Keys.ToList(); for (int i = 0; i < keys.Count; i++) { row.CreateCell(i).SetCellValue(cellHeader[keys[i]]); // 列名为Key的值 } // 3.List对象的值赋值到Excel的单元格里 int rowIndex = 1; // 从第二行开始赋值(第一行已设置为单元头) foreach (var en in enList) { IRow rowTmp = sheet.CreateRow(rowIndex); for (int i = 0; i < keys.Count; i++) // 根据指定的属性名称,获取对象指定属性的值 { string cellValue = ""; // 单元格的值 object propertyValue = null; // 属性的值 PropertyInfo propertyInfo; // 属性的信息 // 3.1 若属性头的名称包含'.',就表示是子类里的属性,那么就要遍历子类,eg:UserEn.UserName if (keys[i].IndexOf(".", StringComparison.Ordinal) >= 0) { // 3.1.1 解析子类属性(这里只解析1层子类,多层子类未处理) string[] propertyArray = keys[i].Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries); string subClassName = propertyArray[0]; // '.'前面的为子类的名称 string subClassPropertyName = propertyArray[1]; // '.'后面的为子类的属性名称 PropertyInfo subClassInfo = en.GetType().GetProperty(subClassName); // 获取子类的类型 if (subClassInfo != null) { // 3.1.2 获取子类的实例 var subClassEn = en.GetType().GetProperty(subClassName)?.GetValue(en, null); // 3.1.3 根据属性名称获取子类里的属性类型 propertyInfo = subClassInfo.PropertyType.GetProperty(subClassPropertyName); if (propertyInfo != null) { propertyValue = propertyInfo.GetValue(subClassEn, null); // 获取子类属性的值 } } } else { // 3.2 若不是子类的属性,直接根据属性名称获取对象对应的属性 propertyInfo = en.GetType().GetProperty(keys[i]); if (propertyInfo != null) { propertyValue = propertyInfo.GetValue(en, null); } } // 3.3 属性值经过转换赋值给单元格值 if (propertyValue != null) { cellValue = propertyValue.ToString(); // 3.3.1 对时间初始值赋值为空 if (cellValue.Trim() == "0001/1/1 0:00:00" || cellValue.Trim() == "0001/1/1 23:59:59") { cellValue = ""; } } // 3.4 填充到Excel的单元格里 rowTmp.CreateCell(i).SetCellValue(cellValue); } rowIndex++; } return workbook; } /// /// 实体类集合导出到EXCEL2007 /// /// 单元头的Key和Value:{ { "UserName", "姓名" }, { "Age", "年龄" } }; /// 数据源 /// 工作表名称 /// 文件的下载地址 /// public static string EntityListToExcel2007(this Dictionary cellHeader, IList enList, string sheetName, string filePath) { var lcRetVal = "error@"; try { string fileName = $"D-{sheetName}-{DateTime.Now:yyyyMMddHHmmssfff}.xlsx"; // 文件名称 filePath = filePath.StartsWith("/") ? filePath : ("/" + filePath); filePath = filePath.EndsWith("/") ? filePath : (filePath + "/"); string path = $"{AppDomain.CurrentDomain.BaseDirectory}{filePath}"; if (!Directory.Exists(path)) Directory.CreateDirectory(path); // 2.解析单元格头部,设置单元头的中文名称 XSSFWorkbook workbook = new XSSFWorkbook(); // 工作簿 ISheet sheet = workbook.CreateSheet(sheetName); // 工作表 IRow row = sheet.CreateRow(0); List keys = cellHeader.Keys.ToList(); for (int i = 0; i < keys.Count; i++) { row.CreateCell(i).SetCellValue(cellHeader[keys[i]]); // 列名为Key的值 } // 3.List对象的值赋值到Excel的单元格里 int rowIndex = 1; // 从第二行开始赋值(第一行已设置为单元头) foreach (var en in enList) { IRow rowTmp = sheet.CreateRow(rowIndex); for (int i = 0; i < keys.Count; i++) // 根据指定的属性名称,获取对象指定属性的值 { string cellValue = ""; // 单元格的值 object propertyValue = null; // 属性的值 PropertyInfo propertyInfo = null; // 属性的信息 // 3.1 若属性头的名称包含'.',就表示是子类里的属性,那么就要遍历子类,eg:UserEn.UserName if (keys[i].IndexOf(".", StringComparison.Ordinal) >= 0) { // 3.1.1 解析子类属性(这里只解析1层子类,多层子类未处理) string[] propertyArray = keys[i].Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries); string subClassName = propertyArray[0]; // '.'前面的为子类的名称 var subClassPropertyName = propertyArray[1]; // '.'后面的为子类的属性名称 PropertyInfo subClassInfo = en.GetType().GetProperty(subClassName); // 获取子类的类型 if (subClassInfo != null) { // 3.1.2 获取子类的实例 var subClassEn = en.GetType().GetProperty(subClassName)?.GetValue(en, null); // 3.1.3 根据属性名称获取子类里的属性类型 propertyInfo = subClassInfo.PropertyType.GetProperty(subClassPropertyName); if (propertyInfo != null) { propertyValue = propertyInfo.GetValue(subClassEn, null); // 获取子类属性的值 } } } else { // 3.2 若不是子类的属性,直接根据属性名称获取对象对应的属性 propertyInfo = en.GetType().GetProperty(keys[i]); if (propertyInfo != null) { propertyValue = propertyInfo.GetValue(en, null); } } // 3.3 属性值经过转换赋值给单元格值 if (propertyValue != null) { if (propertyInfo.PropertyType.Name.ToLower() == "int" || propertyInfo.PropertyType.Name.ToLower() == "int16" || propertyInfo.PropertyType.Name.ToLower() == "int32" || propertyInfo.PropertyType.Name.ToLower() == "int64" || propertyInfo.PropertyType.Name.ToLower() == "double" || propertyInfo.PropertyType.Name.ToLower() == "decimal") { var value = Convert.ToDouble(propertyValue); rowTmp.CreateCell(i).SetCellValue(value); } else if (propertyInfo.PropertyType.Name.ToLower() == "bool") { var value = Convert.ToBoolean(propertyValue); rowTmp.CreateCell(i).SetCellValue(value); } else if (propertyInfo.PropertyType.Name.ToLower() == "nullable`1") { if (propertyInfo.PropertyType.FullName == null) { } else if (propertyInfo.PropertyType.FullName.ToLower().Contains("datetime")) { cellValue = propertyValue.ToString(); // 3.3.1 对时间初始值赋值为空 if (cellValue.Trim() == "0001/1/1 0:00:00" || cellValue.Trim() == "0001/1/1 23:59:59") { cellValue = ""; } rowTmp.CreateCell(i).SetCellValue(cellValue); } else if (propertyInfo.PropertyType.FullName.ToLower().Contains("int")) { var value = (int)Convert.ChangeType(propertyValue, typeof(int)); rowTmp.CreateCell(i).SetCellValue(value); } else if (propertyInfo.PropertyType.FullName.ToLower().Contains("float") || propertyInfo.PropertyType.FullName.ToLower().Contains("double") || propertyInfo.PropertyType.FullName.ToLower().Contains("decimal") || propertyInfo.PropertyType.FullName.ToLower().Contains("single")) { var value = (float)Convert.ChangeType(propertyValue, typeof(float)); rowTmp.CreateCell(i).SetCellValue(value); } else if (propertyInfo.PropertyType.FullName.ToLower().Contains("bool")) { var value = (bool)Convert.ChangeType(propertyValue, typeof(bool)); rowTmp.CreateCell(i).SetCellValue(value); } } else { cellValue = propertyValue.ToString(); // 3.3.1 对时间初始值赋值为空 if (cellValue.Trim() == "0001/1/1 0:00:00" || cellValue.Trim() == "0001/1/1 23:59:59") { cellValue = ""; } // 3.4 填充到Excel的单元格里 rowTmp.CreateCell(i).SetCellValue(cellValue); } } else { // 3.4 填充到Excel的单元格里 rowTmp.CreateCell(i).SetCellValue(cellValue); } } rowIndex++; } // 4.生成文件 FileStream file = new FileStream($"{path}{fileName}", FileMode.Create); workbook.Write(file); file.Close(); lcRetVal = $"{filePath}{fileName}"; } catch (Exception ex) { lcRetVal += ex.Message; //typeof(ExcelHelper).LogError(ex); } return lcRetVal; } #endregion Excel导出 #region Common /// /// Excel row转换为实体对象 /// /// /// 单元头的Key和Value:{ { "UserName", "姓名" }, { "Age", "年龄" } }; /// Excel row /// row index /// 实体 /// 错误信息 private static void ExcelRowToEntity(Dictionary cellHeader, IRow row, int rowIndex, T en, ref StringBuilder errorMsg) { List keys = cellHeader.Keys.ToList(); // 要赋值的实体对象属性名称 string errStr = ""; // 当前行转换时,是否有错误信息,格式为:第1行数据转换异常:XXX列; for (int i = 0; i < keys.Count; i++) { // 1.若属性头的名称包含'.',就表示是子类里的属性,那么就要遍历子类,eg:UserEn.TrueName if (keys[i].IndexOf(".", StringComparison.Ordinal) >= 0) { // 1)解析子类属性 string[] propertyArray = keys[i].Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries); string subClassName = propertyArray[0]; // '.'前面的为子类的名称 string classPropertyName = propertyArray[1]; // '.'后面的为子类的属性名称 PropertyInfo subClassInfo = en.GetType().GetProperty(subClassName); // 获取子类的类型 if (subClassInfo != null) { // 2)获取子类的实例 var subClassEn = en.GetType().GetProperty(subClassName)?.GetValue(en, null); // 3)根据属性名称获取子类里的属性信息 PropertyInfo propertyInfo = subClassInfo.PropertyType.GetProperty(classPropertyName); if (propertyInfo != null) { try { // Excel单元格的值转换为对象属性的值,若类型不对,记录出错信息 propertyInfo.SetValue(subClassEn, GetExcelCellToProperty(propertyInfo.PropertyType, row.GetCell(i)), null); } catch (Exception e) { //typeof(ExcelHelper).LogError(e); if (errStr.Length == 0) { errStr = "第" + rowIndex + "行数据转换异常:"; } errStr += cellHeader[keys[i]] + "列;"; } } } } else { // 2.给指定的属性赋值 PropertyInfo propertyInfo = en.GetType().GetProperty(keys[i]); if (propertyInfo != null) { try { // Excel单元格的值转换为对象属性的值,若类型不对,记录出错信息 propertyInfo.SetValue(en, GetExcelCellToProperty(propertyInfo.PropertyType, row.GetCell(i)), null); } catch (Exception e) { //typeof(ExcelHelper).LogError(e); if (errStr.Length == 0) { errStr = "第" + rowIndex + "行数据转换异常:"; } errStr += cellHeader[keys[i]] + "列;"; } } } } // 若有错误信息,就添加到错误信息里 if (errStr.Length > 0) { errorMsg.AppendLine(errStr); } } /// /// Excel Cell转换为实体的属性值 /// /// 目标对象类型 /// 对象属性的值 private static object GetExcelCellToProperty(Type distanceType, ICell sourceCell) { object rs = distanceType.IsValueType ? Activator.CreateInstance(distanceType) : null; // 1.判断传递的单元格是否为空 if (sourceCell == null || string.IsNullOrEmpty(sourceCell.ToString())) { return rs; } // 2.Excel文本和数字单元格转换,在Excel里文本和数字是不能进行转换,所以这里预先存值 object sourceValue = null; switch (sourceCell.CellType) { case CellType.Blank: break; case CellType.Boolean: sourceValue = sourceCell.BooleanCellValue; break; case CellType.Error: break; case CellType.Formula: break; case CellType.Numeric: sourceValue = sourceCell.NumericCellValue; break; case CellType.String: sourceValue = sourceCell.StringCellValue; break; case CellType.Unknown: break; default: sourceValue = sourceCell.StringCellValue; break; } string valueDataType = distanceType.Name; // 在这里进行特定类型的处理 switch (valueDataType.ToLower()) // 以防出错,全部小写 { case "string": rs = sourceValue?.ToString(); break; case "int": case "int32": rs = (int)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType); break; case "int16": rs = (short)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType); break; case "int64": rs = (long)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType); break; case "float": case "single": rs = (float)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType); break; case "double": rs = (double)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType); break; case "decimal": rs = (decimal)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType); break; case "datetime": rs = (DateTime)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType); break; case "guid": rs = (Guid)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType); break; case "nullable`1": if (distanceType.FullName == null) { rs = ""; } else if (distanceType.FullName.ToLower().Contains("datetime")) { rs = (DateTime)Convert.ChangeType(sourceValue?.ToString() ?? "", typeof(DateTime)); } else if ((bool)distanceType.FullName?.ToLower().Contains("int")) { rs = (int)Convert.ChangeType(sourceValue?.ToString() ?? "", typeof(int)); } else if ((bool)distanceType.FullName?.ToLower().Contains("float") || (bool)distanceType.FullName?.ToLower().Contains("double") || (bool)distanceType.FullName?.ToLower().Contains("decimal") || (bool)distanceType.FullName?.ToLower().Contains("single")) { rs = (float)Convert.ChangeType(sourceValue?.ToString() ?? "", typeof(float)); } else if ((bool)distanceType.FullName?.ToLower().Contains("bool")) { rs = (bool)Convert.ChangeType(sourceValue?.ToString() ?? "", typeof(bool)); } break; } return rs; } #endregion public static HSSFWorkbook CreateWorkBook03(string filePath = null) { if (string.IsNullOrEmpty(filePath)) { return new HSSFWorkbook(); } FileStream file = new FileStream(filePath, FileMode.Open); return new HSSFWorkbook(file); } public static XSSFWorkbook CreateWorkBook07(string filePath = null) { if (string.IsNullOrEmpty(filePath)) { return new XSSFWorkbook(); } return new XSSFWorkbook(filePath); } /// /// 创建Sheet /// /// /// /// /// /// /// public static ISheet GenerateSheet(this string sheetName, int defaultWidth = 20, int defaultHeight = 20, bool is07 = true, IWorkbook workbook = null) { workbook = is07 ? workbook ?? CreateWorkBook07() : workbook ?? CreateWorkBook03(); var sheet = workbook.CreateSheet(sheetName); sheet.DefaultColumnWidth = defaultWidth; sheet.DefaultRowHeight = (short)(defaultHeight * 20); return sheet; } /// /// 创建行 /// /// 表 /// 第几行(从1开始计数) /// public static IRow GenerateRow(this ISheet sheet, int rowIndex) { rowIndex = rowIndex <= 0 ? 1 : rowIndex; var row = sheet.GetRow(rowIndex - 1) ?? sheet.CreateRow(rowIndex - 1); return row; } /// /// 创建单元格 /// /// 表 /// 第几行(从1开始计数) /// 第几列(从1开始计数) /// 值 /// 单元格类型 /// public static ICell GenerateCell(this ISheet sheet, int rowIndex, int columnIndex, string val = null, CellType cellType = CellType.String) { var row = sheet.GenerateRow(rowIndex); var cell = GenerateCell(row, columnIndex, val, cellType); return cell; } /// /// 创建单元格 /// /// 行 /// 第几列(从1开始计数) /// 值 /// 单元格类型 /// public static ICell GenerateCell(this IRow row, int columnIndex, string val = null, CellType cellType = CellType.String) { columnIndex = columnIndex <= 0 ? 1 : columnIndex; var cell = row.GetCell(columnIndex - 1) ?? row.CreateCell(columnIndex - 1); if (!string.IsNullOrEmpty(val)) { cell.SetCellValue(val); cell.SetCellType(cellType); } return cell; } /// /// 设置列宽度 /// /// 表 /// 第几列(从1开始计数) /// 宽度 /// public static ISheet SetCellWidth(this ISheet sheet, int columnIndex, int width) { sheet.SetColumnWidth(columnIndex - 1, width * 256); return sheet; } /// /// 设置列宽度 /// /// 行 /// 第几列(从1开始计数) /// 宽度 /// public static IRow SetCellWidth(this IRow row, int columnIndex, int width) { row.Sheet.SetColumnWidth(columnIndex - 1, width * 256); return row; } /// /// 设置列宽度 /// /// 单元格 /// 第几列(从1开始计数) /// 宽度 /// public static ICell SetCellWidth(this ICell cell, int columnIndex, int width) { cell.Sheet.SetColumnWidth(columnIndex - 1, width * 256); return cell; } /// /// 设置行高度 /// /// 表 /// 第几行(从1开始计数) /// 宽度 /// public static ISheet SetRowHeight(this ISheet sheet, int rowIndex, int height) { sheet.GetRow(rowIndex - 1).SetRowHeight(height); return sheet; } /// /// 设置行高度 /// /// 行 /// 宽度 /// public static IRow SetRowHeight(this IRow row, int height) { row.Height = (short)(height * 20); return row; } /// /// 设置行高度 /// /// 单元格 /// 宽度 /// public static ICell SetRowHeight(this ICell cell, int height) { cell.Row.SetRowHeight(height); return cell; } /// /// 设置单元格的值 /// /// /// /// public static ICell SetValue(this ICell cell, string obj) { return SetValue(cell, obj); } /// /// 设置单元格的值 /// /// 值类型(sting,bool,double,DateTime) /// /// /// public static ICell SetValue(this ICell cell, object obj) { Type type = typeof(T); bool bValue; double iValue; DateTime dValue; if (type == typeof(string)) { cell.SetCellValue(obj.ToString()); } else if (type == typeof(bool) && bool.TryParse(obj.ToString(), out bValue)) { cell.SetCellValue(bValue); } else if ((type == typeof(int) || type == typeof(double) || type == typeof(decimal)) && double.TryParse(obj.ToString(), out iValue)) { cell.SetCellValue(iValue); } else if (type == typeof(DateTime) && DateTime.TryParse(obj.ToString(), out dValue)) { cell.SetCellValue(dValue); } return cell; } #region DATA-FORMAT public static ICellStyle SetCellDateTime(this ICell cell, DateTime value, string formatStr = "yyyy-MM-dd HH:mm:ss") { cell.SetCellValue(value); cell.SetDataFormat(formatStr); return cell.CellStyle; } public static ICellStyle SetCellString(this ICell cell, double value, string formatStr = "@") { cell.SetCellValue(value); cell.SetDataFormat(formatStr); return cell.CellStyle; } public static ICellStyle SetCellDouble(this ICell cell, double value, string formatStr = "0.00") { cell.SetCellValue(value); cell.SetDataFormat(formatStr); return cell.CellStyle; } public static ICellStyle SetCellCurrency(this ICell cell, double value, string formatStr = "¥#,###.##") { cell.SetCellValue(value); cell.SetDataFormat(formatStr); return cell.CellStyle; } public static ICellStyle SetCellPercent(this ICell cell, double value, string formatStr = "0.00%") { cell.SetCellValue(value); cell.SetDataFormat(formatStr); return cell.CellStyle; } public static void SetDataFormat(this ICell cell, string formatStr = "¥#,##0.00") { var cellStyle = cell.CellStyle ?? GetCellStyle(cell); var format = cell.Sheet.Workbook.CreateDataFormat(); cellStyle.DataFormat = format.GetFormat(formatStr); cell.SetCellStyle(cellStyle); } #endregion #region 合并单元格 /// /// 合并单元格 /// /// /// 开始行数(从1开始计数) /// 结束行数(从1开始计数) /// 开始列数(从1开始计数) /// 结束列数(从1开始计数) /// public static ISheet MergedRegion(this ISheet sheet, int firstRow, int lastRow, int firstColumn, int lastColumn) { var region = GetCellRegion(firstRow, lastRow, firstColumn, lastColumn); sheet.MergedRegion(region); return sheet; } public static ISheet MergedRegion(this ISheet sheet, CellRangeAddress region) { sheet.AddMergedRegion(region); //SetRegionBorder(sheet, region, borderTypeStr, borderColorStr); return sheet; } public static CellRangeAddress GetCellRegion(this int firstRow, int lastRow, int firstColumn, int lastColumn) { firstRow = firstRow <= 0 ? 1 : firstRow; firstColumn = firstColumn <= 0 ? 1 : firstColumn; lastRow = lastRow <= 0 ? 1 : lastRow; lastColumn = lastColumn <= 0 ? 1 : lastColumn; return new CellRangeAddress(firstRow - 1, lastRow - 1, firstColumn - 1, lastColumn - 1); } #endregion public static ICellStyle GetCellStyle(this ICell cell) { return cell.CellStyle ?? cell.Sheet.Workbook.CreateCellStyle(); } public static void SetCellStyle(this ICell cell, ICellStyle cellStyle) { cell.CellStyle = cellStyle; } /// /// 保存工作簿 /// /// /// /// /// public static string SaveWorkBook(this ISheet sheet, string filePath, string fileName) { try { if (!Directory.Exists(filePath)) { Directory.CreateDirectory(filePath); } filePath = filePath.EndsWith("\\") ? filePath : filePath + "\\"; FileStream file = new FileStream(filePath + fileName, FileMode.Create); sheet.Workbook.Write(file); file.Close(); return ""; } catch (Exception e) { return e.Message; } } /// /// 保存工作簿 /// /// /// /// /// public static string SaveWorkBook(this IWorkbook workbook, string filePath, string fileName) { try { if (!Directory.Exists(filePath)) { Directory.CreateDirectory(filePath); } filePath = filePath.EndsWith("\\") ? filePath : filePath + "\\"; var path = filePath + fileName; if (File.Exists(path)) { File.Delete(path); } FileStream file = new FileStream(path, FileMode.Create); workbook.Write(file); file.Close(); return ""; } catch (Exception e) { return e.Message; } } } }