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的表头字段,会在数据写入时,抛出空指针异常