使用EasyExcel动态合并单元格(模板方法)
1、导入EasyExcel依赖
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>4.0.3</version>
</dependency>
2、编写实体类
@Data
publci class Student{ @ExcelProperty("姓名")private String name;
}
3、具体方法如下
调用方法(除了基础的模板地址和数据外,增加了合并列索引和分组函数)
/*** 填充模板并合并单元格** @param tempName 模板名称* @param list 填充数据集合* @param resultMap 特殊数据替换map* @param targetFilePath 导出地址* @param excelTypeEnum ecxcel文件类型* @param mergeColumnIndex sheet中需要合并的列的索引* @param groupFunction 分组函数* @param <T>*/public static <T> void buildMergeExcel(String tempName, List<T> list, Map<String, String> resultMap, String targetFilePath, ExcelTypeEnum excelTypeEnum, int[] mergeColumnIndex, Function<T, String> groupFunction) {try {// 获取模板文件ClassPathResource classPathResource = new ClassPathResource("template/" + tempName);// 行计数,初始值取列头行数int lineCount = 1;// 分别填充list数据和特殊数据ExcelWriter excelWriter = EasyExcel.write(new File(LocalStoragePropertiesConstants.LOCAL_PROFILE + targetFilePath)).excelType(excelTypeEnum).withTemplate(classPathResource.getInputStream()).build();FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();List<CellRangeAddress> rangeCellList = createCellRange(list, mergeColumnIndex, lineCount, groupFunction);WriteSheet writeSheet = EasyExcel.writerSheet().registerWriteHandler(new MergeCellRangeWriteHandler(rangeCellList)).build();excelWriter.fill(list, fillConfig, writeSheet);excelWriter.fill(resultMap, writeSheet);list.clear();excelWriter.finish();} catch (IOException e) {throw new RuntimeException(e);}}
提前计算合并的单元格,在sheet创建后一次性合并
/*** 生成合并区域** @param detailList 数据列表* @param mergeColumnIndex 要合并的列索引* @param startRowIndex 起始行(含表头时,表头行数)* @param groupFunction 分组函数,如 e -> e.get某字段()* @return 合并区域集合*/public static <T> List<CellRangeAddress> createCellRange(List<T> detailList, int[] mergeColumnIndex, int startRowIndex, Function<T, String> groupFunction) {if (detailList == null || detailList.isEmpty()) {return Collections.emptyList();}// 计算每个key下的数量Map<String, Long> groupMap = new LinkedHashMap<>();for (T item : detailList) {String key = groupFunction.apply(item);groupMap.put(key, groupMap.getOrDefault(key, 0L) + 1);}List<CellRangeAddress> rangeCellList = new ArrayList<>();// 当前行数int lineCount = startRowIndex;for (Map.Entry<String, Long> entry : groupMap.entrySet()) {int count = entry.getValue().intValue();if (count > 1) {int endRowIndex = lineCount + count - 1;for (int columnIndex : mergeColumnIndex) {rangeCellList.add(new CellRangeAddress(lineCount, endRowIndex, columnIndex, columnIndex));}}lineCount += count;}return rangeCellList;}
单元格合并策略
/*** easyExcel 合并单元格*/
public class MergeCellRangeWriteHandler implements SheetWriteHandler {private final List<CellRangeAddress> rangeCellList;public MergeCellRangeWriteHandler(List<CellRangeAddress> rangeCellList) {this.rangeCellList = (rangeCellList == null) ? Collections.emptyList() : rangeCellList;}public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {Sheet sheet = writeSheetHolder.getSheet();for (CellRangeAddress cellRangeAddress : this.rangeCellList) {sheet.addMergedRegionUnsafe(cellRangeAddress);}}
}
调用如下:
String sheetTitle = "模板名称";FileResultVO fileResultVO = ExpandFileUtil.generateFilePath(EXTENSION_XLSX, sheetTitle + UUID.randomUUID(), EXTENSION_XLSX);ExpandEasyExcelUtil.buildMergeExcel("MB.xlsx",dataList, null, fileResultVO.getFilePath(),ExcelTypeEnum.XLSX,new int[]{0, 1, 2, 3, 4},Student::getName);
工作中实测使用,有什么问题欢迎留言交流