EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。
EasyExcel解决了什么
我们以使用最多的 Apache poi
来做为对比
SpringBoot
引入jar包
1 2 3 4 5 6
| <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.2.2</version> </dependency>
|
- 我使用的最新2.2.2版本,对比csdn等博客中记录的1.0之后的版本来说,这个版本已经进行了很多次的迭代,修复了许多bug,而2.2.1是最近的一个正式版。
能干什么
三大功能(读、写、填充)
读(Read)
图中的converter属性,后面再介绍
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| @Component @AllArgsConstructor @NoArgsConstructor @Builder public @Data class Student {
@ExcelProperty(value = "姓名") @NonNull private String name;
@ExcelProperty(value = "年龄") private Integer age;
@ExcelProperty(value = "性别") private String gender;
@ExcelProperty(value = "身高") private String height;
@ExcelProperty(value = "体重") private String weight;
@ExcelProperty(value = "专业",converter = CustomStringStringConverter.class) private String major;
@DateTimeFormat("yyyy-MM-dd HH:mm:ss") @ExcelProperty(value = "日期") private String update;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
|
public class ListenerExcel extends AnalysisEventListener<Student> { private static final Logger LOGGER = LoggerFactory.getLogger(ListenerExcel.class);
private static final int BATCH_COUNT = 2;
List<Student> list = new ArrayList<>();
private StudentDao studentDao;
public ListenerExcel(StudentDao studentDao) { this.studentDao = studentDao; }
@Override public void invoke(Student data, AnalysisContext context) { Integer rowNum = context.getCurrentRowNum(); if (rowNum == 0) { return; } LOGGER.info("解析到一条数据:{},位于第{}行", JSON.toJSONString(data), rowNum);
list.add(data); if (list.size() >= BATCH_COUNT) { saveData(); list.clear(); } }
@Override public void doAfterAllAnalysed(AnalysisContext context) { saveData(); LOGGER.info("所有数据解析完成!"); }
private void saveData() { LOGGER.info("{}条数据,开始存储数据库!", list.size()); studentDao.saveAll(list); LOGGER.info("存储数据库成功!"); } }
|
重点
针对我们每个要解析的Excel文件都应实现一个监听器,实际就是简化版的解析器,其中我们只需要实现invoke()
和doAfterAllAnalysed()
两个方法,invoke
是Excel文件中每解析一行都需要执行的操作,如果用在我们实际的业务中,一般会放入集合中等待入表或做算法操作,doAfterAllAnalysed
将在整个sheet解析完成后执行。
注意:如果是Spring的项目中使用,Excel的监听器不能被Spring所管理, 要每次读取excel都要new,里面用到spring的话可以构造方法传进去 (比如我上面的StudentDao,持久层)
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @SpringBootTest class LombookApplicationTests {
@Test void contextLoads() throws FileNotFoundException {
StudentDao studentdao = new StudentDaoImpl();
ExcelReaderBuilder read = EasyExcel.read( new FileInputStream("E:\\studentTest.xlsx"), Student.class, new ListenerExcel(studentdao)); read.doReadAll(); } }
|
1、 @ExcelProperty
注解是用来指定每个字段的列名称,以及Excel中的下标位置
这个地方我们只需要统一使用value或者index来指定excel中所对用的列即可,官方文档中不推荐同时使用value和index
2、@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
注解可以将时间格式化,但是需要时间类型为String
3、@ExcelIgnore
注解可以忽略掉当前属性,也就是excel中当前列
4、 @ExcelProperty
中的converter属性表示类型转换器(Excel转对象的数据处理,和对象集合转Excel的数据处理),根据Converter接口找到一些已经提供的的转换器
当然我们可以重写这个接口实现,使用 converter 绑定到属性上
例如:
重写convertToJavaData
和convertToExcelData
方法
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class CustomStringStringConverter implements Converter<String> { @Override public Class supportJavaTypeKey() { return String.class; }
@Override public CellDataTypeEnum supportExcelTypeKey() { return CellDataTypeEnum.STRING; }
@Override public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception { return "【学科专业】" + cellData.getStringValue(); }
@Override public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception { return new CellData("【学科专业】" + value); } }
|
在解析Excel文件的时候自动对对应的属性值进行转换
同样,在生成Excel时也可以通过 convertToExcelData
方法自动转换数据
写(write)
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
public class DataTemplateImpl implements DataTemplate { @Override public List<Student> create() {
List<Student> students = new ArrayList<>();
Student build = Student.builder() .name("张三") .age(22) .gender("man") .height("170") .weight("120") .major("计算机科学与技术") .update("2020-04-27 11:17:50") .build();
students.add(build); return students; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @SpringBootTest public class WriteTest {
@Test void contextLoads() throws FileNotFoundException {
String fileName = "E:\\" + "simpleWrite" + System.currentTimeMillis() + ".xlsx"; DataTemplate dataTemplate = new DataTemplateImpl(); EasyExcel.write(fileName, Student.class) .sheet("模板") .doWrite(dataTemplate.create()); } }
|
1、doWrite中传入数据
2、excelType
可指定类型,使用ExcelTypeEnum
的枚举类
1、使用excludeColumnFiledNames
或者excludeColumnIndexes
会根据列名或者列编码来屏蔽该列
2、使用注解@ExcelIgnore
同样可以忽略列
体重 属性使用 @ExcelIgnore
忽略
年龄 属性使用方法 excludeColumnFiledNames
忽略
web中的读和写(Swagger)
下载模板