EasyExcel 导出,导入自定义表头,表头更名

一、场景

在同一个场景中导出的Excel 中的表头字段(title)存在不同的名称 (表头、标题),在导出时,要存在差异化,并且导出的模版要同时可以导出

二、方案

  • 在导出时,添加自定义的handler,对导出的字段进行处理,更换导出的字段名称
  • 在导入时,自定义需要获取的表头名称

三、代码示例

测试类

import java.util.*;

@Slf4j
class CustomCellWriteHandlerTest {

   @Data
   public static class DemoData {
       @ExcelProperty(value = "first")
       private String oldHeader1;
       @ExcelProperty(value = "second")
       private String oldHeader2;
       @ExcelProperty(value = "测试3")
       private String oldHeader3;
       @ExcelProperty(value = "测试4")
       private String oldHeader4;
   }

   private List<DemoData> demos = new ArrayList<>();

   private Map<String, String> headMap = new HashMap<>();
   private Map<String, String> readMap = new HashMap<>(); // 不需要考虑,测试数据
   private List<List<String>> head = new ArrayList<>(); // 自定义的导入请求头

   @BeforeEach
   public void init() {
       for (int i = 0; i < 3; i++) {
           DemoData demoData = new DemoData();
           demoData.setOldHeader1("first" + i);
           demoData.setOldHeader2("second" + i);
           demoData.setOldHeader3("测试3+" + i);
           demoData.setOldHeader4("测试4+" + i);
           demos.add(demoData);
       }

       headMap.put("oldHeader1", "firstChange");
       headMap.put("second", "secondChange");

       readMap.put("firstChange", "first");
       readMap.put("secondChange", "second");


       head.add(Collections.singletonList("firstChange"));
       head.add(Collections.singletonList("secondChange"));
       head.add(Collections.singletonList("测试3"));
//        head.add(Collections.singletonList("测试6"));
       head.add(Collections.singletonList("测试4"));
   }


   @Test
   void testCustomizeExportEasyExcel() {
       String filename = "output.xlsx";
       EasyExcel.write(filename, DemoData.class)
               .registerWriteHandler(new CustomCellWriteHandler(headMap))
               .sheet("Sheet1")
               .doWrite(demos);
   }

   @Test
   void testCustomizeImportListener() {
       String filename = "output.xlsx";
       CustomReadListener<DemoData> demoDataCustomReadListener = new CustomReadListener<>(readMap); // 使用常规的Listener就可以了,此处是测试用,可忽略
       EasyExcel.read(filename, DemoData.class, demoDataCustomReadListener)
               .head(head)
               .sheet().doRead();
       List<DemoData> list = demoDataCustomReadListener.getList();
       System.out.println(list);
   }
}

自定义的handler CustomCellWriteHandler


@AllArgsConstructor
@NoArgsConstructor
public class CustomCellWriteHandler implements CellWriteHandler {

   private Map<String, String> headMap = new HashMap<>(); // 传入需要进行表头替换的Map,以便在解析表头时可以进行替换
   @Override
   public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {

   }

   @Override
   public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {

   }

   @Override
   public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {

   }

   @Override
   public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
       // 如果是表头,可以更改表头的内容
       if (Boolean.TRUE.equals(isHead)) {
           if (headMap.containsKey(head.getFieldName())) {
               cell.setCellValue(headMap.get(head.getFieldName()));
           }
           if (headMap.containsKey(head.getHeadNameList().get(0))) {
               cell.setCellValue(headMap.get(head.getHeadNameList().get(0)));
           }
       }
   }
}

注意的点

- 在进行导入时
EasyExcel.read(filename, DemoData.class, demoDataCustomReadListener)
               .head(head)
               .sheet().doRead();
   			这段代码中head是我们自定义导入的表头,在read中还加上了DemoData.class 这个表头类
   			因为不加入表头类,读取的表头就是按照顺序读取的,对数据的表头顺序一致有非常高的要求
   			
- 使用DemoData.class 还有一个就是,在进行导入处理时,会根据表头,对导入的数据进行匹配,
这样在后续处理时数据会更干净,同时能够直接将结果数据,映射为我们想要的class类

- 在read中添加class 后,同时使用head 进行自定义表头,需要满足head的长度不大于class字段的总长度,
不然会在读取表头的时候就出现null的表头字段,会在数据写入时,抛出空指针异常
posted @ 2024-06-05 10:35  代码红了一大片  阅读(1518)  评论(0编辑  收藏  举报