回到:github原作者地址:https://github.com/CodePhiliaX/fastexcel
案例官网:https://easyexcel.opensource.alibaba.com/docs/current/
什么是 FastExcel
FastExcel 是由原 EasyExcel 作者创建的新项目。2023 年我已从阿里离职,近期阿里宣布停止更新 EasyExcel,作者他本人决定继续维护和升级这个项目。在重新开始时,为它起名为 FastExcel,以突出这个框架在处理 Excel 文件时的高性能表现,而不仅仅是简单易用。
FastExcel 将始终坚持免费开源,并采用最开放的 MIT 协议,使其适用于任何商业化场景。这为开发者和企业提供了极大的自由度和灵活性。FastExcel 的一些显著特点包括:
- 1、完全兼容原 EasyExcel 的所有功能和特性,这使得用户可以无缝过渡。
- 2、从 EasyExcel 迁移到 FastExcel 只需简单地更换包名和 Maven 依赖即可完成升级。
- 3、在功能上,比 EasyExcel 提供更多创新和改进。
- 4、FastExcel 1.0.0 版本新增了读取 Excel 指定行数和将 Excel 转换为 PDF 的功能。
主要特性
-
- 高性能读写:FastExcel 专注于性能优化,能够高效处理大规模的 Excel 数据。相比一些传统的 Excel 处理库,它能显著降低内存占用。
-
- 简单易用:该库提供了简洁直观的 API,使得开发者可以轻松集成到项目中,无论是简单的 Excel 操作还是复杂的数据处理都能快速上手。
-
- 流式操作:FastExcel 支持流式读取,将一次性加载大量数据的问题降到最低。这种设计方式在处理数十万甚至上百万行的数据时尤为重要。
安装
下表列出了各版本 FastExcel 基础库对 Java 语言版本最低要求的情况:
版本 | jdk版本支持范围 | 备注 |
---|---|---|
1.0.0+ | jdk8 - jdk21 | 目前的master分支,完全兼容easyexcel |
强烈建议您使用最新版本的 FastExcel,因为最新版本中的性能优化、BUG修复和新功能都会让您的使用更加方便。
当前 FastExcel 底层使用 poi 作为基础包,如果您的项目中已经有 poi 相关组件,需要您手动排除 poi 的相关 jar 包。
Maven
如果您使用 Maven 进行项目构建,请在 pom.xml
文件中引入以下配置:
<dependency>
<groupId>cn.idev.excel</groupId>
<artifactId>fastexcel</artifactId>
<version>1.2.0</version>
</dependency>
 {
System.out.println("解析到一条数据" + JSON.toJSONString(data));
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
System.out.println("所有数据解析完成!");
}
}
public static void main(String[] args) {
String fileName = "demo.xlsx";
// 读取 Excel 文件
FastExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();
}
简单示例:创建 Excel 文件
下面是一个创建 Excel 文档的简单例子:
// 示例数据类
public class DemoData {
@ExcelProperty("字符串标题")
private String string;
@ExcelProperty("日期标题")
private Date date;
@ExcelProperty("数字标题")
private Double doubleData;
@ExcelIgnore
private String ignore;
}
// 填充要写入的数据
private static List<DemoData> data() {
List<DemoData> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
DemoData data = new DemoData();
data.setString("字符串" + i);
data.setDate(new Date());
data.setDoubleData(0.56);
list.add(data);
}
return list;
}
public static void main(String[] args) {
String fileName = "demo.xlsx";
// 创建一个名为“模板”的 sheet 页,并写入数据
FastExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
}
controller 案例
/**
* 导出excel 表格
* @param sysRole 查询条件
* @param ids 导出ids
* @return
*/
@ResponseExcel
@GetMapping("/export")
@HasPermission("sys_role_export")
public List<RoleExcelVO> export(SysRole sysRole, Long[] ids) {
return sysRoleService.exportListRole(sysRole, ids);
}
/**
* 导入角色
* @param excelVOList 角色列表
* @param bindingResult 错误信息列表
*/
@PostMapping("/import")
@HasPermission("sys_role_export")
public Result importRole(@RequestExcel List<RoleExcelVO> excelVOList, BindingResult bindingResult) {
return sysRoleService.importRole(excelVOList, bindingResult);
}
vo类
import jakarta.validation.constraints.NotBlank;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 角色excel 对应的实体
*/
@Data
@ColumnWidth(30)
public class RoleExcelVO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 导入时候回显行号
*/
@ExcelLine
@ExcelIgnore
private Long lineNum;
/**
* 主键ID
*/
@ExcelProperty("角色编号")
private Long roleId;
/**
* 角色名称
*/
@NotBlank(message = "角色名称不能为空")
@ExcelProperty("角色名称")
private String roleName;
/**
* 角色标识
*/
@NotBlank(message = "角色标识不能为空")
@ExcelProperty("角色标识")
private String roleCode;
/**
* 角色描述
*/
@NotBlank(message = "角色描述不能为空")
@ExcelProperty("角色描述")
private String roleDesc;
}
实现类方法
/**
* 导入角色
* @param excelVOList 角色列表
* @param bindingResult 错误信息列表
*/
@Override
public Result importRole(List<RoleExcelVO> excelVOList, BindingResult bindingResult) {
// 通用校验获取失败的数据
List<ErrorMessage> errorMessageList = (List<ErrorMessage>) bindingResult.getTarget();
// 个性化校验逻辑
List<SysRole> roleList = this.list();
// 执行数据插入操作 组装 RoleDto
for (RoleExcelVO excel : excelVOList) {
Set<String> errorMsg = new HashSet<>();
// 检验角色名称或者角色编码是否存在
boolean existRole = roleList.stream()
.anyMatch(sysRole -> excel.getRoleName().equals(sysRole.getRoleName())
|| excel.getRoleCode().equals(sysRole.getRoleCode()));
existRole ? errorMsg.add(MsgUtils.getMessage(ErrorCodes.SYS_ROLE_EXIST, excel.getRoleName(),excel.getRoleCode())) : null;
// 数据合法情况
CollUtil.isEmpty(errorMsg) ? insertExcelRole(excel): errorMessageList.add(new ErrorMessage(excel.getLineNum(), errorMsg));
}
if (CollUtil.isNotEmpty(errorMessageList)) {
return R.failed(errorMessageList);
}
return Result.ok();
}
/**
* 查询全部的角色
* @return list
*/
@Override
public List<RoleExcelVO> listRole(SysRole sysRole, Long[] ids) {
List<SysRole> roleList = this
.list(Wrappers.lambdaQuery(sysRole).in(ArrayUtil.isNotEmpty(ids), SysRole::getRoleId, ids));
// 转换成execl 对象输出
return roleList.stream().map(role -> {
RoleExcelVO roleExcelVO = new RoleExcelVO();
BeanUtil.copyProperties(role, roleExcelVO);
return roleExcelVO;
}).collect(Collectors.toList());
}
/**
* 插入excel Role
*/
private void insertExcelRole(RoleExcelVO excel) {
SysRole sysRole = new SysRole();
sysRole.setRoleName(excel.getRoleName());
sysRole.setRoleDesc(excel.getRoleDesc());
sysRole.setRoleCode(excel.getRoleCode());
this.save(sysRole);
}