EasyExcel 是一款基于 Java 的简单易用的 Excel 文件操作工具。它提供了丰富的 API,可以方便地读取、写入和操作 Excel 文件,支持常见的 Excel 操作,如读取/写入单元格数据、合并单元格、设置样式、处理大数据量等。EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。
使用 EasyExcel 可以读取 Excel 文件的内容并将其转化为 Java 对象,或者按行进行处理。例如:
// 读取 Excel 文件内容并转化为 Java 对象
List<User> userList = EasyExcel.read("path/to/excel.xlsx").sheet().doReadSync(User.class);
// 按行处理 Excel 文件
EasyExcel.read("path/to/excel.xlsx").sheet().doReadSync(new AnalysisEventListener<User>() {
@Override
public void invoke(User user, AnalysisContext context) {
// 处理每行数据
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 处理完成后的回调
}
});
EasyExcel 提供了方便的 API 来写入数据到 Excel 文件中。例如:
// 写入 Java 对象到 Excel 文件
EasyExcel.write("path/to/excel.xlsx").sheet().doWrite(userList);
// 写入指定数据到 Excel 文件
List<List<Object>> data = new ArrayList<>();
// 添加数据到 data 列表...
EasyExcel.write("path/to/excel.xlsx").sheet().doWrite(data);
EasyExcel 允许你设置单元格的样式、合并单元格、设置表头等操作。例如:
// 设置表头
List<List<String>> head = new ArrayList<>();
// 添加表头数据到 head 列表...
EasyExcel.write("path/to/excel.xlsx").head(head).sheet().doWrite(data);
// 设置单元格样式
WriteCellStyle style = new WriteCellStyle();
// 设置样式属性...
WriteSheet sheet = EasyExcel.writerSheet(0).build();
sheet.setCellStyle(style);
EasyExcel.write("path/to/excel.xlsx").sheet(sheet).doWrite(data);
// 合并单元格
WriteSheet sheet = EasyExcel.writerSheet(0).build();
sheet.setAutomaticMergeHead(true); // 自动合并表头
sheet.merge(firstRow, lastRow, firstCol, lastCol); // 合并单元格
EasyExcel.write("path/to/excel.xlsx").sheet(sheet).doWrite(data);
EasyExcel 提供了一些特性来处理大数据量的 Excel 文件,如使用滑动窗口来限制内存占用、使用回调接口来处理每行数据等。这些特性可以帮助你高效地处理大型 Excel 文件而不会导致内存溢出。例如:
// 大数据量写入
EasyExcel.write("path/to/excel.xlsx", User.class).sheet().registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).doWrite(userList);
<dependency>
<groupId>com.alibabagroupId>
<artifactId>easyexcelartifactId>
<version>3.3.2version>
dependency>
**
* 用户 Excel 导出 VO
*/
@Data
public class UserExcelVO {
@ExcelProperty("用户编号")
private Long id;
@ExcelProperty("用户名称")
private String username;
@ExcelProperty("用户昵称")
private String nickname;
@ExcelProperty("用户邮箱")
private String email;
@ExcelProperty("手机号码")
private String mobile;
@ExcelProperty(value = "用户性别", converter = DictConvert.class)
@DictFormat(DictTypeConstants.USER_SEX)
private Integer sex;
@ExcelProperty(value = "帐号状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.COMMON_STATUS)
private Integer status;
@ExcelProperty("最后登录IP")
private String loginIp;
@ExcelProperty("最后登录时间")
private LocalDateTime loginDate;
@ExcelProperty("部门名称")
private String deptName;
@ExcelProperty("部门负责人")
private String deptLeaderNickname;
}
① 每个字段上的 @ExcelProperty (opens new window)注解,声明 Excel Head 头部的名字
② 每个字段的值,就是它对应的 Excel Row 行的数据值
③ @ExcelProperty 注解的 converter 属性是 DictConvert 转换器,通过它将 status = 1 转换成“开启”列,status = 0 转换成”禁用”列,注解 @DictFormat (opens new window)为对应的字典数据的类型。
更多《EasyExcel 中的注解 》
public class ExcelUtils {
/**
* 将列表以 Excel 响应给前端
*
* @param response 响应
* @param filename 文件名
* @param sheetName Excel sheet 名
* @param head Excel head 头
* @param data 数据列表哦
* @param 泛型,保证 head 和 data 类型的一致性
* @throws IOException 写入失败的情况
*/
public static <T> void write(HttpServletResponse response, String filename, String sheetName,
Class<T> head, List<T> data) throws IOException {
// 输出 Excel
EasyExcel.write(response.getOutputStream(), head)
.autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度
.sheet(sheetName).doWrite(data);
// 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
}
public static <T> List<T> read(MultipartFile file, Class<T> head) throws IOException {
return EasyExcel.read(file.getInputStream(), head, null)
.autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
.doReadAllSync();
}
}
@GetMapping("/export")
@Operation(summary = "导出用户")
@OperateLog(type = EXPORT)
public void exportUserList(@Validated UserExportReqVO reqVO,
HttpServletResponse response) throws IOException {
// 获得用户列表
List<UserDO> users = userService.getUserList(reqVO);
UserExcelVO excelVO = UserConvert.INSTANCE.convert02(user);
// 输出
ExcelUtils.write(response, "用户数据.xls", "用户列表", UserExcelVO.class, excelVO );
}
@PostMapping("/import")
@Operation(summary = "导入用户")
@Parameters({
@Parameter(name = "file", description = "Excel 文件", required = true),
@Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true")
})
public void importExcel(@RequestParam("file") MultipartFile file,
@RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception {
List<UserImportExcelVO> list = ExcelUtils.read(file, UserImportExcelVO.class);
}