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
);
工作中实测使用,有什么问题欢迎留言交流