介绍
对Execl进行读写操作,可以使用poi完成,但是它是将整个 Excel 的内容全部读出来放入到内存中,所以内存消耗非常严重,如果同时进行包含大数据量的 Excel 读操作,很容易造成内存溢出问题。
使用EasyExecl工具类可以很好地避免上面的问题,同时对底层进行了封装,简化了代码,十分好用。
使用指南
依赖导入
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.1</version>
</dependency>
创建实体类
@Data
public class User {
// index : 表示execl中的列数
@ExcelProperty(index = 0)
private Long id;
@ExcelProperty(index = 1)
private String name;
// converter: 自定义转换器
@ExcelProperty(index = 2,converter = GenderConverter.class)
private Integer gender;
}
简单写
简单读
public void testRead(){
// 要读取的文件路径(也可以调用重载的方法,传入文件输入流)
String filePath = "D:/user.xlsx";
// 执行读方法 (读取操作在监听器中完成)
EasyExcel.read(filePath,User.class,new ExeclListener()).sheet().doRead();
}
配置读取操作监听器
public class ExeclListener extends AnalysisEventListener<User> {
/**
* 读取表头数据
* @param headMap
* @param context
*/
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
System.out.println("表头数据:"+headMap.get(0)+"---"+headMap.get(1)+"---"+headMap.get(2));
}
/**
* 读取主体内容,每次读取一行
* @param user
* @param analysisContext
*/
@Override
public void invoke(User user, AnalysisContext analysisContext) {
System.out.println("进行一次读取");
System.out.println(user);
}
/**
* 读取数据完毕后调用
* @param analysisContext
*/
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
System.out.println("完成了全部数据的读取");
}
}
存在的问题
由于监听器无法被Spring管理,所以不能在监听器中注入service/dao接口进行数据的持久化,通常使用有参构造传入接口对象的方式实现,然后通过持久层接口完成数据的持久化。
由于在invoke方法中每次读取一行,所以在保存数据时也存在两种方法:
- 每次将读取到的数据调用接口完成数据库的插入(n行数据操作n次数据库)
- 将每次读取到的数据存在一个list集合中,将list结合达到一定大小时,批量完成数据库的插入操作
配置定义转换器
execl表中可能存在如性别是男/女表示,数据库是0 1表示的情况,或者是事件类型的不匹配,这个时候需要自定义转换器。
public class GenderConverter implements Converter<Integer> {
public static final String MALE = "男";
public static final String FEMALE = "女";
@Override
public Class supportJavaTypeKey() {
return Integer.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public Integer convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
String stringValue = cellData.getStringValue();
if (MALE.equals(stringValue)){
return 0;
}else {
return 1
}
}
@Override
public CellData convertToExcelData(Integer integer, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
return null;
}
}