NPOI保留EXCEL公式并赋值导出
使用NPOI操作EXCEL时,单元格内相关公式需要执行特定代码去保留,同时针对模板写入数据后导出的文件,需要通过代码执行,否则导出内容不会触发公式的计算
核心代码
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. 获取公式求值器
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();
More info: Learnerping的个人微博

浙公网安备 33010602011771号