easypoi一对多对多导出excel格式问题,数据不对应

刚刚开通了一个公众号,会分享一些技术博客和自己觉得比较好的项目,同时会更新一些自己使用的工具和图书资料,后面会整理一些面试资料进行分享,觉得有兴趣的可以关注一下。
在这里插入图片描述

项目场景:

最近在做一个导出excel报表的需求,数据是三表关联出来的(关系一对多对多)。导出要求对应三者的关系,将对应的子数据,父节点数据要进行合并单元格。
这种场景直接使用easyPOI一键导出很方便,只要配置相对应的注解标注各自的对应关系即可。
实体类代码如下:

  • 实体类1
@Data
@ExcelTarget("test2Entity")
public class Test1Entity {

    @Excel(name = "property1", width = 17.0)
    private String property1;

    @Excel(name = "property2",orderNum = "1")
    private String property2;

    @ExcelCollection(name="Test2Entity信息", orderNum = "6")
    private List<Test2Entity> list;

}
  • 实体类2
@Data
@ExcelTarget("test2Entity")
public class Test2Entity {

    @Excel(name = "property1-1", width = 17.0)
    private String property1_1;

    @Excel(name = "property2-2",orderNum = "1")
    private String property2_2;

    @ExcelCollection(name="Test3Entity信息", orderNum = "6")
    private List<Test3Entity> list;

}
  • 实体类3
@Data
@ExcelTarget("test1Entity")
public class Test3Entity {

    @Excel(name = "姓名", width = 17.0)
    private String name;

    @Excel(name = "年龄",orderNum = "1")
    private Integer age;

    @Excel(name = "电话",orderNum = "2", width = 17.0)
    private String mobile;

}

这三者的关系,Test1EntityTest2Entity是一对多的关系,Test2EntityTest3Entity是一对多的关系,
配置好关联关系后,我们直接使用之前博客的介绍的代码,生成即可。

ExcelExportUtil.exportExcel(new ExportParams("test", "result", ExcelType.XSSF),
                Test1Entity.class, list);

导出即可!


问题描述

果然没有想到的那么简单,生成的文件,数据是对应不上的,老是少数据,开始我以为是对应关系开始就差错了,debug数据看其实是正确的,那么只能看源代码了。


原因分析:

我使用的easyPOI的版本是4.1.0,核心创建excel的代码如下(在BaseExportService类中):

	public int[] createCells(Drawing patriarch, int index, Object t,
                             List<ExcelExportEntity> excelParams, Sheet sheet, Workbook workbook,
                             short rowHeight, int cellNum) {
        try {
            ExcelExportEntity entity;
            Row               row = sheet.getRow(index) == null ? sheet.createRow(index) : sheet.getRow(index);
            if (rowHeight != -1) {
                row.setHeight(rowHeight);
            }
            int maxHeight = 1, listMaxHeight = 1;
            // 合并需要合并的单元格
            int margeCellNum = cellNum;
            int indexKey     = createIndexCell(row, index, excelParams.get(0));
            cellNum += indexKey;
            for (int k = indexKey, paramSize = excelParams.size(); k < paramSize; k++) {
                entity = excelParams.get(k);
                if (entity.getList() != null) {
                    Collection<?> list      = getListCellValue(entity, t);
                    int           listIndex = 0, tmpListHeight = 0;
                    if (list != null && list.size() > 0) {
                        int tempCellNum = 0;
                        for (Object obj : list) {
                            int[] temp = createCells(patriarch, index + listIndex, obj, entity.getList(), sheet, workbook, rowHeight, cellNum);
                            tempCellNum = temp[1];
                            tmpListHeight += temp[0];
                            listIndex++;
                        }
                        cellNum = tempCellNum;
                        listMaxHeight = Math.max(listMaxHeight, tmpListHeight);
                    }
                } else {
                    Object value = getCellValue(entity, t);

                    if (entity.getType() == BaseEntityTypeConstants.STRING_TYPE) {
                        createStringCell(row, cellNum++, value == null ? "" : value.toString(),
                                index % 2 == 0 ? getStyles(false, entity) : getStyles(true, entity),
                                entity);

                    } else if (entity.getType() == BaseEntityTypeConstants.DOUBLE_TYPE) {
                        createDoubleCell(row, cellNum++, value == null ? "" : value.toString(),
                                index % 2 == 0 ? getStyles(false, entity) : getStyles(true, entity),
                                entity);
                    } else {
                        createImageCell(patriarch, entity, row, cellNum++,
                                value == null ? "" : value.toString(), t);
                    }
                    if (entity.isHyperlink()) {
                        row.getCell(cellNum - 1)
                                .setHyperlink(dataHandler.getHyperlink(
                                        row.getSheet().getWorkbook().getCreationHelper(), t,
                                        entity.getName(), value));
                    }
                }
            }
            maxHeight += listMaxHeight - 1;
            if (indexKey == 1 && excelParams.get(1).isNeedMerge()) {
                excelParams.get(0).setNeedMerge(true);
            }
            for (int k = indexKey, paramSize = excelParams.size(); k < paramSize; k++) {
                entity = excelParams.get(k);
                if (entity.getList() != null) {
                    margeCellNum += entity.getList().size();
                } else if (entity.isNeedMerge() && maxHeight > 1) {
                    for (int i = index + 1; i < index + maxHeight; i++) {
                        if(sheet.getRow(i) == null ) {
                            sheet.createRow(i);
                        }
                        sheet.getRow(i).createCell(margeCellNum);
                        sheet.getRow(i).getCell(margeCellNum).setCellStyle(getStyles(false, entity));
                    }
                    PoiMergeCellUtil.addMergedRegion(sheet, index, index + maxHeight - 1, margeCellNum, margeCellNum);
                    margeCellNum++;
                }
            }
            return new int[]{maxHeight, cellNum};
        } catch (Exception e) {
            LOGGER.error("excel cell export error ,data is :{}", ReflectionToStringBuilder.toString(t));
            LOGGER.error(e.getMessage(), e);
            throw new ExcelExportException(ExcelExportEnum.EXPORT_ERROR, e);
        }

    }

问题的原因找到了,代码在判断是List的时候,会进行循环递归,传过去的值是RowIndex的数据,每次循环,listIndex这个RowIndex会增加,也就是每行创建一条数据。如果这个是单层一对多的关联关系是没有问题的。
但是!!如果出现像我这种一对多对多的这种复杂关系,虽然递归嵌套也能处理,当从最深层返回上一层对应关系的时候,RowIndex会回退!!!导致数据覆盖!!!


解决方案:

我本来是想重写的,只需要回退的时候,记住增加了几个增加上去就好了,但是想看看高版本有没有修复,升级到4.5.0之后发现这个问题就修复了。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦幻D开始

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值