最近在工作中遇到一个动态表头的数据导入,使用EasyExcel常规的类映射来接收是不可行的。我的解决方式是自已动态解析来处理,思路是:继承EasyExcel的AnalysisEventListener,手动处理和接收动态数据。这里主要适用表头只有一行,不适用多行复杂的表头,复杂表头可在这基础上扩展,请自行研究,哈哈。
自定义一个DynamicHeaderListener类
public class DynamicHeaderListener extends AnalysisEventListener<Map<Integer, String>> {
private List<String> headers = new ArrayList<>(); // 动态表头
// private List<Map<String, String>> dataList = new ArrayList<>(); // 数据列表,每行的key值为表头名,value为数据值
private List<List<String>> dataList = new ArrayList<>(); //数据列表,每个列数据和excel的位置相同
@Override
public void invoke(Map<Integer, String> dataRow, AnalysisContext context) {
if (headers.isEmpty()) {
// 如果headers为空,则认为当前行为表头
for (Map.Entry<Integer, String> entry : dataRow.entrySet()) {
if (StrUtil.isNotBlank(entry.getValue())) {
headers.add(entry.getValue().trim());
} else {
headers.add(entry.getValue());
}
}
return;
}
// 处理数据行
List<String> rowData = new ArrayList<>();
for (int i = 0; i < headers.size(); i++) {
// rowData.put(headers.get(i), dataRow.get(i));
if (StrUtil.isNotBlank(dataRow.get(i))) {
rowData.add(dataRow.get(i).trim());
} else {
rowData.add(dataRow.get(i));
}
}
this.dataList.add(rowData);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// TODO Auto-generated method stub
}
public List<String> getHeaders() {
return headers;
}
// public List<Map<String, String>> getData() {
// return dataList;
// }
public List<List<String>> getData() {
return dataList;
}
}
以上代码是取excel表格的第一行为表头存入List<String> headers里面,然后每行数据存入List<List<String>> dataList,该集合的下标数据与headers下标是对应的。也可以存入List<Map<String, String>> dataList里面,代码我注释掉了,可以根据实际使用选择把数据存入不同数据结构的dataList里面。然后getHeaders()方法是获取表头,getData()方法是获取数据。
使用如下:
DynamicHeaderListener listener = new DynamicHeaderListener();
EasyExcel.read(file.getInputStream(), listener)
.sheet()
.headRowNumber(0) // 第一行为表头
.doRead();
List<String> headers = listener.getHeaders(); //表头集合
List<List<String>> importDataList = listener.getData(); ///数据集合