使用Apache POI批量生成Excel时出现styles.xml样式损坏丢失问题
问题根因
- 跨Workbook复用样式对象:你标注的样式代码仅执行一次,意味着所有生成的文档共用了首次创建时绑定到第一个Workbook的CellStyle、Font实例,而Apache POI中XSSFCellStyle、XSSFFont都是和单个Workbook实例强绑定的,不能跨Workbook使用,后续生成的文档写入时会因为样式归属异常导致styles.xml结构损坏。
- 输出流关闭顺序错误:保存逻辑中先执行了
workbook.close()再执行outputStream.flush(),此时Workbook关联的资源已经释放,可能导致输出的文件尾部数据不完整。 - 若
getArial10Bold方法返回的Font对象也是全局仅创建一次,同样存在跨Workbook复用的问题。
修复方案
- 每次读取新的Workbook模板后,单独为当前Workbook实例执行一遍样式创建逻辑,禁止跨Workbook复用CellStyle、Font、DataFormat实例。
- 修正文件保存的资源关闭顺序,先刷写、关闭输出流,再关闭Workbook,也可以直接用try-with-resources自动处理资源关闭,修正后的保存代码参考:
public static void saveWorkbook(XSSFWorkbook workbook, String path) { try (FileOutputStream outputStream = new FileOutputStream(path)) { workbook.write(outputStream); } catch (IOException e) { e.printStackTrace(); } finally { try { workbook.close(); } catch (IOException e) { e.printStackTrace(); } } }
- 调整
getArial10Bold方法逻辑,每次调用时为传入的当前Workbook实例创建新的Font对象,禁止全局复用Font实例,参考实现:
private XSSFFont getArial10Bold(XSSFWorkbook workbook) { XSSFFont font = workbook.createFont(); font.setFontName("Arial"); font.setFontHeightInPoints((short)10); font.setBold(true); return font; }
- 可额外对模板文件做一次预校验:用Excel打开模板文件,执行一次“保存”操作排除模板本身存在隐性格式错误的可能。
内容的提问来源于stack exchange,提问作者POP3
相关产品推荐
相关产品推荐

