tip:这块合并我是按照我们项目中所涉及的excel编写的逻辑,没做大量测试,仅供参考。
读取的数据:
我们希望每一行都能读取为类似的Map:
{“0”:“123”,“1”:“北京”,“2”:“京1”,“3”:“J1”,“4”:“>5”,“5”:“>5”}
但是如果不进行合并单元格处理,只能读成:
在读取代码中加入extraRead,读取合并
在监听器中,编写方法,读取合并的信息:
@Getter
public class ReadMergeAsMapListener extends AnalysisEventListener<Map<String, Object>> {
private final List<Map<String, Object>> dataList = new ArrayList<Map<String, Object>>();
private final List<CellExtra> extraList = new ArrayList<CellExtra>();
public void invoke(Map<String, Object> data, AnalysisContext context) {
dataList.add(data);
}
public void extra(CellExtra extra, AnalysisContext context) {
CellExtraTypeEnum type = extra.getType();
// 合并
if (type.equals(CellExtraTypeEnum.MERGE)){
extraList.add(extra);
}
}
public void doAfterAllAnalysed(AnalysisContext context) {
System.out.println("read finish");
}
}
打印出合并的信息,可以得到合并的单元格信息:
通过这个json,并观察excel,
我们可以判断:rowIndex、columnIndex指的是在excel中的坐标,
带first的两组代表的是,从first到last的单元格是合并的。
接下来我们再根据读取出来的dataList对数据进行填补。
(其实可以判断出来,这个rowIndex,columnIndex可以处理成对应的 dataList信息)
由于这个extraList是读取的所有数据包括表头,而dataList会去掉表头,
所以我们要认为规定实际数据的起点,也就是数据开始的行数(从0开始数)
例如这个excel,headRow就是2。
编写合并逻辑
private static void fillDataListByMerge(List<Map<Integer, Object>> dataList, List<CellExtra> extraList, Integer headRow) {
for (CellExtra cellExtra : extraList) {
Integer rowIndex = cellExtra.getRowIndex();
if (rowIndex < headRow){
continue;
}
int dataListIndex = rowIndex - headRow;
Integer dataMapKey = cellExtra.getColumnIndex();
Map<Integer, Object> dataMap = dataList.get(dataListIndex);
Integer firstRowIndex = cellExtra.getFirstRowIndex() - headRow;
Integer lastRowIndex = cellExtra.getLastRowIndex() - headRow;
Integer firstColumnIndex = cellExtra.getFirstColumnIndex();
Integer lastColumnIndex = cellExtra.getLastColumnIndex();
Object value = dataMap.get(dataMapKey);
// 左右合并
for (int i = firstColumnIndex + 1; i < lastColumnIndex + 1; i++) {
dataMap.put(i, value);
}
// 上下合并
for (int i = firstRowIndex + 1; i < lastRowIndex + 1; i++) {
Map<Integer, Object> integerObjectMap = dataList.get(i);
integerObjectMap.put(firstColumnIndex, value);
if (!firstColumnIndex.equals(lastColumnIndex)){
for (int j = firstColumnIndex + 1; j < lastColumnIndex + 1; j++) {
integerObjectMap.put(j, value);
}
}
}
}
}
合并结果: