使用NPOI操作EXCEL时,单元格内相关公式需要执行特定代码去保留,同时针对模板写入数据后导出的文件,需要通过代码执行,否则导出内容不会触发公式的计算
核心代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| using (var file = new FileStream(strTemplate, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { // 直接读取模板的完整Workbook,包含所有样式、公式、格式 xssfWorkbook = new XSSFWorkbook(file); }
/// <summary> /// 核心赋值方法(保留模板格式和公式) /// </summary> /// <param name="dto">导出数据DTO</param> /// <param name="sheet">目标工作表</param> private void SetSheetCellValue(BIReportDto dto, XSSFSheet sheet, int dateVal) // 替换YourDtoType为实际DTO类名 { // ========== 通用赋值工具方法(核心:避免重复代码,保留样式/公式) ========== void SetCellValue(int rowIndex, int cellIndex, object value) { // 1. 获取行(优先用模板已有行,不新建) IRow row = sheet.GetRow(rowIndex); if (row == null) { row = sheet.CreateRow(rowIndex); // 若新建行,继承模板行高(可选,根据模板调整) row.Height = sheet.GetRow(rowIndex)?.Height ?? row.Height; }
// 2. 获取单元格(优先用模板已有单元格,不新建) ICell cell = row.GetCell(cellIndex); if (cell == null) { cell = row.CreateCell(cellIndex); // 关键:复制模板单元格样式(保留字体/颜色/边框/数字格式) ICell templateCell = sheet.GetRow(rowIndex)?.GetCell(cellIndex); if (templateCell != null) { cell.CellStyle = templateCell.CellStyle; } }
// 3. 跳过公式单元格(防止覆盖模板公式) if (cell.CellType == CellType.Formula) { return; }
// 4. 安全赋值(处理空值+类型转换) try { switch (value) { case null: cell.SetCellValue(0); // 空值默认赋值0 break; case int intVal: cell.SetCellValue(intVal); break; case double doubleVal: cell.SetCellValue(doubleVal); break; case decimal decimalVal: cell.SetCellValue(Convert.ToDouble(decimalVal)); break; case string strVal: // 字符串转数值(兼容DTO中string类型的数值字段) if (double.TryParse(strVal, out double strToDouble)) { cell.SetCellValue(strToDouble); } else { cell.SetCellValue(strVal); // 非数值字符串直接赋值 } break; default: cell.SetCellValue(value.ToString()); break; } } catch (Exception ex) { // 赋值异常兜底(避免单个单元格错误导致整体失败) cell.SetCellValue(0); // 可选:记录日志 // LogHelper.Error($"单元格[{rowIndex},{cellIndex}]赋值失败:{ex.Message}"); } } }
|
对字段进行赋值之后需要手动刷新,才能让列表中公式执行,并在导出内容中展示计算结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| // 1. 获取公式求值器 IFormulaEvaluator evaluator = xssfWorkbook.GetCreationHelper().CreateFormulaEvaluator();
// 2. 刷新所有公式 evaluator.EvaluateAll(); // 这一步会计算所有公式的当前值
using (var fileStream = new FileStream(strFile, FileMode.Create, FileAccess.Write)) { xssfWorkbook.Write(fileStream); // 强制刷新缓冲区,确保完整写入 fileStream.Flush(); }
// 释放资源(避免内存泄漏) xssfWorkbook.Close();
|