alibaba / easyexcel

快速、简洁、解决大文件内存溢出的java处理Excel工具
https://easyexcel.opensource.alibaba.com
Apache License 2.0
32.18k stars 7.5k forks source link

多列表组合填充填充场景出现数据填充丢失 #3282

Open mirocolo opened 1 year ago

mirocolo commented 1 year ago

建议先去看文档

快速开始常见问题

触发场景描述

多列表组合填充填充场景出现数据填充丢失

这边的目标场景是有多个下拉的列表填充 模版长这个样子 image 预期效果 可以生成并填充下拉的列表

触发Bug的代码

    public static String esBatchImportFileOptionCodeFill(File originaltemplateFile,
        Map<String, List<EsOptionBaseDTO>> map) {
        String fileName = FileUtil.getTmpDir() + File.separator
            + IdUtil.fastSimpleUUID() + ".xlsx";

        FileUtil.touch(fileName);

        try (ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(originaltemplateFile).build()) {
            WriteSheet writeSheet = EasyExcel.writerSheet(2).build();

            for (Map.Entry<String, List<EsOptionBaseDTO>> stringListEntry : collect) {
                // 如果有多个list 模板上必须有{前缀.} 这里的前缀就是 data1,然后多个list必须用 FillWrapper包裹
                FillWrapper data = new FillWrapper(stringListEntry.getKey(), stringListEntry.getValue());
                excelWriter.fill(data, writeSheet);

            }

        }
    }

提示的异常或者没有达到的效果

大家尽量把问题一次性描述清楚,然后贴上全部异常,这样方便把问题一次性解决掉。 至少大家要符合一个原则就是,能让其他人复现出这个问题,如果无法复现,肯定无法解决。

实际的效果如图 打开文件提示部分内容有问题

image

部分数据丢失 image

自己增加了以下处理代码后:

    public static String esBatchImportFileOptionCodeFill(File originaltemplateFile,
        Map<String, List<EsOptionBaseDTO>> map) {
        String fileName = FileUtil.getTmpDir() + File.separator
            + IdUtil.fastSimpleUUID() + ".xlsx";

        FileUtil.touch(fileName);

        try (ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(originaltemplateFile).build()) {
            WriteSheet writeSheet = EasyExcel.writerSheet(2).build();
            // 因为有多个模版码表填充 当存在多个码表需要填充 需要根据数据行数排序 行数少的先填充 否则会出现数据丢失问题
            List<Map.Entry<String, List<EsOptionBaseDTO>>> collect = new ArrayList<>(map.entrySet());
            collect.sort((a, b) -> {
                if (a.getValue().size() == b.getValue().size()) {
                    return 0;
                }
                return a.getValue().size() > b.getValue().size() ? 1 : -1;
            });
            for (Map.Entry<String, List<EsOptionBaseDTO>> stringListEntry : collect) {
                // 如果有多个list 模板上必须有{前缀.} 这里的前缀就是 data1,然后多个list必须用 FillWrapper包裹
                FillWrapper data = new FillWrapper(stringListEntry.getKey(), stringListEntry.getValue());
                excelWriter.fill(data, writeSheet);

            }

        }
    }

导出数据后目前正常可用

mirocolo commented 1 year ago

版本:

com.alibaba easyexcel 3.3.2
lkzgit commented 1 year ago

EsOptionBaseDTO 参数的属性是什么?多个模版的实体对象都不一样,怎么处理?图一是我的模版, image 图二是我导出的数据, image 应该在同一行才对,

mirocolo commented 1 year ago

我的场景只是恰好是相同实体对象罢了 不同实体对象也是一样的 EsOptionBaseDTO 这个只是定义的填充对象 不需要太关注 问题点应该是同行多个列表填充对象错位的问题 你这个场景似乎可以用 单个对象填充就好了

Ltyro commented 1 year ago

20年的问题现在还没修复吗

lkzgit commented 1 year ago

我这个就用的多个单个对象填充的