要回答您的问题,是的,在处理大型 XLSX 文件时,POI 总是会使用非常大量的内存,这比 XLSX 文件的大小要大得多。我认为这不会很快改变,并且有很明显的原因:XLSX 基本上是一堆压缩的 XML 文件,并且 XML 被很好地压缩(大约 10 倍)。让这个 XML 不压缩地放在内存中已经使内存消耗增加了十倍,所以如果你添加数据结构的所有开销,你不可能期望内存消耗比 XLSX 文件大小增加 10%。
现在,好消息是,正如评论中提到的,Apache POI 引入了SXSSF,用于在电子表格中流式传输大量数据,具有非常好的性能和低内存使用率。以这种方式生成的 XLSX 文件仍然在硬盘上流式传输,最终可能会占用相当多的空间,但至少在写入数十万行时不会冒 OOME 的风险。
您的问题是您将无法让 JETT 直接使用 SXSSF,因为它需要将整个文档加载到内存中以执行模板填充。JETT作者在这里快速讨论了这个话题。
我遇到了同样的问题,最后做了两步 XLSX 创建:
用于生成标题和格式的标准 JETT XLSX 模板。第一张表的最后一行包含带有 $$tokens$$ 的单元格,每个单元格一个。我不使用 JETT 插入大量行。
JETT 完成工作后,我重新打开工作簿,阅读并删除第一个电子表格最后一行的 $$tokens$$,然后开始使用 SXSSF 逐行流式传输数据。
当然,这种方法有一些限制: - 在行插入期间,您不能在任何流式行上使用 JETT(但您之前可以,例如动态选择 $$tokens$$ 的顺序) - 单元格格式不会除非您使用 POI API 自己处理,否则不会被复制。我个人更喜欢在我的 XLSX 文件中格式化整个列,它将应用于流数据。
如果您想使用通过 SXSSF 插入的数据显示图表,这也适用:您可以使用函数 OFFSET 和 COUNTA 定义一个命名范围,然后创建一个数据透视表和数据透视图,当在 Excel 中打开 XLSX 时将刷新该数据透视表和数据透视图。