在 xlsx 工作簿中,有一些单元格包含一些无界的 SUMIF 公式,如下所示:SUMIF(MySheetname!$B:$B,$E4,MySheetname!$I:$I)
. 使用 Apache POI 5.0.0 对一个 SUMIF 函数的评估持续 100 毫秒,对给定工作簿的评估持续几分钟。
提高执行持续时间的一种方法是将公式绑定到以下内容:SUMIF(MySheetname!$B1:$B100,$E4,MySheetname!$I1:$I100)
. 在我的情况下,这不是一个解决方案,因为我不是 xlsx 文件的作者,并且系统从未知的人那里获取未知的 xlsx 文件(所以我不能只告诉他们限制 SUMIF 范围)。
当前的实现org.apache.poi.ss.formula.functions.Sumif
迭代给定(无界)范围内的所有单元格,因此每次评估迭代 1048576 个单元格。
这是方法实现的一部分sumMatchingCells(AreaEval, I_MatchPredicate, AreaEval)
:
for (int r=0; r<height; r++) {
for (int c=0; c<width; c++) {
result += accumulate(aeRange, mp, aeSum, r, c);
}
}
我想通过检查行或列是否实际存在于总和范围中来提高此方法的性能。也许是这样的(使用不存在的方法sheetContainsRowIndex
):
for (int r = 0; r < height; r++) {
if (aeSum.sheetContainsRowIndex(aeSum.getFirstRow() + r)) {
for (int c = 0; c < width; c++) {
if (aeSum.sheetContainsColumnIndex(aeSum.getFirstColumn() + c)) {
[...]
LazyAreaEval
包含 aSheetRangeEvaluator
并且 this 包含SheetRefEvaluator
s 并且这些包含 an并且EvaluationSheet
this 至少知道getLastRowNum()
. 不幸的是,这个属性链是私有的。
知道如何实现这一目标吗?或任何其他想法如何提高 SUMIF 执行的性能?