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

Apache POI SXSSFWorkbook日期样式不生效问题求助

使用SXSSFWorkbook时日期样式失效的问题

我们的应用基于Apache POI生成Excel表格,因需生成超15万行的大型表格,原XSSFWorkbook导致内存占用飙升至3GB以上,因此切换为滑动窗口模式的SXSSFWorkbook。

大部分功能符合预期(列自动调整需在创建工作表后调用trackAllColumnsForAutoSizing()),但出现核心问题:日期样式设置完全不生效。

现有日期样式创建代码

protected CellStyle createDateCellStyle() {
    SXSSFCreationHelper createHelper = (SXSSFCreationHelper)workbook.getCreationHelper();
    CellStyle cellStyle = workbook.createCellStyle();
    cellStyle.setDataFormat(createHelper.createDataFormat().getFormat("dd.MM.yyyy"));
    return cellStyle;
}

(已尝试将CreationHelper替换为SXSSFCreationHelper,无效果)

单元格样式赋值代码

cell.setCellStyle(dateStyle);

本该显示为日期的单元格全部以整数形式展示,相同代码在XSSFWorkbook全内存模式下完全正常。

当前环境:Java 8、POI 5.2.3(最新版本)、Tomcat 7。


修复方案

这是SXSSF的已知问题,根源在于SXSSF对内置格式与自定义格式的处理逻辑存在差异,直接通过格式字符串获取格式索引无法正确关联日期类型。

方案1:使用内置日期格式索引

POI提供预定义的日期格式索引,直接使用可绕过自定义格式的适配问题:

protected CellStyle createDateCellStyle() {
    CellStyle cellStyle = workbook.createCellStyle();
    // 选用内置的日期格式索引,示例为"dd/mm/yyyy"
    cellStyle.setDataFormat((short)14); 
    return cellStyle;
}

常用内置日期格式索引参考:

  • (short)14: dd/mm/yyyy
  • (short)22: m/d/yy h:mm
  • (short)17: h:mm

方案2:正确注册自定义日期格式

若必须使用自定义格式字符串,需操作SXSSF底层的XSSFWorkbook完成格式注册,并明确指定格式类型:

protected CellStyle createDateCellStyle() {
    // 获取SXSSF包装的底层XSSFWorkbook
    XSSFWorkbook xssfWorkbook = (XSSFWorkbook) ((SXSSFWorkbook)workbook).getXSSFWorkbook();
    XSSFCreationHelper createHelper = xssfWorkbook.getCreationHelper();
    XSSFCellStyle cellStyle = xssfWorkbook.createCellStyle();
    
    // 注册自定义日期格式,避免与内置格式冲突
    XSSFDataFormat dataFormat = xssfWorkbook.createDataFormat();
    short formatIndex = dataFormat.getFormat("dd.MM.yyyy");
    // 关键:明确标记格式类型为日期
    xssfWorkbook.getStylesSource().getNumberFormatAt(formatIndex).setFormatType(FormatType.DATE);
    
    cellStyle.setDataFormat(formatIndex);
    return cellStyle;
}

额外注意事项

  • 避免重复创建大量CellStyle,POI对单元格样式数量有限制,建议全局复用样式对象
  • 赋值日期单元格时,确保传入Date或POI支持的LocalDateTime类型,而非直接传入数字:
// 正确的日期赋值示例
cell.setCellValue(new Date());
// 或POI 5+支持的LocalDateTime
cell.setCellValue(LocalDateTime.now());

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 08:24:56