easypoi 导出 一对一实体乱序问题

背景:

        使用easypoi 作为导入导出框架,引入的版本号是:

<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-base</artifactId>
    <version>4.0.0</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-annotation</artifactId>
    <version>4.0.0</version>
</dependency>

使用场景:

       使用@ExcelEntity ,指定分组名称,理想状态能按顺序输出如下表格:

public class ContractTurnOverExcelVO {

       /**
        * 固定租金
        */
       @ExcelEntity(name ="固定租金",show = true,id = "CostDTO.class")
       private CostDTO fixedRent;

       /**
        * 预估营业额
        */
       @ExcelEntity(name ="预估营业额",show = true,id = "CostDTO.class")
       private CostDTO turnover;


       /**
        * 提成租金
        */
       @ExcelEntity(name ="提成租金",show = true,id = "CostDTO.class")
       private CostDTO royaltyRent;


       /**
        * 实付租金(根据计租模型来确定数据)
        */
       @ExcelEntity(name ="实付租金",show = true,id = "CostDTO.class")
       private CostDTO actualRent;


       /**
        * 房租合同其他费用合计
        */
       @ExcelEntity(name ="房租合同其他费用合计",show = true,id = "CostDTO.class")
       private CostDTO otherRent;


       /**
        * 其他合同费用合计
        */
       @ExcelEntity(name ="其他合同费用合计",show = true,id = "CostDTO.class")
       private CostDTO otherContractRent;


       /**
        * 所有费用合计
        * 【其他合同固定费用合计】+【房租合同实付租金】+【房租合同其他费用合计】
        */
       @ExcelEntity(name ="合计",show = true,id = "CostDTO.class")
       private CostDTO totalRent;
}

实际现象:

         导出的 @ExcelEntity 并没有按照顺序输出

解决方案:

        使用1,2,3,4代替分组名称。然后再用Map 自定义映射分组名称。再拿到Workbook后遍历所在行,遍历替换想要输出的表格名称。由此解决乱序问题。

/**
 * 固定租金
 */
@ExcelEntity(name ="1",show = true,id = "CostDTO.class")
private CostDTO fixedRent;

/**
 * 预估营业额
 */
@ExcelEntity(name ="2",show = true,id = "CostDTO.class")
private CostDTO turnover;


/**
 * 提成租金
 */
@ExcelEntity(name ="3",show = true,id = "CostDTO.class")
private CostDTO royaltyRent;
static {
    TITLE_MAP.put("1", "固定租金");
    TITLE_MAP.put("2", "预估营业额");
    TITLE_MAP.put("3", "提成租金");
    TITLE_MAP.put("4", "实付租金");
    TITLE_MAP.put("5", "房租合同其他费用合计");
    TITLE_MAP.put("6", "其他合同费用合计");
    TITLE_MAP.put("7", "合计");
}
//导出多个表格
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, ContractTurnOverExcelVO.class, contractTurnOverExcelVOS);
//处理导出的名字映射
workbook.getSheetAt(0).getRow(0).forEach(cell -> {
    String value = (String) TITLE_MAP.get(cell.getStringCellValue());
    if (ObjectUtil.isNotEmpty(value)) {
        cell.setCellValue(value);
    }
});

分析原因:

      跟踪easypoi 源码可以发现:在ExcelExportService类中insertDataToSheet方法通过sortAllParams(excelParams)把导出类的属性重新排序了一遍。

         跟进sortAllParams方法中可以看到源码中使用HashMap存放分组和分组中具体的数据。由于HashMap的存放顺序和key 的hash值有关。所以在HashMap 遍历链表的时候,和push的顺序无关,导致乱序。

        了解到问题的本质后,我们就可以采用确定顺序hash 的数字代替文本。保证按照我们想要的顺序输出,最后得到表格结果后就可以根据预设的映射替换成我们需要的真实文字导出。

        至此乱序问题就完美解决啦。。。。

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用 EasyPoi 导出一对多数据时,需要使用 `@ExcelCollection` 注解来标识一对多的关系。下面是一个示例: 假设我们有两个实体类: `Order` 和 `OrderItem`,一个订单可以对应多个订单项。 ```java public class Order { @Excel(name = "订单编号", orderNum = "0") private String orderId; @Excel(name = "订单总价", orderNum = "1") private BigDecimal totalPrice; @ExcelCollection(name = "订单项", orderNum = "2") private List<OrderItem> orderItemList; // 省略 getter 和 setter 方法 } public class OrderItem { @Excel(name = "订单项编号", orderNum = "0") private String orderItemId; @Excel(name = "商品名称", orderNum = "1") private String productName; @Excel(name = "商品数量", orderNum = "2") private Integer productQuantity; // 省略 getter 和 setter 方法 } ``` 在 `Order` 类中,我们使用 `@ExcelCollection` 注解标识 `orderItemList` 属性,表示一个订单有多个订单项。在导出时,EasyPoi 会自动处理一对多的数据,并将订单项列表展开成多行数据。 下面是一个导出示例: ```java // 构造数据 List<Order> orderList = new ArrayList<>(); Order order1 = new Order(); order1.setOrderId("1001"); order1.setTotalPrice(new BigDecimal(100)); List<OrderItem> orderItemList1 = new ArrayList<>(); OrderItem item1 = new OrderItem(); item1.setOrderItemId("101"); item1.setProductName("商品1"); item1.setProductQuantity(2); orderItemList1.add(item1); OrderItem item2 = new OrderItem(); item2.setOrderItemId("102"); item2.setProductName("商品2"); item2.setProductQuantity(3); orderItemList1.add(item2); order1.setOrderItemList(orderItemList1); orderList.add(order1); // 导出 ExcelExportUtil.exportExcel(new ExportParams("订单列表", "订单"), Order.class, orderList, new FileOutputStream("order.xls")); ``` 在导出结果中,我们可以看到订单项被展开成了多行数据: | 订单编号 | 订单总价 | 订单项编号 | 商品名称 | 商品数量 | | :-----: | :-----: | :-----: | :-----: | :-----: | | 1001 | 100 | 101 | 商品1 | 2 | | | | 102 | 商品2 | 3 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值