背景
说到导出Excel文档,我们一般会想到很多放方式,比如简单的EasyPoi,采用注解的方式,直接导出,使用template模板方式,然后将数据写入模板,将数据转换成Map或是List集合写入Excel。
EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。
github地址:https://github.com/alibaba/easyexcel
使用demo
导入依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.0.5</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>4.1.2</version> </dependency>
demo入口
public class TestExecel { public static void main(String[] args) { //文件绝对路径 String name = "/Users/test/src/mytest/test.xlsx"; //read方法可以传递文件名也可以传递File EasyExcel.read(name, UserTest.class, new CustomerExcelDataListener()) .sheet() .headRowNumber(1) .doRead(); } }
模版类
@Data public class UserTest { /** * 用户姓名 */ @ExcelProperty(value = "用户姓名", index = 0) private String name; /** * 用户手机号 */ @ExcelProperty("用户手机号") private String phone; /** * 用户年龄 */ @ExcelProperty("用户年龄") private Integer age; }
自定义监听处理类
public class CustomerExcelDataListener implements ReadListener<DetectSyncToCarEntity> { /** * 每隔200条存储数据库然后清理list ,方便内存回收 */ private final int BATCH_COUNT = 200; private final List<UserTest> cacheList = new ArrayList<>(); @SneakyThrows @Override public void onException(Exception exception, AnalysisContext context) { //异常时需要做的处理 //log.error("load file row data error! info:{}", exception); } /** * 这里会一行行的返回头 * * @param headMap * @param context */ @SneakyThrows @Override public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) { } /** * 这个每一条数据解析都会来调用 * * @param data * @param context */ @Override public void invoke(UserTest data, AnalysisContext context) { if (null != data){ //将数据暂存到缓存中,到达处理数量时进行处理 cacheList.add(data); if (detectSyncToCarEntityList.size() >= BATCH_COUNT){ doProcess(false); } } } @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { //收尾阶段,最后一批次没处理的数据进行处理 doProcess(true); } public CustomerExcelDataListener() { //可以将外边的service传入构造方法进行使用 } /** * * @param isFinal 是否为最后一批数据 */ // @Transactional(rollbackFor = Exception.class) public void doProcess(Boolean isFinal) { //一批次的数据进行逻辑处理 //业务处理 //处理完成之后清理cache cacheList.clear(); } }