求助: 流式输出大型 Excel 文件

不好意思,我问题比较多,见谅🙏 不过,这也说明我是真的很认真的在使用集算器😄

前几天求助了流式读大型 Excel 文件,这次是关于流式输出大型 Excel 的问题,这里说的大型是指大几万行以上,二三十列的那种。没办法,这种低效存储格式毒害表哥表妹 40 年早已遍布各种办公场景,已经不可回避。

当前,集算器流式输出 Excel 格式有两种方法,我在使用时发现了一些问题:

第一种:file().xlsexport@act()

注意此时是 "文件. 输出 @c",当该文件不存在时会自动新建,如果存在文件时可以通过 @a 选项进行追加式输出。先读了一个 9 万多行 24 列的文件成游标,然后输出成 Excel 格式,为了测试需要,先不管操作流程是否合理,以下语句用追加输出的方式执行 3 次,

imagepng

第一次执行时,因为没有 2017.xlsx 这个文件,语句自动新建并输出到了结果表,耗时也符合预期;

当执行第二次时,耗时陡增,追加同样的 9 万多行,耗时一下子变成 50 秒左右,但结果依然符合预期;

当执行第三次时,报错了,文件读取错误,但依然会输出一个文件,但这个文件的结果是不一样的,连指定的表名称也变了,行数就是游标的 9 万多行,并没有追加,看样子是重新生成了另一个文件。

三次运行的耗时如下所示:

imagepng

第三次运行报错后输出的文件如下:

imagepng

我在想,追加的时候是不是要先打开这个文件,所以第二次运行的时候,因为要打开那个 9 万多行的文件所以一下子耗时就增加了,当运行第三次时,因为文件已有 18 多万行,太大了,打开的时候报错了。

那像这种情况,干脆让程序直接报错后中断运行,就说文件太大,此方法不合适,别再生成新文件了,这样行不行?

文档里也说了”使用流式写出大文件,当文件 f 存在时,文件 f 需要支持被写入,且不能过大“,其实我是有心理准备的,但不知道到底多大是大,什么样的是不过于大,所以干脆报错中断,省了麻烦。

第二种:XO@w.xlsexport

这里的 XO 是指一个 Excel 文件以流式方法写的 open 对象,要用 file.xlsopen@w() 先打开。这个方法非常好,在某些情形下还可以多线程写出,比如当前工作簿中输出至不同的工作表,就可以并行,能节省老多时间。

但有一个问题,file.xlsopen@w 每一次都是重新生成一个 file,写的时候不管是不是追加的模式,只要是 @w 的方式,原先存在的文件也会被抹掉,我不知道有没有弄错,比如以下语句:

imagepng

第一次运行时不存在要写出的 2017.xlsx 文件,运行后,会生成 5 个工作表,结果符合预期:

imagepng

然后,再执行上述同样的语句,此时 2017.xlsx 这个文件已经存在,我预想的是 @a 会追加数据,但运行后并没有追加,应该是重新写了一个新的。

所以,xlsopen@w()是生成新的 excel 写入对象,那如果要往一个已有的大型 excel 文件上追加数据要如何操作?file.xlsexport@ac() 这个方法有限制,所以,xlsopen@w 能不能把已有文件打开成写入模式且不抹除数据?

暂时就想到这么多,有其他的我再补充。恳请大佬们帮忙看看,给予指导🙏

再说个题外的😄
无意中发现了一个 Apache 软件基金会孵化器项目 Apache Fesod 2.0
https://fesod.apache.org
说是专门为 Java 生态提供高性能 Excel 处理能力的开源库,原型是阿里巴巴开发的 EasyExcel,今年年初捐给了 Apache 软件基金会,成为了孵化器项目,看介绍也是依赖于 POI 5.5.1,但比 POI 更高效。我没别的意思哈,只是觉得 POI 也是 20 年的老项目了,性能也是中等稍偏上,依赖于集算器的多线程并行能力,读入和写出才像样一些。想着如果能进一步提高对 excel 文件的处理效率,也是一件好事。当然这还是个孵化器项目,还不是那种像 POI 已经定型的 Top-Level-Project,对产品稳定性可能有风险,哈哈,只是一个题外话,莫怪🙏