使用 EasyExcel 导出 Excel 时,有时会遇到如下情况:
- 既要根据模板填充某些 sheet
- 又要根据业务写入某些 sheet
EasyExcel 官方没有提供这样的示例,经过自己的研究和实验,得到了如下步骤:
定义导出文件名
String fileName = "测试.xlsx";
获取模板文件
InputStream templateFile = ResourceUtil.getResourceObj("templates/template.xlsx").getStream();
此时读取的模板文件默认为压缩文件,是不能在后续进行填充的,所以需要在 pom.xml 中进行配置:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>2.6</version> <configuration> <!-- 配置不需要压缩的文件 --> <nonFilteredFileExtensions> <nonFilteredFileExtension>xls</nonFilteredFileExtension> <nonFilteredFileExtension>xlsx</nonFilteredFileExtension> </nonFilteredFileExtensions> </configuration> </plugin> </plugins> </build>
定义填充页数据
@Data public class FillData { private String name; private double number; }
FillData fillData = new FillData(); fillData.setName("张三"); fillData.setNumber(5.2);
定义业务页数据
@Data public class BusinessData { @ExcelProperty("字符串标题") private String string; @ExcelProperty("日期标题") private Date date; @ExcelProperty("数字标题") private Double doubleData; /** * 忽略这个字段 */ @ExcelIgnore private String ignore; }
BusinessData businessData = new BusinessData(); businessData.setString("测试"); businessData.setDate(new Date()); businessData.setDoubleData(1.0); List<BusinessData> businessDataList = Collections.singletonList(businessData);
定义写入器
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFile).build();
定义填充页 sheet
WriteSheet writeSheet0 = EasyExcel.writerSheet().registerWriteHandler(new CustomTemplateSheetStrategy("动态命名sheet")).build();
这里使用了
CustomTemplateSheetStrategy
。之所以要使用该拦截器,是因为填充时默认是只能取模板定义的 sheet 名称作为填充页的 sheet 名称,但业务中往往是需要动态命名 sheet 的,所以使用拦截器进行拦截处理后命名。
CustomTemplateSheetStrategy
代码如下:
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
/**
* 自定义模板导出sheet拦截器
*
* @author 天航星
* @date 2024-07-03 13:48
*/
public class CustomTemplateSheetStrategy implements SheetWriteHandler {
private Integer sheetNo;
private String sheetName;
public CustomTemplateSheetStrategy(String sheetName) {
this.sheetName = sheetName;
}
public CustomTemplateSheetStrategy(Integer sheetNo, String sheetName) {
this.sheetNo = sheetNo;
this.sheetName = sheetName;
}
@Override
public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
}
/**
* 功能:动态修改模板中sheet的名称
* sheet创建完成后调用
* @param writeWorkbookHolder
* @param writeSheetHolder
*/
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
if (sheetName == null) {
return;
}
if (sheetNo == null) {
sheetNo = 0;
}
writeWorkbookHolder.getCachedWorkbook().setSheetName(sheetNo, sheetName);
}
}
定义业务页 sheet
WriteSheet writeSheet1 = EasyExcel.writerSheet("Sheet1").head(BusinessData.class).build();
填充数据
excelWriter.fill(fillData, writeSheet0);
注意:这里一定要传入对象,不能传入列表,否则填充的内容会变为空白。
写入数据
excelWriter.write(businessDataList, writeSheet1);
关闭写入器
excelWriter.finish();
注意:这里必须要关闭写入器,不然写入的文件为空。
根据以上步骤即可以填充+写入的方式导出 Excel,以下是完整代码:
import cn.hutool.core.io.resource.ResourceUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.sevnce.pop.customer.handler.CustomTemplateSheetStrategy;
import lombok.Data;
import org.junit.jupiter.api.Test;
import java.io.InputStream;
import java.util.Collections;
import java.util.Date;
import java.util.List;
/**
* 测试用例
*
* @author 天航星
* @date 2024-07-03 10:55
*/
public class TestDemo {
@Data
public class FillData {
/**
* 名称
*/
private String name;
/**
* 数字
*/
private double number;
}
@Data
public class BusinessData {
@ExcelProperty("字符串标题")
private String string;
@ExcelProperty("日期标题")
private Date date;
@ExcelProperty("数字标题")
private Double doubleData;
/**
* 忽略这个字段
*/
@ExcelIgnore
private String ignore;
}
@Test
public void test() {
// 定义导出文件名
String fileName = "测试.xlsx";
// 获取模板文件
InputStream templateFile = ResourceUtil.getResourceObj("templates/template.xlsx").getStream();
// 定义填充页数据
FillData fillData = new FillData();
fillData.setName("张三");
fillData.setNumber(5.2);
// 定义业务页数据
BusinessData businessData = new BusinessData();
businessData.setString("测试");
businessData.setDate(new Date());
businessData.setDoubleData(1.0);
List<BusinessData> businessDataList = Collections.singletonList(businessData);
// 定义写入器
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFile).build();
// 定义填充页 sheet
WriteSheet writeSheet0 = EasyExcel.writerSheet().registerWriteHandler(new CustomTemplateSheetStrategy("动态命名sheet")).build();
// 定义业务页 sheet
WriteSheet writeSheet1 = EasyExcel.writerSheet("Sheet1").head(BusinessData.class).build();
// 填充数据
excelWriter.fill(fillData, writeSheet0);
// 写入数据
excelWriter.write(businessDataList, writeSheet1);
// 关闭写入器
excelWriter.finish();
}
}
环境:
- JDK:1.8.0_202
- SpringBoot:2.7.17
- EasyExcel:3.3.2