You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache POI 5.0 XSSF单元格修改字体无法保存问题求助

问题分析与解决方案

你的问题核心在于Apache POI中Font是工作簿级别的共享对象,直接通过CellStyle.getFont()修改属性会影响所有引用该Font的单元格样式,而不是当前CellStyle独有的设置。

为什么会出现这种情况?

在你的代码逻辑里:

  • 每次调用writeCell时,你传入wb.createCellStyle()创建的新样式,再通过newStyle.cloneStyleFrom(cell.getCellStyle())复制原样式。但这一步复制的只是样式的引用,新样式的Font还是原单元格样式的Font实例,并没有被克隆成新对象。
  • 当你执行newStyle.getFont().setFontHeightInPoints(...)时,修改的是这个共享Font实例的属性。后续处理其他单元格时,如果又把该Font的字号改回20,所有使用这个Font的单元格都会同步变成20号字——这就是测试点0(单个单元格处理后)显示正确,但所有单元格处理完成后(测试点1)全部变回默认字号的根本原因。

修复方案

你需要为每个需要不同字号的样式创建独立的Font实例,而不是直接修改共享的Font对象。修改后的writeCell方法如下:

private void writeCell(Student stu, XSSFCell cell, XSSFCellStyle newStyle) {
    // 复制原单元格样式的基础属性
    newStyle.cloneStyleFrom(cell.getCellStyle());
    cell.setCellValue(stu.getName());
    
    // 关键修复:创建新的Font实例,克隆原Font的所有属性
    XSSFFont originalFont = cell.getCellStyle().getFont();
    XSSFFont newFont = cell.getSheet().getWorkbook().createFont();
    newFont.cloneStyleFrom(originalFont);
    
    // 修改新Font的字号
    newFont.setFontHeightInPoints((short) (stu.isLongName() ? 17 : 20));
    
    // 将新Font绑定到当前样式
    newStyle.setFont(newFont);
    
    // 填充颜色逻辑保持不变
    newStyle.setFillForegroundColor(stu.isBoarding() ? IndexedColors.PALE_BLUE.getIndex() : IndexedColors.LIGHT_GREEN.getIndex());
    newStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
    
    cell.setCellStyle(newStyle);
}

额外优化建议

考虑到Excel格式对工作簿中CellStyle和Font的数量有上限,你可以提前缓存不同字号+颜色组合的样式,避免重复创建对象:

  • 维护一个Map,用「字号+颜色标识」作为键,对应的CellStyle作为值。
  • 处理单元格时,先检查Map中是否已有对应样式,没有再创建并存入Map。

这样修改后,每个需要不同字号的单元格都会使用独立的Font实例,字号设置就能正确保存到输出文件中了。

内容的提问来源于stack exchange,提问作者RocketDev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 23:37:44