EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。
github文档: https://github.com/alibaba/easyexcel
<dependency>
<groupId>com.alibabagroupId>
<artifactId>easyexcelartifactId>
<version>2.2.3version>
dependency>
常用如下两种读取方式
EasyExcel.read(文件名/文件流,数据实体类.class,监听器).sheet().doRead();
EasyExcel.read(文件名/文件流,数据实体类.class,监听器).build();
实例1:
(这里假设已有实体类User)
public void test1() {
EasyExcel.read("D:\\file\\1.xlsx", User.class, new AnalysisEventListener<User>() {
// 每解析一行数据,该方法会被调用一次
@Override
public void invoke(User user, AnalysisContext analysisContext) {
System.out.println("解析数据为:" + user.toString());
}
// 全部解析完成被调用
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
System.out.println("解析完成...");
// 保存到数据库
}
}).sheet().doRead();
}
实例2:
(这里假设已有实体类User)
// springboot 接口
@PostMapping("/importUser")
public void importUser(@RequestParam("file") MultipartFile file)
ExcelReader excelReader = EasyExcel.read(file.getInputStream(), User.class, new AnalysisEventListener<DemoData>() {
@Override
public void invoke(User user, AnalysisContext analysisContext) {
System.out.println("解析数据为:" + user.toString());
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
System.out.println("解析完成...");
// 保存到数据库
}
}).build();
ReadSheet sheet = EasyExcel.readSheet(0).build(); // 创建sheet对象,读取Excel的第一个sheet, 也可以根据sheet名称获取
excelReader.read(sheet); // 读取sheet表格数据,可以读取多个sheet
excelReader.finish(); // 这里必须手动关闭
}
读取多个sheet表格
// 方式1
EasyExcel.read(...)
// .sheet(0).doRead();
.doReadAll(); // 读取全部sheet
// 方式2
ExcelReader excelReader = EasyExcel.read(...) .build();
ReadSheet sheet = EasyExcel.readSheet(0).build();
//excelReader.read(sheet);
excelReader.readAll(); // 读所有sheet
excelReader.finish();
// 读指定的多个sheet
ExcelReader excelReader = EasyExcel.read(...) .build();
ReadSheet sheet = EasyExcel.readSheet(0).build();
// 读取sheet,有几个就构建几个sheet进行读取
excelReader.read(sheet0);
excelReader.finish();
每次调用 EasyExcel.read() 都需要 new 一个 AnalysisEventListener 对象,我们可以将AnalysisEventListener封装为一个对象,方便重复调用
public class EasyExcelUtils<T> {
/**
* 获取读取Excel的监听器对象
* @param consumer 处理解析数据的函数, 一般可以是数据入库逻辑的函数
* @param threshold 阈值,达到阈值就处理一次存储的数据
* @param 数据模型泛型
* @return 返回监听器
*/
public static <T> AnalysisEventListener<T> getReadListener(Consumer<List<T>> consumer, int threshold) {
return new AnalysisEventListener<T>() {
// ArrayList 查询更快
// List dataList = new ArrayList<>(threshold);
// LinkedList 插入和删除更快
List<T> dataList = new LinkedList<>();
/**
* 每解析一行调用, 订阅者1
* @param data 解析的每行数据
* @param context
*/
@Override
public void invoke(T data, AnalysisContext context) {
dataList.add(data);
// 达到阈值就处理一次存储的数据
if (dataList.size() >= threshold) {
consumer.accept(dataList);
dataList.clear();
}
}
/**
* excel文件解析完成后,事件调度中心会通知到该方法, 订阅者2
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 最后阈值外的数据做处理
if (dataList.size() > 0) {
consumer.accept(dataList);
}
}
};
}
/**
* 获取读取Excel的监听器对象, 不指定阈值, 默认阈值为 2000
*/
public static <T> AnalysisEventListener<T> getReadListener(Consumer<List<T>> consumer) {
return getReadListener(consumer, 2000);
}
}
使用示例
// 读取excel文件
public void test() {
EasyExcel.read("user.xlsx", User.class,EasyExcelUtils.getReadListener(dataProcess())).doReadAll();
}
// 处理数据
public Consumer<List<User>> dataProcess() {
return users -> users.forEach(System.out::println);
}
在实体类中加入注解可以格式化数据,
与lombok结合使用。
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class User {
@ExcelProperty(value = "字符串标题", index = 0)
private String name;
@ExcelProperty(value = "日期标题", index = 1)
@DateTimeFormat(value = "yyyy年MM月dd日 HH时mm分ss秒") // 格式化日期类型数据
private Date hireDate;
@ExcelProperty(value = "数字标题", index = 2)
@NumberFormat(value = "###.#") // 格式化数字类型数据,保留一位小数,@NumberFormat不能用在Double类型中
private String salary;
}
// 1、根据实体对象导出文件
EasyExcel.write(response.getOutputStream(), 实体.class).sheet().doWrite(list<实体>);
// 2、根据List>导出文件
EasyExcel.write(response.getOutputStream()).head(表头list对象).sheet().doWrite(数据list对象);
// 3、根据模板文件
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(new ClassPathResource("模板.xlsx").getInputStream()).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
excelWriter.fill(list实体对象, writeSheet); // 填充数据1
excelWriter.fill(map对象, writeSheet); // 填充数据2
excelWriter.finish(); // 关闭流
在实体类中定义
@Data
@NoArgsConstructor
//@ContentRowHeight(50)//内容单元格高度
//@HeadRowHeight(50)//表头单元格高度
//@ColumnWidth(50)//单元格宽度
public class User {
@ExcelProperty(value = {"导出台账","序号"})
private Integer no;
@ExcelProperty(value = {"导出台账","编号"})
private String code;
}