EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。
他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。
文档
依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.76</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> <scope>provided</scope> </dependency>
实体类,和Excel文件对应
package com.example.demo; import java.util.Date; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; /** * 基础数据类.这里的排序和excel里面的排序一致 * * @author Jiaju Zhuang **/ @Getter @Setter @EqualsAndHashCode public class DemoData { private String name; private Integer age; private Date birthday; }
package com.example.demo; import java.util.List; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.read.listener.ReadListener; import com.alibaba.excel.util.ListUtils; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; /** * 模板的读取类 * * @author Jiaju Zhuang */ // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去 @Slf4j public class DemoDataListener implements ReadListener<DemoData> { /** * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收 */ private static final int BATCH_COUNT = 100; /** * 缓存的数据 */ private List<DemoData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); /** * 这个每一条数据解析都会来调用 * * @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()} * @param context */ @Override public void invoke(DemoData data, AnalysisContext context) { log.info("解析到一条数据:{}", JSON.toJSONString(data)); cachedDataList.add(data); // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM if (cachedDataList.size() >= BATCH_COUNT) { saveData(); // 存储完成清理 list cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); } } /** * 所有数据解析完成了 都会来调用 * * @param context */ @Override public void doAfterAllAnalysed(AnalysisContext context) { // 这里也要保存数据,确保最后遗留的数据也存储到数据库 saveData(); log.info("所有数据解析完成!"); } /** * 加上存储数据库 */ private void saveData() { log.info("{}条数据,开始存储数据库!", cachedDataList.size()); log.info("存储数据库成功!"); } }
读取和写入
package com.example.demo; import com.alibaba.excel.EasyExcel; import org.junit.jupiter.api.Test; import java.io.File; import java.util.ArrayList; import java.util.Date; import java.util.List; public class ExcelTest { /** * 最简单的读 * <p>1. 创建excel对应的实体对象 参照{@link DemoData} * <p>2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoDataListener} * <p>3. 直接读即可 */ @Test public void simpleRead() { String fileName = "demo" + File.separator + "demo.xlsx"; // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭 EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead(); } /** * 最简单的写 * <p>1. 创建excel对应的实体对象 参照{@link DemoData} * <p>2. 直接写即可 */ @Test public void simpleWrite() { String fileName = "demo" + File.separator + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去读,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 // 如果这里想使用03 则 传入excelType参数即可 EasyExcel.write(fileName, DemoData.class) .sheet("模板") .doWrite(this.data()); } private List<DemoData> data() { List<DemoData> list = new ArrayList<>(); for (int i = 0; i < 10; i++) { DemoData data = new DemoData(); data.setName("姓名" + i); data.setBirthday(new Date()); data.setAge(50 + i); list.add(data); } return list; } }
输出表格
参考