使用 EasyExcel 导出 Excel 时,有时会遇到如下情况:
- 既要根据模板填充某些 sheet
- 又要根据业务写入某些 sheet
EasyExcel 官方没有提供这样的示例,经过自己的研究和实验,得到了如下步骤:
- 定义导出文件名
1String fileName = "测试.xlsx";
- 获取模板文件
1InputStream templateFile = ResourceUtil.getResourceObj("templates/template.xlsx").getStream();
此时读取的模板文件默认为压缩文件,是不能在后续进行填充的,所以需要在 pom.xml 中进行配置:
1<build> 2 <plugins> 3 <plugin> 4 <groupId>org.apache.maven.plugins</groupId> 5 <artifactId>maven-resources-plugin</artifactId> 6 <version>2.6</version> 7 <configuration> 8 <!-- 配置不需要压缩的文件 --> 9 <nonFilteredFileExtensions> 10 <nonFilteredFileExtension>xls</nonFilteredFileExtension> 11 <nonFilteredFileExtension>xlsx</nonFilteredFileExtension> 12 </nonFilteredFileExtensions> 13 </configuration> 14 </plugin> 15 </plugins> 16</build>
- 定义填充页数据
1@Data 2public class FillData { 3 private String name; 4 private double number; 5}
1FillData fillData = new FillData(); 2fillData.setName("张三"); 3fillData.setNumber(5.2);
- 定义业务页数据
1@Data 2public class BusinessData { 3 @ExcelProperty("字符串标题") 4 private String string; 5 @ExcelProperty("日期标题") 6 private Date date; 7 @ExcelProperty("数字标题") 8 private Double doubleData; 9 /** 10 * 忽略这个字段 11 */ 12 @ExcelIgnore 13 private String ignore; 14}
1BusinessData businessData = new BusinessData(); 2businessData.setString("测试"); 3businessData.setDate(new Date()); 4businessData.setDoubleData(1.0); 5List<BusinessData> businessDataList = Collections.singletonList(businessData);
- 定义写入器
1ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFile).build();
- 定义填充页 sheet
1WriteSheet writeSheet0 = EasyExcel.writerSheet().registerWriteHandler(new CustomTemplateSheetStrategy("动态命名sheet")).build();
这里使用了 CustomTemplateSheetStrategy。
之所以要使用该拦截器,是因为填充时默认是只能取模板定义的 sheet 名称作为填充页的 sheet 名称,但业务中往往是需要动态命名 sheet 的,所以使用拦截器进行拦截处理后命名。
CustomTemplateSheetStrategy代码如下:
1import com.alibaba.excel.write.handler.SheetWriteHandler; 2import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; 3import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; 4 5/** 6 * 自定义模板导出sheet拦截器 7 * 8 * @author 天航星 9 * @date 2024-07-03 13:48 10 */ 11public class CustomTemplateSheetStrategy implements SheetWriteHandler { 12 13 private Integer sheetNo; 14 15 private String sheetName; 16 17 public CustomTemplateSheetStrategy(String sheetName) { 18 this.sheetName = sheetName; 19 } 20 21 public CustomTemplateSheetStrategy(Integer sheetNo, String sheetName) { 22 this.sheetNo = sheetNo; 23 this.sheetName = sheetName; 24 } 25 26 @Override 27 public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { 28 29 } 30 31 /** 32 * 功能:动态修改模板中sheet的名称 33 * sheet创建完成后调用 34 * @param writeWorkbookHolder 35 * @param writeSheetHolder 36 */ 37 @Override 38 public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { 39 40 if (sheetName == null) { 41 return; 42 } 43 if (sheetNo == null) { 44 sheetNo = 0; 45 } 46 writeWorkbookHolder.getCachedWorkbook().setSheetName(sheetNo, sheetName); 47 } 48} 49
- 定义业务页 sheet
1WriteSheet writeSheet1 = EasyExcel.writerSheet("Sheet1").head(BusinessData.class).build();
- 填充数据
1excelWriter.fill(fillData, writeSheet0);
**注意:**这里一定要传入对象,不能传入列表,否则填充的内容会变为空白。
- 写入数据
1excelWriter.write(businessDataList, writeSheet1);
- 关闭写入器
1excelWriter.finish();
**注意:**这里必须要关闭写入器,不然写入的文件为空。
根据以上步骤即可以填充+写入的方式导出 Excel,以下是完整代码:
1import cn.hutool.core.io.resource.ResourceUtil; 2import com.alibaba.excel.EasyExcel; 3import com.alibaba.excel.ExcelWriter; 4import com.alibaba.excel.annotation.ExcelIgnore; 5import com.alibaba.excel.annotation.ExcelProperty; 6import com.alibaba.excel.write.metadata.WriteSheet; 7import com.sevnce.pop.customer.handler.CustomTemplateSheetStrategy; 8import lombok.Data; 9import org.junit.jupiter.api.Test; 10import java.io.InputStream; 11import java.util.Collections; 12import java.util.Date; 13import java.util.List; 14 15/** 16 * 测试用例 17 * 18 * @author 天航星 19 * @date 2024-07-03 10:55 20 */ 21public class TestDemo { 22 23 @Data 24 public class FillData { 25 26 /** 27 * 名称 28 */ 29 private String name; 30 31 /** 32 * 数字 33 */ 34 private double number; 35 } 36 37 @Data 38 public class BusinessData { 39 40 @ExcelProperty("字符串标题") 41 private String string; 42 43 @ExcelProperty("日期标题") 44 private Date date; 45 46 @ExcelProperty("数字标题") 47 private Double doubleData; 48 49 /** 50 * 忽略这个字段 51 */ 52 @ExcelIgnore 53 private String ignore; 54 } 55 56 @Test 57 public void test() { 58 59 // 定义导出文件名 60 String fileName = "测试.xlsx"; 61 // 获取模板文件 62 InputStream templateFile = ResourceUtil.getResourceObj("templates/template.xlsx").getStream(); 63 // 定义填充页数据 64 FillData fillData = new FillData(); 65 fillData.setName("张三"); 66 fillData.setNumber(5.2); 67 // 定义业务页数据 68 BusinessData businessData = new BusinessData(); 69 businessData.setString("测试"); 70 businessData.setDate(new Date()); 71 businessData.setDoubleData(1.0); 72 List<BusinessData> businessDataList = Collections.singletonList(businessData); 73 // 定义写入器 74 ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFile).build(); 75 // 定义填充页 sheet 76 WriteSheet writeSheet0 = EasyExcel.writerSheet().registerWriteHandler(new CustomTemplateSheetStrategy("动态命名sheet")).build(); 77 // 定义业务页 sheet 78 WriteSheet writeSheet1 = EasyExcel.writerSheet("Sheet1").head(BusinessData.class).build(); 79 // 填充数据 80 excelWriter.fill(fillData, writeSheet0); 81 // 写入数据 82 excelWriter.write(businessDataList, writeSheet1); 83 // 关闭写入器 84 excelWriter.finish(); 85 } 86} 87
环境:
- JDK:1.8.0_202
- SpringBoot:2.7.17
- EasyExcel:3.3.2
