1

上一篇文章的补充。解决遗留问题:

对mergedRegionHelper完成改造之后,不能支持模板配置为一行多个结果集、并且结果集都存在合并单元格的情况。比如:

image.png

导出数据,系统会报错:
image.png

分析了一下,是因为我们虽然修改mergedRegionHelper的算法,在插入行之后不再对缓存数据做调整、而是记录了插入的行数,但是因为easypoi处理模板的的方式是从上到下、从左到右逐行、逐列处理模板的单元格。

如上图的模板,当处理到第2行第一列的时候碰到foreash,如果我们给的数据集多于1条数据的话,就会插入行、调用mergedRegionHelper的shiftrow方法从而更新掉我们新增的属性rowsSfhited。当继续处理到第2行的第二个foreach的时候,调用mergedRegionHelper判断是否是合并单元格的时候就会出问题,因为这个时候mergedRegionHelper的rowsShifted已经被更新了:

    public boolean isMergedRegion(int row, int col) {
        //20230211 new added SHIFTMETHOD_KEEP_MERGEDCACHE
        if(shiftMethod == SHIFTMETHOD_KEEP_MERGEDCACHE)
            row -= rowsShifted;
        return mergedCache.containsKey(row + "_" + col);
    }

想要判断的是第2行的数据,但是实际并不是第2行,所以导致错误。

解决bug

仔细分析一下修改后的mergedRegionHelper逻辑,其实我们只要能做到当一行数据处理完成、准备处理下一行数据的时候,更新mergedRegionHelper的rowsShfited属性,就不会有问题了。

所以我们就找到这个逻辑的位置,在ExcelExportOfTemplateUtil#parseTemplate方法,需要初始化新增变量shiftCache(shiftCache是为了支持单行多个数据集而引入的缓存变量,用来记录每一个foreach行插入了多少行数据):
image.png
然后在循环处理当前行所有列结束、要跳转到下一行的循环前,处理mergedRegionHelper:

for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) {
                if (row.getCell(i) != null && !tempCreateCellSet
                        .contains(row.getRowNum() + "_" + row.getCell(i).getColumnIndex())) {
                    setValueForCellByMap(row.getCell(i), map);
                }
            }
            //20230212 check shifed rows from shiftCache and set to mergedRegionHelper
            // when we moved to the next row
            if(shiftCache.get(row.getRowNum()+1)!=null){
                mergedRegionHelper.shiftRows(sheet, row.getRowNum(), shiftCache.get(row.getRowNum()+1), sheet.getLastRowNum());
            }

重跑,成功得到结果:
image.png

上一篇 easypoi 模板导出时的公式及foreach合并单元格问题
下一篇 Quartz 相关线程


45 声望17 粉丝