500 个 Excel 文件汇总计算的效率提升

如题,在 SPL 主目录下有一个 TrialBalance 文件夹,包含 500 个格式一致的 xlsx 文件。文件的格式如下所示:

imagepng

表格有 10 列,425 行,要求对 500 个文件的 C16:J425 这个区域中对应的单元格对位相加,汇总后保持源格式输出。需要汇总计算的单元格区域中,有些单元格的值 "***“,汇总后需保持”***",而不是 1500 个星号,如果是空单元格,保持空,其它的单元格都是数值,需相加后填入。一个简单的汇总计算,类似案例,在官网中也有,地址如下:

4.23 汇总文件 - 按单元格位置对位汇总 - 文件个数不定

这是一个很好的启蒙案例。但有个问题,用 xlsopen 效率不理想,如果用案例中的方法来汇总此例中的 500 个文件,需耗时 100 多秒(本机 10G 内存,配置一般)。我想到了用游标的方式来读取,把每一个文件中的区域读成嵌套序列,对位相加后汇总到一个总的序列,再用 xlscell 把这个序列写出去,代码如下:

A B
1 =now()
2 =[${fill(",",408)}] // 创建长度为 409 的序列
3 =directory@p("TrialBalance\\*.xlsx") // 获取 500 个 xlsx 文件的路径
4 =A3.(file(~).xlsimport@c(;,17:)) // 批量获取成游标,每个表的 17 行开始
5 >A4.run@m(~.fetch().array().m(2:).(A2.modify(#,[A2(#)++~.m(3:).(if(~=="***",null,~))]))) // 循环 fetch 数据的同时,对序列 A2 对位相加
6 >a=file(A3(1)).xlsopen(),a.xlscell("C17":,1;A2) // 选择任意一个文件 open 成对象,写入 A2 序列
7 =file("Output.xlsx").xlswrite(a) // 输出结果
8 =interval@ms(A1,now()) // 本机 10G 内存,耗时 12578 毫秒

用游标的方法,效率有明显提升,本机 10G 内存耗时 13 秒。

发此帖的目的是想求助大佬指导:

  • 代码格 A5 中,run@m() 多线程似乎对效率提升没有助益,本机最多 4 个线程,且在集算器中也设置成了最多 4 线程;
  • 代码格中对 A2 序列的修改,用赋值法 A2(#)=A2(#)++~ 和用 modify 方法 A2.modify(#,[A2(#)++~]) 有没有效率上的差异,还有没有其他更好的写法?我猜测这两种写法在效率上是一样的。不像序列的拼接运算和 insert,前者会产生新的对象,而后者只是修改源对象。
  • 把 A5 里的语句嵌套放进 A4 似乎会快一些,这是不是错觉?应该不至于在执行 A5 的时候又执行一次 A4 吧?
  • 还有没有其它写法,可以让 xlsx 文件的处理效率有所提升,比如本机 10G 内存能否把效率提升到 10 秒以内。16G 内存的机器,代码执行效率似乎要快很多,最快能到 5 秒。我想依靠代码而不是硬件来提升效率。
  • 代码效率不是很稳定,第一次执行时会慢一些,第二次执行会快很多,后续执行效率波动不会很大。

恳请大佬们得闲时给予帮助指导,谢谢!

excel 文件已打包附上,只有 10 个,500 个打包太大了,上传不了,若要测试,复制 500 个就行:

TrialBalancezip