1:依赖(Maven)
XML
复制代码
<!-- FastExcel 官网最新版 -->
<dependency>
<groupId>cn.idev.excel</groupId>
<artifactId>fastexcel</artifactId>
<version>1.0.0</version>
</dependency>
2:动态表头实体类
java
复制代码
package com.fantaibao.module.vo.target;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentStyle;
import cn.idev.excel.annotation.write.style.HeadFontStyle;
import cn.idev.excel.annotation.write.style.HeadStyle;
import cn.idev.excel.enums.poi.FillPatternTypeEnum;
import cn.idev.excel.enums.poi.HorizontalAlignmentEnum;
import cn.idev.excel.enums.poi.VerticalAlignmentEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@HeadFontStyle(fontName = "黑体", fontHeightInPoints = 12)
@HeadStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER, verticalAlignment = VerticalAlignmentEnum.CENTER,
fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 44)
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER, verticalAlignment = VerticalAlignmentEnum.CENTER)
public class TargetIndexExportStoreStaVo {
/**
* 年份(2025)
*/
@ColumnWidth(15)
@ExcelProperty({"${indexName}", "年度"})
private Integer year;
/**
* 门店名称
*/
@ColumnWidth(20)
@ExcelProperty({"${indexName}", "门店名称"})
private String storeName;
/**
* 年目标
*/
@ColumnWidth(15)
@ExcelProperty({"${indexName}", "年目标"})
private String totalTarget;
/**
* 当前进度
*/
@ColumnWidth(20)
@ExcelProperty({"${indexName}", "当前进度"})
private String progress;
/**
* 目标完成率
*/
@ColumnWidth(20)
@ExcelProperty({"${indexName}", "目标完成率"})
private String finishRate;
}
java
复制代码
package com.fantaibao.module.vo.target;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.write.style.*;
import cn.idev.excel.enums.poi.FillPatternTypeEnum;
import cn.idev.excel.enums.poi.HorizontalAlignmentEnum;
import cn.idev.excel.enums.poi.VerticalAlignmentEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@HeadFontStyle(fontName = "黑体", fontHeightInPoints = 12)
@HeadStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER, verticalAlignment = VerticalAlignmentEnum.CENTER,
fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 44)
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER, verticalAlignment = VerticalAlignmentEnum.CENTER)
@ContentFontStyle(fontName = "黑体", fontHeightInPoints = 10)
public class TargetIndexExportStoreMonthStaVo {
/**
* 年份(2025)
*/
@ColumnWidth(15)
@ExcelProperty({"${indexName}", "年度"})
private Integer year;
/**
* 门店名称
*/
@ColumnWidth(25)
@ExcelProperty({"${indexName}", "门店名称"})
private String storeName;
/**
* 月目标
*/
@ColumnWidth(15)
@ExcelProperty({"${indexName}", "${month}月目标"})
private String totalTarget;
/**
* 当前进度
*/
@ColumnWidth(20)
@ExcelProperty({"${indexName}", "当前进度"})
private String progress;
/**
* 目标完成率
*/
@ColumnWidth(20)
@ExcelProperty({"${indexName}", "目标完成率"})
private String finishRate;
}
3:动态表头数据填充策略
java
复制代码
package com.fantaibao.handler;
import cn.hutool.core.collection.CollUtil;
import cn.idev.excel.metadata.Head;
import cn.idev.excel.write.handler.CellWriteHandler;
import cn.idev.excel.write.metadata.holder.WriteSheetHolder;
import cn.idev.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.Cell;
public class CustomHeaderWriteHandler implements CellWriteHandler {
private final String indexName;
public CustomHeaderWriteHandler(String indexName) {
this.indexName = indexName;
}
@Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
// 处理表头
if (CollUtil.isNotEmpty(head.getHeadNameList())) {
// 处理一级表头
if (CollUtil.isNotEmpty(head.getHeadNameList())) {
String replace = head.getHeadNameList().get(0).replace("${indexName}", indexName);
head.getHeadNameList().set(0, replace);
}
}
}
}
public class CustomMonthHeaderWriteHandler implements CellWriteHandler {
private final String indexName;
private final int month;
public CustomMonthHeaderWriteHandler(String indexName, int month) {
this.indexName = indexName;
this.month = month;
}
@Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
if (isHead && head != null) {
// 处理表头
if (CollUtil.isNotEmpty(head.getHeadNameList())) {
// 处理一级表头
String indexName = head.getHeadNameList().get(0).replace("${indexName}", this.indexName);
head.getHeadNameList().set(0, indexName);
// 处理二级表头
String monthStr = head.getHeadNameList().get(1);
if (!monthStr.contains("${month}")) {
return;
}
String month = monthStr.replace("${month}", String.valueOf(this.month));
head.getHeadNameList().set(1, month);
}
}
}
}
4:导出工具类
java
复制代码
/**
* 按单个指标生成年度-月度汇总数据
*
* @param zipOut ZIP输出流
* @param fileNamePrefix 文件名前缀
* @param storeTargetYearList 门店年目标集合
* @param storeMonthTargetList 门店月目标集合
* @param enums 指标
* @param storeMap 门店集合
* @throws IOException 抛出的异常
*/
public static void generateSingleIndexStaExcelFile(ZipOutputStream zipOut, String fileNamePrefix, List<StoreIndexYearStaVo> storeTargetYearList,
List<StoreIndexMonthStaVo> storeMonthTargetList, IndicatorsTypeEnums enums,
Map<String, StoreInfoListVO> storeMap) throws IOException {
ZipEntry zipEntry = new ZipEntry(enums.getName() + "门店" + fileNamePrefix + "目标汇总.xlsx");
zipOut.putNextEntry(zipEntry);
try (ExcelWriter excelWriter = EasyExcel.write(zipOut).autoCloseStream(false).build()) {
// Sheet1: 门店指标年目标汇总
WriteSheet yearSheet = EasyExcel.writerSheet(0, enums.getName() + "门店年目标")
.head(TargetIndexExportStoreStaVo.class)
.registerWriteHandler(new CustomHeaderWriteHandler(StrUtil.isNotBlank(enums.getUnit()) ? enums.getName() + "(" + enums.getUnit() + ")" : enums.getName()))
.build();
excelWriter.write(getYearSheetData(enums, storeTargetYearList, storeMap), yearSheet);
// Sheet2: 门店指标月目标汇总
for (int month = 1; month <= 12; month++) {
WriteSheet monthSheet = EasyExcel.writerSheet(month, "门店" + month + "月目标")
.head(TargetIndexExportStoreMonthStaVo.class)
.registerWriteHandler(new CustomMonthHeaderWriteHandler(StrUtil.isNotBlank(enums.getUnit()) ? enums.getName() + "(" + enums.getUnit() + ")" : enums.getName(), month))
.build();
excelWriter.write(getMonthSheetDataByMonth(enums, storeMonthTargetList, month, storeMap), monthSheet);
}
excelWriter.finish();
} catch (Exception e) {
try {
zipOut.closeEntry();
} catch (IOException ignored) {
}
throw e;
}
zipOut.closeEntry();
}
5:样例