[alibaba/easyexcel]同时使用合并单元格和模板填充导出文件后, 打开导出的文件Excel会触发自动修复

2024-05-21 326 views
0

触发场景描述 使用 OnceAbsoluteMergeStrategy 为 ExcelWriter 指定合并策略后, 再使用 excelWriter.fill(); 进行多次填充, 即执行多个 ExcelWriter.fill(); 后, 生成的 Excel 文件会触发 MS Office 的自动修复, 点击修复后看到的修复记录如下: 已删除的记录: /xl/worksheets/sheet1.xml 部分的 合并单元格. 将生成的.xlsx 文件改为.zip 解压后查看/xl/worksheets/sheet1.xml 文件发现使用 OnceAbsoluteMergeStrategy 指定的合并单元格策略被执行了多遍, 即有几次 excelWriter.fill();方法调用就执行了几遍. 触发Bug的代码

   OnceAbsoluteMergeStrategy mergeStrategy = new OnceAbsoluteMergeStrategy(3, 3, 0, 0);
            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
                .withTemplate(templateFileName)
                .registerWriteHandler(mergeStrategy)
                .build();
  excelWriter.fill(map, writeSheet);
            excelWriter.fill(new FillWrapper("list1", title), writeSheet);

提示的异常或者没有达到的效果 如场景描述所提及

回答

0

如执行两次 excelWriter.fill(); 后的 xml 文件如下

<mergeCells count="2"><mergeCell ref="A3:A9"/><mergeCell ref="A3:A9"/></mergeCells>
9

请提供全代码,是否和多次填充没关系。实测没问题。

8
代码如下

修改自 https://github.com/alibaba/easyexcel/blob/665f1e2f0e72a17da4b531326cfad4236149da05/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java, 增加了 OnceAbsoluteMergeStrategy mergeStrategy = new OnceAbsoluteMergeStrategy(3, 8, 0, 0);

/**
     * 多列表组合填充填充
     *
     * @since 2.2.0-beta1
     */
    @Test
    public void compositeFill() {

        OnceAbsoluteMergeStrategy mergeStrategy = new OnceAbsoluteMergeStrategy(3, 8, 0, 0);

        // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
        // {} 代表普通变量 {.} 代表是list的变量 {前缀.} 前缀可以区分不同的list
        String templateFileName =
            TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator
                + "composite.xlsx";

        String fileName =
            TestFileUtil.getPath() + "compositeFill" + System.currentTimeMillis() + ".xlsx";
        ExcelWriter excelWriter = EasyExcel.write(fileName).registerWriteHandler(mergeStrategy)
            .withTemplate(templateFileName).build();
        WriteSheet writeSheet = EasyExcel.writerSheet().build();
        FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL)
            .build();
        // 如果有多个list 模板上必须有{前缀.} 这里的前缀就是 data1,然后多个list必须用 FillWrapper包裹
        excelWriter.fill(new FillWrapper("data1", data()), fillConfig, writeSheet);
        excelWriter.fill(new FillWrapper("data1", data()), fillConfig, writeSheet);
        excelWriter.fill(new FillWrapper("data2", data()), writeSheet);
        excelWriter.fill(new FillWrapper("data2", data()), writeSheet);
        excelWriter.fill(new FillWrapper("data3", data()), writeSheet);
        excelWriter.fill(new FillWrapper("data3", data()), writeSheet);

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("date", "2019年10月9日13:28:28");
        excelWriter.fill(map, writeSheet);

        // 别忘记关闭流
        excelWriter.finish();
    }
sheet1.xml 文件如下
<mergeCells count="2"><mergeCell ref="A5:B5"/><mergeCell ref="A1:A4"/><mergeCell ref="A4:A9"/><mergeCell ref="A4:A9"/><mergeCell ref="A4:A9"/><mergeCell ref="A4:A9"/><mergeCell ref="A4:A9"/><mergeCell ref="A4:A9"/><mergeCell ref="A4:A9"/></mergeCells>

@zhuangjiaju

8

我也遇到了, 总是提示 让修复;只要 fill 和合并单元格 在一起 就出问题; 单独的 fill 没有问题;

9
        WriteSheet writeSheet = EasyExcel.writerSheet().build();
        excelWriter.fill(new FillWrapper("data", info.getDataList()), writeSheet);
        excelWriter.fill(map, writeSheet);
        excelWriter.finish();
2

合并单元格的类 public class ExcelMergeCellStrategy extends AbstractSheetWriteHandler { private List list;

public ExcelMergeCellStrategy(List<CellExtra> list) {
    this.list = list;
}

@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
    if (list == null || list.size() < 1) {
        return;
    }

    Sheet sheet = writeSheetHolder.getSheet();
    for (CellExtra extra : list) {
        if (extra.getType().equals(CellExtraTypeEnum.MERGE)) {
            CellRangeAddress address = new CellRangeAddress(extra.getFirstRowIndex(), extra.getLastRowIndex(), extra.getFirstColumnIndex(), extra.getLastColumnIndex());
            sheet.addMergedRegionUnsafe(address);
        }
    }
}

}

7

这个问题是合并单元格是默认开了不去校验就合并,你和合并的单元格和原有的单元格冲突了

0

这个问题是合并单元格是默认开了不去校验就合并,你和合并的单元格和原有的单元格冲突了

问题关键不在于和原有单元格冲突, 改成 OnceAbsoluteMergeStrategy mergeStrategy = new OnceAbsoluteMergeStrategy(30, 80, 0, 0); 不与原单元格冲突, 也还是一样会触发自动修复

5

楼主 这个问题最后解决没?