Excel操作封装(NOPI),实体集合导出Excel,Excel读取到实体集合
/************************************************* * 描述: * * Author:ys * Date:2023/7/31 17:45:03 * Update: * ************************************************/ using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms.VisualStyles; using System.Windows.Forms; using static Sunny.UI.UIDataGridView; using Sunny.UI.Win32; using NPOI.SS.Util; using NPOI.XSSF.UserModel; using NPOI.SS.UserModel; using NPOI.HSSF.UserModel; using System.Data; using NPOI.SS.Formula.Eval; using System.Text.RegularExpressions; using System.Reflection; using System.ComponentModel; namespace Wd.Common { public class ExcelHelper { #region 读取excel /// <summary> /// 根据Excel和Sheet返回DataTable /// </summary> /// <param name="filePath">Excel文件地址</param> /// <param name="sheetIndex">Sheet索引</param> /// <returns>DataTable</returns> public static DataTable GetDataTableByExcelPath(string filePath, int sheetIndex) { return GetDataSetByExcelPath(filePath, sheetIndex).Tables[0]; } /// <summary> /// 根据Excel返回DataSet /// </summary> /// <param name="filePath">Excel文件地址</param> /// <param name="sheetIndex">Sheet索引,可选,默认返回所有Sheet</param> /// <returns>DataSet</returns> public static DataSet GetDataSetByExcelPath(string filePath, int? sheetIndex = null) { DataSet ds = new DataSet(); IWorkbook fileWorkbook; using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { if (filePath.Last() == 's') { try { fileWorkbook = new HSSFWorkbook(fs); } catch (Exception ex) { //logger.Error("打开Excel文件失败!", ex); throw ex; } } else { try { fileWorkbook = new XSSFWorkbook(fs); } catch { fileWorkbook = new HSSFWorkbook(fs); } } } for (int i = 0; i < fileWorkbook.NumberOfSheets; i++) { if (sheetIndex != null && sheetIndex != i) continue; DataTable dt = new DataTable(); ISheet sheet = fileWorkbook.GetSheetAt(i); // 表名 dt.TableName = sheet.SheetName; //表头 IRow header = sheet.GetRow(sheet.FirstRowNum); List<int> columns = new List<int>(); for (int j = 0; j < header.LastCellNum; j++) { object obj = GetValueTypeForXLS(header.GetCell(j) as ICell); if (obj == null || obj.ToString() == string.Empty) { dt.Columns.Add(new DataColumn("Columns" + j.ToString())); } else dt.Columns.Add(new DataColumn(obj.ToString())); columns.Add(j); } //数据 IEnumerator rows = sheet.GetEnumerator(); int RowIndex = sheet.FirstRowNum + 1; while (rows.MoveNext()) { if (sheet.GetRow(RowIndex) == null) { break; } DataRow dr = dt.NewRow(); bool hasValue = false; foreach (int K in columns) { dr[K] = GetValueTypeForXLS(sheet.GetRow(RowIndex).GetCell(K) as ICell); if (dr[K] != null && dr[K].ToString() != string.Empty) { hasValue = true; } } if (hasValue) { dt.Rows.Add(dr); } RowIndex++; } ds.Tables.Add(dt); } return ds; } /// <summary> /// 根据单元格将内容返回为对应类型的数据 /// </summary> /// <param name="cell">单元格</param> /// <returns>数据</returns> private static object GetValueTypeForXLS(ICell cell) { if (cell == null) return null; switch (cell.CellType) { case CellType.Blank: //BLANK: return null; case CellType.Boolean: //BOOLEAN: return cell.BooleanCellValue; case CellType.Numeric: //NUMERIC: if (DateUtil.IsCellDateFormatted(cell)) { return cell.DateCellValue.ToString("yyyy/MM/dd hh:mm:ss.fff"); } else { return cell.NumericCellValue; } case CellType.String: //STRING: return cell.StringCellValue; case CellType.Error: //ERROR: return cell.ErrorCellValue; case CellType.Formula: //FORMULA: switch (cell.CachedFormulaResultType) { case CellType.Boolean: return cell.BooleanCellValue; case CellType.Error: return ErrorEval.GetText(cell.ErrorCellValue); case CellType.Numeric: if (DateUtil.IsCellDateFormatted(cell)) { return cell.DateCellValue.ToString("yyyy/MM/dd"); } else { return cell.NumericCellValue; } case CellType.String: string str = cell.StringCellValue; if (!string.IsNullOrEmpty(str)) { return str.ToString().Trim(); } else { return string.Empty; } case CellType.Unknown: case CellType.Blank: default: return string.Empty; } default: return "=" + cell.CellFormula; } } #endregion #region 实体集合保存Excel,Excel读取到L实体集合 /// <summary> /// 保存Excel文件 /// </summary> /// <param name="pathExcelName">保存路径+Excel文件名</param> /// <param name="sheetName">Sheet工作表名</param> /// <param name="data">实体类对象</param> public static void ExportExcelByList<T>(string pathExcelName, string sheetName, List<T> data) { //创建一个Excel文档 IWorkbook workBook = new HSSFWorkbook(); //创建一个工作表Sheet ISheet sheet = workBook.CreateSheet(sheetName); sheet.DefaultColumnWidth = 50; int rowNum = 0; //LastRowNum记录当前可用写入的行索引 var row = sheet.CreateRow(sheet.LastRowNum); //获取这个实体对象的所有属性 PropertyInfo[] preInfo = typeof(T).GetProperties(); foreach (var item in preInfo) { //获取当前属性的自定义特性列表 object[] objPres = item.GetCustomAttributes(typeof(DescriptionAttribute), true); if (objPres.Length > 0) { for (int i = 0; i < objPres.Length; i++) { //创建行,将当前自定义特性写入 row.CreateCell(rowNum).SetCellValue(((DescriptionAttribute)objPres[i]).Description); rowNum++; } } } int j = sheet.LastRowNum + 1, columnNum = 0; foreach (var item in data) { columnNum = 0; row = sheet.CreateRow(j++); //获取当前对象的属性列表 var itemProps = item.GetType().GetProperties(); foreach (var itemPropSub in itemProps) { //获取当前对象特性中的自定义特性[Description("自定义特性")] var objs = itemPropSub.GetCustomAttributes(typeof(DescriptionAttribute), true); if (objs.Length > 0) { //将当前对象的特性值,插入当前行的第n列单元格 row.CreateCell(columnNum).SetCellValue(itemPropSub.GetValue(item, null) == null ? "" : itemPropSub.GetValue(item, null).ToString()); columnNum++; } } } //文件流写入 using (MemoryStream ms = new MemoryStream()) { workBook.Write(ms); using (FileStream fs = new FileStream(pathExcelName, FileMode.Create, FileAccess.Write)) { ms.WriteTo(fs); } ms.Flush(); ms.Position = 0; workBook.Close(); } } #endregion 实体集合与Excel互相转换 #region DataTable导出Excel 和Excel读取到DataTabel /// <summary> /// DataTabel导出excel /// </summary> /// <param name="tabelDatas"></param> /// <param name="excelPathAll"></param> /// <param name="errMsg"></param> /// <returns></returns> public static bool ExportExcelByDataTabel(string excelPathAll, DataTable tabelDatas, out string errMsg) { errMsg = string.Empty; if (string.IsNullOrEmpty(excelPathAll)) { SaveFileDialog saveFileDialog = new SaveFileDialog(); //设置文件标题 saveFileDialog.Title = "导出Excel文件"; //设置文件类型 saveFileDialog.Filter = "Microsoft Office Excel 工作簿(*.xls)|*.xls"; //设置默认文件类型显示顺序 saveFileDialog.FilterIndex = 1; //是否自动在文件名中添加扩展名 saveFileDialog.AddExtension = true; //是否记忆上次打开的目录 saveFileDialog.RestoreDirectory = true; //设置默认文件名 //saveFileDialog.FileName = ""; //按下确定选择的按钮 if (saveFileDialog.ShowDialog() == DialogResult.OK) { //获得文件路径 excelPathAll = saveFileDialog.FileName.ToString(); } else { errMsg = "没有获取到保存路径"; return false; } } string myDateFormat = "yyyy-MM-dd HH:mm:ss"; XSSFWorkbook wb = new XSSFWorkbook(); ISheet sheet = wb.CreateSheet("Sheet1"); IRow rowHeader = sheet.CreateRow(0); for (int i = 0; i < tabelDatas.Columns.Count; i++) { DataColumn column = tabelDatas.Columns[i]; rowHeader.CreateCell(i).SetCellValue(column.Caption); } short decimalformat = HSSFDataFormat.GetBuiltinFormat("0.00"); short dateformat = wb.CreateDataFormat().GetFormat(myDateFormat); ICellStyle styleDecimal = wb.CreateCellStyle(); styleDecimal.DataFormat = decimalformat; ICellStyle styleDate = wb.CreateCellStyle(); styleDate.DataFormat = dateformat; ICellStyle styleNormal = wb.CreateCellStyle(); for (int i = 0; i < tabelDatas.Rows.Count; i++) { DataRow dr = tabelDatas.Rows[i]; IRow ir = sheet.CreateRow(i + 1); for (int j = 0; j < dr.ItemArray.Length; j++) { ICell icell = ir.CreateCell(j); object cellValue = dr[j]; Type type = cellValue.GetType(); if (type == typeof(decimal) || type == typeof(double) || type == typeof(int) || type == typeof(float)) { icell.SetCellValue(Convert.ToDouble(cellValue)); icell.CellStyle = styleDecimal; } else if (type == typeof(DateTime)) { icell.SetCellValue(Convert.ToDateTime(cellValue).ToString(myDateFormat)); icell.CellStyle = styleNormal; } else if (type == typeof(bool)) { icell.SetCellValue(Convert.ToBoolean(cellValue) ? "是" : "否"); icell.CellStyle = styleNormal; } else { icell.SetCellValue(cellValue.ToString()); icell.CellStyle = styleNormal; } } } using (FileStream fs = File.OpenWrite(excelPathAll)) { wb.Write(fs); } return true; } #endregion DataTable导出Excel 和Excel读取到DataTabel #region DataTabel导出Csv 和CSV文件读取到DataTable /// <summary> /// Csv文件读取到DataTable /// </summary> /// <param name="filePath">csv文件路径</param> /// <param name="n">表示第n行是字段title,第n+1行是记录开始(首行是标题传0)</param> /// <returns>可选参数表示最后K行不算记录默认0</returns> public static DataTable GetDataTableByCsvPath(string filePath, int n) { DataTable dt = new DataTable(); String csvSplitBy = "(?<=^|,)(\"(?:[^\"]|\"\")*\"|[^,]*)"; StreamReader reader = new StreamReader(filePath, System.Text.Encoding.Default, false); int i = 0, m = 0; reader.Peek(); while (reader.Peek() > 0) { m = m + 1; string str = reader.ReadLine(); if (m >= n + 1) { if (m == n + 1) //如果是字段行,则自动加入字段。 { MatchCollection mcs = Regex.Matches(str, csvSplitBy); foreach (Match mc in mcs) { if (dt.Columns.Contains(mc.Value)) { dt.Columns.Add(mc.Value + "2"); //增加列标题 } else { dt.Columns.Add(mc.Value); } } } else { MatchCollection mcs = Regex.Matches(str, "(?<=^|,)(\"(?:[^\"]|\"\")*\"|[^,]*)"); i = 0; System.Data.DataRow dr = dt.NewRow(); foreach (Match mc in mcs) { dr[i] = mc.Value; i++; } dt.Rows.Add(dr); //DataTable 增加一行 } } } return dt; } /// <summary> /// 将DataTable导出为Csv文件 /// </summary> /// <param name="dt">数据</param> /// <param name="savaPath">保存的路径</param> /// <param name="strName">文件名称</param> /// <returns></returns> public static string ExportCsvByDataTabel(System.Data.DataTable dt, string savaPath, string strName) { //保存到本项目文件夹下 //string strPath = Path.GetTempPath() + strName + ".csv"; //保存到指定目录下 string strPath = savaPath + "\\" + strName + ".csv"; if (File.Exists(strPath)) { File.Delete(strPath); } //先打印标头 StringBuilder strColu = new StringBuilder(); StringBuilder strValue = new StringBuilder(); int i = 0; try { StreamWriter sw = new StreamWriter(new FileStream(strPath, FileMode.CreateNew), Encoding.GetEncoding("GB2312")); for (i = 0; i <= dt.Columns.Count - 1; i++) { strColu.Append(dt.Columns[i].ColumnName); strColu.Append(","); } //移出掉最后一个,字符 strColu.Remove(strColu.Length - 1, 1); sw.WriteLine(strColu); foreach (DataRow dr in dt.Rows) { //移出 strValue.Remove(0, strValue.Length); for (i = 0; i <= dt.Columns.Count - 1; i++) { strValue.Append(dr[i].ToString()); strValue.Append(","); } //移出掉最后一个,字符 strValue.Remove(strValue.Length - 1, 1); sw.WriteLine(strValue); } sw.Close(); //打开文件 //System.Diagnostics.Process.Start(strPath); return strPath; } catch (Exception ex) { return ""; } } #endregion DataTabel导出Csv 和CSV文件读取到DataTable #region 导出excel 【使用NPOI库】 /// <summary> /// DataTable转存为Excel文件【使用NPOI库】 /// </summary> /// <param name="dt"></param> /// <param name="filePath"></param> public static void GetExcelByDataTable(DataTable dt, string filePath) { // 创建一个新的Excel工作簿 IWorkbook workbook = new XSSFWorkbook(); // 创建一个新的工作表并命名为“Sheet1” ISheet worksheet = workbook.CreateSheet("Sheet1"); // 将DataTable的列名写入工作表中 IRow headerRow = worksheet.CreateRow(0); for (int i = 0; i < dt.Columns.Count; i++) { ICell cell = headerRow.CreateCell(i); cell.SetCellValue(dt.Columns[i].ColumnName); } // 将DataTable的数据写入工作表中 for (int i = 0; i < dt.Rows.Count; i++) { IRow dataRow = worksheet.CreateRow(i + 1); for (int j = 0; j < dt.Columns.Count; j++) { ICell cell = dataRow.CreateCell(j); cell.SetCellValue(dt.Rows[i][j].ToString()); } } // 保存Excel文件 using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write)) { workbook.Write(fileStream); } } /// <summary> /// 将excel导入到datatable /// </summary> /// <param name="filePath">excel路径</param> /// <param name="isColumnName">第一行是否是列名</param> /// <returns>返回datatable</returns> public static DataTable GetDataTableByExcel(string filePath, bool isColumnName) { DataTable dataTable = null; FileStream fs = null; DataColumn column = null; DataRow dataRow = null; IWorkbook workbook = null; ISheet sheet = null; IRow row = null; ICell cell = null; int startRow = 0; try { using (fs = File.OpenRead(filePath)) { // 版本后缀控制 if (filePath.IndexOf(".xlsx") > 0) workbook = new XSSFWorkbook(fs); // 版本后缀控制 else if (filePath.IndexOf(".xls") > 0) workbook = new HSSFWorkbook(fs); if (workbook != null) { sheet = workbook.GetSheetAt(0);//读取第一个sheet,当然也可以循环读取每个sheet dataTable = new DataTable(); if (sheet != null) { int rowCount = sheet.LastRowNum;//总行数 if (rowCount > 0) { IRow firstRow = sheet.GetRow(0);//第一行 int cellCount = firstRow.LastCellNum;//列数 //构建datatable的列 if (isColumnName) { startRow = 1;//如果第一行是列名,则从第二行开始读取 for (int i = firstRow.FirstCellNum; i < cellCount; ++i) { cell = firstRow.GetCell(i); if (cell != null) { if (cell.StringCellValue != null) { column = new DataColumn(cell.StringCellValue); dataTable.Columns.Add(column); } } } } else { for (int i = firstRow.FirstCellNum; i < cellCount; ++i) { column = new DataColumn("column" + (i + 1)); dataTable.Columns.Add(column); } } //填充行 for (int i = startRow; i <= rowCount; ++i) { row = sheet.GetRow(i); if (row == null) continue; dataRow = dataTable.NewRow(); for (int j = row.FirstCellNum; j < cellCount; ++j) { cell = row.GetCell(j); if (cell == null) { dataRow[j] = ""; } else { //CellType(Unknown = -1,Numeric = 0,String = 1,Formula = 2,Blank = 3,Boolean = 4,Error = 5,) switch (cell.CellType) { case CellType.Blank: dataRow[j] = ""; break; case CellType.Numeric: short format = cell.CellStyle.DataFormat; //对时间格式(2015.12.5、2015/12/5、2015-12-5等)的处理 if (format == 14 || format == 31 || format == 57 || format == 58) dataRow[j] = cell.DateCellValue; else dataRow[j] = cell.NumericCellValue; break; case CellType.String: dataRow[j] = cell.StringCellValue; break; } } } dataTable.Rows.Add(dataRow); } } } } } return dataTable; } catch (Exception) { if (fs != null) { fs.Close(); } return null; } } public static void GetExcelByDataGridView(DataGridView dgv, string filePath) { // 创建一个新的Excel工作簿 IWorkbook workbook = new XSSFWorkbook(); // 创建一个新的工作表并命名为“Sheet1” ISheet worksheet = workbook.CreateSheet("Sheet1"); // 将DataTable的列名写入工作表中 IRow headerRow = worksheet.CreateRow(0); for (int i = 0; i < dgv.Columns.Count; i++) { ICell cell = headerRow.CreateCell(i); cell.SetCellValue(dgv.Columns[i].HeaderText); } // 将DataTable的数据写入工作表中 for (int i = 0; i < dgv.Rows.Count; i++) { IRow dataRow = worksheet.CreateRow(i + 1); for (int j = 0; j < dgv.Columns.Count; j++) { ICell cell = dataRow.CreateCell(j); cell.SetCellValue(dgv.Rows[i].Cells[j].ToString()); } } // 保存Excel文件 using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write)) { workbook.Write(fileStream); } } #endregion /// <summary> /// /// </summary> /// <param name="filePath"></param> /// <param name="ht">Hashtable的key与Excel文件中的名称对应</param> /// <param name="sheetIndex"></param> public static void WriteHashtable(string filePath, Hashtable ht, int? sheetIndex = null) { if (ht == null) { return; } IWorkbook fileWorkbook; using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { if (filePath.Last() == 's') { try { fileWorkbook = new HSSFWorkbook(fs); } catch (Exception ex) { //logger.Error("打开Excel文件失败!", ex); throw ex; } } else { try { fileWorkbook = new XSSFWorkbook(fs); } catch { fileWorkbook = new HSSFWorkbook(fs); } } } foreach (DictionaryEntry dictEntry in ht) { string strKey = dictEntry.Key.ToString(); string strValue = dictEntry.Value as string; List<string> lstValue = dictEntry.Value as List<string>; if (strValue != null) { IName name1 = fileWorkbook.GetName(dictEntry.Key.ToString()); CellReference cr2 = new CellReference(name1.RefersToFormula); ICell cell2 = fileWorkbook.GetSheet(cr2.SheetName).GetRow(cr2.Row).GetCell(cr2.Col); cell2.SetCellValue(strValue); } else if (lstValue != null) { IName name1 = fileWorkbook.GetName(dictEntry.Key.ToString()); if (name1 == null) { //logger.Warn("名称为null:" + dictEntry.Key.ToString()); continue; } CellReference cr2 = new CellReference(name1.RefersToFormula); var cellSheet = fileWorkbook.GetSheet(cr2.SheetName); var cellRow = cellSheet.GetRow(cr2.Row); int iRowCount = (int)Math.Ceiling((double)lstValue.Count / cellRow.Cells.Count); int iCurRow = -1; for (int rowIndex = 0; rowIndex < iRowCount; rowIndex++) { iCurRow = cr2.Row + rowIndex + 1; var newRow = cellSheet.GetRow(iCurRow); if (iCurRow > cellSheet.LastRowNum) { cellSheet.CreateRow(iCurRow); } else { cellSheet.ShiftRows(iCurRow, cellSheet.LastRowNum, 1, true, false); } newRow = cellSheet.GetRow(iCurRow); newRow.Height = cellRow.Height; for (int colIndex = 0; colIndex < cellRow.Cells.Count; colIndex++) { var cellsource = cellRow.GetCell(colIndex); var cellInsert = newRow.CreateCell(colIndex); var cellStyle = cellsource.CellStyle; //设置单元格样式 if (cellStyle != null) { cellInsert.CellStyle = cellsource.CellStyle; if (lstValue.Count > rowIndex * cellRow.Cells.Count + colIndex) { if (lstValue[rowIndex * cellRow.Cells.Count + colIndex] == "虚拟出库" || lstValue[rowIndex * cellRow.Cells.Count + colIndex] == "虚拟退库") { //设置单元格信息 //cellsource.CellStyle.FillPattern = FillPattern.SolidForeground; //cellsource.CellStyle.FillForegroundColor = 10; ICellStyle boldStyle = fileWorkbook.CreateCellStyle(); boldStyle.FillPattern = FillPattern.SolidForeground; boldStyle.FillForegroundColor = 10; boldStyle.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center; boldStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center; cellInsert.CellStyle = boldStyle; } } } if (rowIndex * cellRow.Cells.Count + colIndex >= lstValue.Count) { break; } cellInsert.SetCellValue(lstValue[rowIndex * cellRow.Cells.Count + colIndex]); } } } } using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) { fileWorkbook.Write(fs); fs.Flush(); } } /// <summary> /// 根据Excel和Sheet返回DataTable /// </summary> /// <param name="filePath">Excel文件地址</param> /// <param name="sheetIndex">Sheet索引</param> /// <returns>DataTable</returns> public static DataTable GetDataTable(string filePath, int sheetIndex) { return GetDataSetByExcelPath(filePath, sheetIndex).Tables[0]; } } }