当在后端开发中处理Excel业务时,EasyExcel是一个非常有用的工具,它提供了强大的模板填充功能,可以轻松解决各种业务需求。在本文中,我将首先简要介绍EasyExcel模板填充功能的基本用法,然后提供一种根据业务需要执行多份复制与填充的实用方案。
EasyExcel模板填充功能的基本用法
使用EasyExcel的[模板填充功能]与[简单写]相比,可以diy工作表(sheet)的样式,让生成的excel更加美观且不必花费更多的开发时间。
使用简单写完成一个Excel报表
-
创建Java类,方便构建数据映射到Excel中;在类中使用注解配置单元格格式和标题
@ExcelProperty
: 设置excel中标题名称@ColumnWidth
: 设置单元格的宽度
java
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CatDTO {
@ExcelProperty(value = "姓名")
private String name;
@ExcelProperty(value = "品种")
@ColumnWidth(15)
private String breed;
@ExcelProperty(value = "年龄")
private Double age;
@ExcelProperty(value = "描述")
@ColumnWidth(30)
private String desc;
}
- 使用EasyExcel提供的Write API,将数据写入Excel中。
java
@SpringBootTest
class DemoApplicationTests {
@Test
void writeTest1() {
String fileName = "write-" + System.currentTimeMillis() + ".xlsx";
// 构建数据
List<CatDTO> catWriteData = List.of(
CatDTO.builder().name("肥猫").breed("银渐层").age(1.2).desc("每天吃吃睡睡睡睡睡").build(),
CatDTO.builder().name("虎妞").breed("德文卷毛猫").age(0.6).desc("活泼好动无敌可爱爱粘人").build()
);
EasyExcel.write(fileName, CatDTO.class).sheet().doWrite(catWriteData);
}
}
- 生成效果
使用模板填充完成一个Excel报表
- 创建Java类
java
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CatFillDTO {
private String name;
private String breed;
private Double age;
private String desc;
}
- 构建模板,在数据填充所在列上,填上与之对应的实体类属性名;
- 使用EasyExcel提供的Fill API,获取模板文件,写入数据。
java
@SpringBootTest
class DemoApplicationTests {
@Test
void fillTest1() {
String fileName = "fill-" + System.currentTimeMillis() + ".xlsx";
// 构建数据
List<CatFillDTO> catFillData = List.of(
CatFillDTO.builder().name("肥猫").breed("银渐层").age(1.2).desc("每天吃吃睡睡睡睡睡").build(),
CatFillDTO.builder().name("虎妞").breed("德文卷毛猫").age(0.6).desc("活泼好动无敌可爱爱粘人").build()
);
FileUtil.touch(fileName);
// 加载模板
InputStream resourceAsStream = ResourceUtil.getStreamSafe("temp/cat-template.xlsx");
// 生成工作簿对象
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(resourceAsStream).build();
// 生成工作表对象
WriteSheet writeSheet = EasyExcel.writerSheet().build();
// 多组数据填充需要另起一行时 forceNewRow(true)
FillConfig fillConfig = FillConfig.builder().forceNewRow(true).build();
// 多组数据填充 List<实体类> 对象
excelWriter.fill(catFillData, fillConfig, writeSheet);
// 关闭excelWriter
excelWriter.finish();
}
}
- 生成效果
可以看出,使用模板填充可以省去在代码中配置字段名称、单元格大小等配置,在实现复杂的Excel样式或美观修饰上更有优势;
根据业务需要执行多份复制与填充的方案
在处理Excel时,你或许会遇到这样的问题。使用指定模板填充数据,数据根据某个特征进行划分,分别填进不同的工作表(sheet)中,这样,我们需要根据业务的需求, 来生成相应的模板表数量,再分别填充上数据。
实现思路
- 使用POI API加载模板文件为Workbook对象
- 使用POI中的cloneSheet API复制相应数量的模板工作表
- 将复制好数量的工作簿文件转换成输入流,以便在EasyExcel withTemplate API中使用
- 使用EasyExcel fill API填充数据。
(直接上业务代码,实现的功能为模板表1不执行复制,只进行填充,模板表2进行复制并填充)
java
@Service
@Slf4j
@RequiredArgsConstructor
public class SpeakerServiceImpl implements ISpeakerService {
/**
* 填充模板文件
*
* @param sheet1Data sheet1数据
* @param promptMap 提示地图
* @return {@code File}
*/
public File fillTemplateFile(
CustomSpeakerDemandExcelDTO sheet1Data, Map<String, List<CustomSpeakerPromptDTO>> promptMap) {
try {
// 构建模板
byte[] asInputStream = this.buildTemplateFile(promptMap);
// 创建临时导出文件
File temporaryFile = Files.createTempFile("speaker_task_", ".xlsx").toFile();
// easyExcel API 根据is作为模板填充数据,并写入临时文件temporaryFile
ExcelWriter excelWriter = EasyExcel.write(temporaryFile)
.withTemplate(new ByteArrayInputStream(asInputStream))
.build();
// 填充模板1的sheet
WriteSheet writeSheet1 = EasyExcel.writerSheet(0).build();
excelWriter.fill(sheet1Data, writeSheet1);
// 填充模板2的多个sheet
int sheetIndex = 1;
for (String key : promptMap.keySet()) {
WriteSheet writeSheet = EasyExcel.writerSheet(sheetIndex).build();
// 写入数据到当前sheet
List<CustomSpeakerPromptDTO> prompt = promptMap.get(key);
excelWriter.fill(prompt, writeSheet);
sheetIndex++;
}
excelWriter.finish();
return temporaryFile;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 构建模板文件
*
* @param promptMap 提示地图
* @return {@code byte[]}
* @throws IOException ioexception
*/
public byte[] buildTemplateFile(Map<String, List<CustomSpeakerPromptDTO>> promptMap) throws IOException {
// 加载模板文件
InputStream templateStream = ResourceUtil.getStreamSafe("temp/speaker-task-template.xlsx");
Workbook workbook = WorkbookFactory.create(templateStream);
// 设置模板sheet数量, 需要复制promptMap.size()-1 次工作表2
boolean first = true;
for (String key : promptMap.keySet()) {
if (first) {
// 第一组数据可以直接使用当前模板,不需要进行复制
workbook.setSheetName(1, key);
} else {
// 复制模板到新工作表,并设置表名
Sheet newSheet = workbook.cloneSheet(1);
workbook.setSheetName(workbook.getSheetIndex(newSheet), key);
}
first = false;
}
ByteArrayOutputStream ops = new ByteArrayOutputStream();
workbook.write(ops);
byte[] byteArray = ops.toByteArray();
// 原文件流后续已不使用,此处关闭
templateStream.close();
ops.close();
return byteArray;
}
}
酸奶小肥阳原创,欢迎阅读点赞加收藏,关注我随时与我技术交流吧😄