EasyExcel是一个快速、简单的Excel操作框架,特别适合大批量数据的读写操作,下面我们就来看看如何在Spring Boot项目中整合EasyExcel框架来实现复杂表格数据的导入导出功能。
实现Excel导出功能
引入依赖
首先我们需要在项目的pom.xml文件中引入EasyExcel相关的依赖,如下所示。
com.alibaba
easyexcel
3.0.5
实现逻辑
创建需要Excel导出的实体类,这里我们实现了一个简单的数据导出操作,在实际场景中可以结合实际业务来实现,如下所示。
@Data
public class UserData {
@ExcelProperty("用户编号")
private Long userId;
@ExcelProperty("用户名")
private String username;
@ExcelProperty("邮箱")
private String email;
@ExcelProperty("注册时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private LocalDateTime registerTime;
}
接下来编写一个控制器来处理 Excel 导出请求,如下所示。
@RestController
@RequestMapping("/excel")
public class ExcelExportController {
@GetMapping("/export")
public void exportExcel(HttpServletResponse response) throws IOException {
// 模拟一些导出数据
List userList = Arrays.asList(
new UserData(1L, "Alice", "alice@example.com", LocalDateTime.now()),
new UserData(2L, "Bob", "bob@example.com", LocalDateTime.now())
);
// 设置响应头
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode("用户数据", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
// 写入 Excel
EasyExcel.write(response.getOutputStream(), UserData.class)
.sheet("用户信息")
.doWrite(userList);
}
}
上面的操作就实现了一个简单的Excel的导出功能,我们可以通过访问数据导出接口来实现Excel数据文件的导出操作。
实现Excel导入功能
和导出一样,导入数据时也需要定义对应的实体类。与导出可以共用实体类,接下来就是实现数据导入操作逻辑处理,如下所示。在使用EasyExcel进行导入时需要实现一个AnalysisEventListener,这样我们可以通过这个监听器来处理每一行的Excel数据,如下所示。
public class UserExcelListener extends AnalysisEventListener {
private List userList = new ArrayList<>();
// 每读一行数据都会调用该方法
@Override
public void invoke(UserData userData, AnalysisContext context) {
userList.add(userData);
}
// 数据全部读完后调用
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里可以执行批量插入数据库等操作
System.out.println("Excel 数据读取完成,共 " + userList.size() + " 条数据");
}
public List getUserList() {
return userList;
}
}
编写导入控制器,用来接收文件上传数据并使用EasyExcel解析Excel中的数据操作,如下所示。
@RestController
@RequestMapping("/excel")
public class ExcelImportController {
@PostMapping("/import")
public String importExcel(@RequestParam("file") MultipartFile file) throws IOException {
if (file.isEmpty()) {
return "上传文件为空";
}
UserExcelListener listener = new UserExcelListener();
EasyExcel.read(file.getInputStream(), UserData.class, listener).sheet().doRead();
List userList = listener.getUserList();
// 这里可以把数据保存到数据库中
// userService.saveBatch(userList);
return "导入成功,共 " + userList.size() + " 条数据";
}
}
接口接收Excel文件,读取文件内容并通过UserExcelListener将数据解析后存储到userList中,最终返回导入数据的条数。当然在处理完成之后,我们也可以将数据写入到数据库中,或者是其他的持久化机制中。
复杂表格的处理
如果导入导出的Excel表格比较复杂,比如有合并单元格、多级表头等,这样我们就可以通过如下的方式来对相关的操作进行优化。
多级表头的处理
可以使用 @ExcelProperty 注解中的数组来实现多级表头,如下所示。
@Data
public class ComplexUserData {
@ExcelProperty({"用户信息", "用户编号"})
private Long userId;
@ExcelProperty({"用户信息", "用户名"})
private String username;
@ExcelProperty({"联系信息", "邮箱"})
private String email;
@ExcelProperty({"联系信息", "电话号码"})
private String phone;
}
合并单元格
要实现合并单元格的操作,需要添加自定义表格合并处理器CellWriteHandler,如下所示,定义一个单元格合并处理器。
public class MergeCellWriteHandler implements CellWriteHandler {
@Override
public void afterCellDispose(CellWriteHandlerContext context) {
WriteSheetHolder sheetHolder = context.getWriteSheetHolder();
WriteCellData> cellData = context.getFirstCellData();
// 合并逻辑,示例中简单的根据数据情况合并单元格
if (context.getRowIndex() == 0 && context.getColumnIndex() == 0) {
CellRangeAddress cellRangeAddress = new CellRangeAddress(0, 0, 0, 1); // 合并第一行的前两列
sheetHolder.getSheet().addMergedRegion(cellRangeAddress);
}
}
}
然后在写入 Excel 时配置,对相关单元格进行合并处理。如下所示。
EasyExcel.write(response.getOutputStream(), ComplexUserData.class)
.registerWriteHandler(new MergeCellWriteHandler()) // 注册合并单元格处理器
.sheet("复杂表格")
.doWrite(complexUserList);
总结
通过EasyExcel,我们可以轻松实现Excel的导入导出功能对于复杂表格,并且我们也可以通过自定义监听器、表头处理和合并单元格来解决复杂场景的表格数据处理。这样我们就可以对Excel表格的处理。