目录
一、文章简介
二、概念
1.EasyExcel是什么?
2.EasyExcel 能用在哪里?
3.为什么要选用EasyExcel解析excel?
4.如何使用EasyExcel?
三、EasyExcel快速入门
1.环境搭建
2.简单写excel
代码示例
TestFileUtil
Employee
SimpleWrite
演示效果
3.简单读excel
代码示例
SimpleRead
演示效果
四、EasyExcel进阶操作
1.批量(重复)写数据
代码示例
ManyWrite
效果演示
2.按模版填充单个对象数据
代码示例
效果演示
3.按模版批量填充多个对象数据
代码示例
4.自定义监听器读海量(百万级别)数据并监控内存消耗
代码示例
EmployeeDao
EmployeeListener
MyRead
五、EasyExcel综合应用
阿里EasyExcel 即学即会:海量数据的导入导出
一、文章简介
主要讲解在java应用中如何利用EasyExcel技术完成对excel文件的导入和导出操作。
数据从excel------->数据库: 导入
数据从数据库-------->excel:导出
二、概念
1.EasyExcel是什么?
-
EasyExcel是一个基于Java的简单、省内存的读写Excel的阿里开源项目。
-
在尽可能节约内存的情况下支持读写百M的Excel。
2.EasyExcel 能用在哪里?
项目中涉及到Excel文件,CVS文件大多数的读写操作,均可以使用。
3.为什么要选用EasyExcel解析excel?
4.如何使用EasyExcel?
阿里官方文档: EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel 官网
三、EasyExcel快速入门
1.环境搭建
-
创建maven工程
-
引入相关坐标
-
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.2</version> </dependency>
-
-
参考官方API完成功能
2.简单写excel
-
编写模型类并加入注解
-
编写获取测试数据的方法
-
调用官方API完成写功能
-
核心代码:
EasyExcel.write(fileName, DemoData.class).sheet("测试").doWrite(data(100000));
代码示例
TestFileUtil
获取代码路径的工具类
package com.ithiema.utils;
/*获取代码路径的工具类,可以获取到模块这一级的磁盘路径;*/
public class TestFileUtil {public static String getPath() {return TestFileUtil.class.getResource("/").getPath().replace("classes/","");}
public static void main(String[] args) {System.out.println(getPath());}
}
Employee
员工类
package com.ithiema.pojo;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {@ExcelProperty("员工工号")private int id;@ExcelProperty("员工姓名")private String name;@ExcelProperty("员工工资")private double salary;@ExcelProperty("入职日期")private Date date;
}
SimpleWrite
easyexcel的简单写数据
package com.ithiema.write;
import com.alibaba.excel.EasyExcel;
import com.ithiema.pojo.Employee;
import com.ithiema.utils.TestFileUtil;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
/*练习easyexcel的简单写数据*/
public class SimpleWrite {
@Testpublic void testWrite(){String name = TestFileUtil.getPath() + "简单写数据" + System.currentTimeMillis() + ".xlsx";EasyExcel.write(name, Employee.class).sheet("我的快速入门").doWrite(data(12));}
// 准备测试数据的方法private List<Employee> data(int i) {List<Employee> list = new ArrayList<>();for (int j = 1; j <= i; j++) {list.add(new Employee(j,"测试数据"+j,6.6*j,new Date()));}return list;}
}
演示效果
3.简单读excel
-
编写模型类并加入注解
-
监听器介绍
-
调用官方API完成写功能
-
核心代码:
EasyExcel.read(fileName, DemoData.class, new PageReadListener<DemoData>
(list -> System.out.println(list))).sheet().doRead();
代码示例
SimpleRead
快速入门,简单读
package com.ithiema.read;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener;
import com.ithiema.pojo.Employee;
import com.ithiema.utils.TestFileUtil;
import org.junit.Test;
import java.io.File;
/*快速入门,简单读*/
public class SimpleRead {/*** 使用EasyExcel框架读取Excel文件** 指定文件路径,数据模型类(Employee.class),以及一个读取监听器,用于处理读取到的每条数据。* 文件名通过TestFileUtil.getPath()获取相对路径,并拼接上特定的文件名。* 使用EasyExcel的read方法指定文件名、数据模型类和监听器,然后调用sheet().doRead()开始读取第一个工作表的数据。*/@Testpublic void testRead(){// 构建文件路径String fileName = "D:\\develop\\dev\\easyexcel-course\\easyExcel-heima\\QuickStart\\target\\test-简单写数据1722256409955.xlsx";// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭// 这里每次会读取100条数据 然后返回过来 直接调用使用数据就行EasyExcel.read(fileName, Employee.class, new PageReadListener<Employee>(dataList -> {// 遍历并打印读取到的每个员工对象for (Employee employee : dataList) {System.out.println(employee);}})).sheet(0).doRead();}}
演示效果
四、EasyExcel进阶操作
1.批量(重复)写数据
-
编写模型类并加入注解
-
调用官方API完成写功能
try (ExcelWriter writer = EasyExcel.write(fileName, DemoData.class).build()) {WriteSheet writeSheet = EasyExcel.writerSheet("测试表1").build();for (int i = 0; i < 3; i++) {ExcelWriter write = writer.write(data(100000), writeSheet);}}
代码示例
ManyWrite
进阶写数据
package com.ithiema.write;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.ithiema.pojo.Employee;
import com.ithiema.utils.TestFileUtil;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/*进阶写数据*/
public class ManyWrite {
/*** 批量写入Excel数据* * 该方法创建一个Excel文件,然后分三次写入100条员工数据。* 使用EasyExcel框架简化了Excel文件的写入操作。*/@Testpublic void testWrite(){// 构建文件名,包含批量写数据字样和当前时间戳,确保文件名的唯一性String name = TestFileUtil.getPath() + "批量写数据" + System.currentTimeMillis() + ".xlsx";// 与文件想关联的写对象 使用try-with-resources语句确保ExcelWriter资源在使用后能被正确关闭try (ExcelWriter writer = EasyExcel.write(name, Employee.class).build()) {// 准备一个表对象 设置写入的Sheet信息WriteSheet sheet = EasyExcel.writerSheet("批量写练习").build();// 循环三次,每次写入10000条员工数据// 利用writer向sheet表写数据for (int i = 1; i <= 3; i++) {writer.write(data(100), sheet);}}}// 准备测试数据的方法private List<Employee> data(int i) {List<Employee> list = new ArrayList<>();for (int j = 1; j <= i; j++) {list.add(new Employee(j,"测试数据"+j,6.6*j,new Date()));}return list;}
}
效果演示
上面写的数据格式不好看怎么办?
-
利用阿里提供的模版写数据
-
模版设置的样式新添加的数据会自动包含样式
2.按模版填充单个对象数据
-
编写模型类并加入注解
-
按要求编写模版文件
-
调用官方API完成写功能
EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(fillData);
代码示例
效果演示
3.按模版批量填充多个对象数据
-
编写模型类并加入注解
-
按要求编写模版文件
-
调用官方API完成写功能
try (ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build()) {WriteSheet writeSheet = EasyExcel.writerSheet(0).build();WriteSheet writeSheet2 = EasyExcel.writerSheet("数据2").build();excelWriter.fill(data(300000), writeSheet);excelWriter.fill(data(300000), writeSheet2);}
代码示例
package com.ithiema.write;
import com.alibaba.excel.EasyExcel;
import com.ithiema.pojo.Employee;
import com.ithiema.utils.TestFileUtil;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/*根据模版写数据*/
public class FillWriter {/*** 使用EasyExcel框架通过模板填充数据至新Excel文件** 此方法将从指定的模板文件读取样式和结构,然后填充20条数据(由data(20)方法提供)到名为"1025"的工作表中,* 并保存到新的Excel文件中,文件名中包含系统当前时间戳以确保唯一性。*/@Testpublic void testFill(){// 模板文件的绝对路径String templateFileName = "D:\\develop\\dev\\easyexcel-course\\easyExcel-heima\\QuickStart\\target\\模板.xlsx";// 目标文件的绝对路径,包含时间戳确保文件名唯一String fileName = "D:\\develop\\dev\\easyexcel-course\\easyExcel-heima\\QuickStart\\target\\"+System.currentTimeMillis()+ "按照模版写数据.xlsx";// 使用EasyExcel框架,指定目标文件、模板文件和工作表名称进行数据填充EasyExcel.write(fileName).withTemplate(templateFileName).sheet("1025").doFill(data(20));}// 准备测试数据的方法private List<Employee> data(int i) {List<Employee> list = new ArrayList<>();for (int j = 1; j <= i; j++) {list.add(new Employee(j,"测试数据"+j,6.6*j,new Date()));}return list;}
}
4.自定义监听器读海量(百万级别)数据并监控内存消耗
-
编写模型类并加入注解
-
自定义监听器
-
调用官方API完成写功能
EasyExcel.read(fileName, IndexOrNameData.class, new IndexOrNameDataListener()).sheet().doRead();
代码示例
EmployeeDao
package com.ithiema.dao;
import com.ithiema.pojo.Employee;
import java.util.List;
public class EmployeeDao {public void saveData(List<Employee> list){System.out.println("模拟保存数据..."+list.size());}
}
EmployeeListener
/*** EmployeeListener 类实现了 ReadListener 接口,用于处理 Excel 文件读取过程中的数据事件。* 主要功能是在读取每行数据时将其添加到一个列表中,当列表达到预设大小时批量保存数据到数据库,* 并在读取完成后处理剩余未达批次的数据。*/
public class EmployeeListener implements ReadListener<Employee> {
/*** 批量保存数据的阈值,默认为 100 条记录。*/private int count = 100;
/*** 数据访问对象,用于与数据库交互,执行数据保存操作。*/private EmployeeDao dao;
/*** 临时存储读取数据的列表,达到预设大小后清空并批量保存。*/private List<Employee> list = new ArrayList<>(count);
/*** 构造函数,初始化数据访问对象。** @param dao 数据访问对象,用于数据的持久化操作。*/public EmployeeListener(EmployeeDao dao) {this.dao = dao;}
/*** 计数器,用于监控批量保存次数,每 100 批次调用一次垃圾回收。*/int c = 0;
/*** 当解析一行数据时调用此方法。* 将读取到的 Employee 对象添加到 list 中,当 list 达到预设大小时,调用 dao 的 saveData 方法批量保存数据,* 并重新初始化 list。** @param employee 解析得到的 Employee 对象。* @param analysisContext 分析上下文,包含解析过程中的相关信息。*/@Overridepublic void invoke(Employee employee, AnalysisContext analysisContext) {list.add(employee);if(list.size() >= count){dao.saveData(list);list = new ArrayList<>(count);c++;if(c % 100 == 0){System.gc(); // 每 100 批次调用一次垃圾回收,优化内存使用。}}}
/*** 在所有数据解析完成后调用此方法。* 处理剩余未达批次的数据,即当读取完成时 list 中可能还存在未保存的数据,此时将它们全部保存到数据库。** @param analysisContext 分析上下文,包含解析过程中的相关信息。*/@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {if(list.size() > 0){dao.saveData(list); // 保存剩余数据。}}
}
MyRead
package com.ithiema.read;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.ithiema.EmployeeListener.EmployeeListener;
import com.ithiema.dao.EmployeeDao;
import com.ithiema.pojo.Employee;
import com.ithiema.utils.TestFileUtil;
import org.junit.Test;
/*使用自定义监听器读数据*/
public class MyRead {
// 读单表@Testpublic void testRead(){String filename = TestFileUtil.getPath() + "3万.xlsx";ExcelReader reader = EasyExcel.read(filename, Employee.class,new EmployeeListener(new EmployeeDao())).build();ReadSheet sheet = EasyExcel.readSheet().build();reader.read(sheet);}
@Testpublic void testRead3(){String filename = TestFileUtil.getPath() + "批量写数据1669108667435.xlsx";EasyExcel.read(filename, Employee.class, new EmployeeListener(new EmployeeDao())).sheet().doRead();}
}
五、EasyExcel综合应用
-
环境搭建
-
实现文件导入功能(采用异步上传并使用遮罩层)
-
实现文件导出功能(采用同步下载并解决文件名中文乱码)
代码gitee地址:
EasyExcel: 阿里EasyExcel学习记录