EasyExcel

EasyExcel 的 github 地址: github.com/alibaba/eas… EasyExcel 的官方介绍:
【20200123】SpringBoot   EasyExcel - 图1
可以看到 EasyExcel 最大的特点就是使用内存少,当然现在它的功能还比较简单,能够面对的复杂场景比较少,不过基本的读写完全可以满足。

一. 依赖

首先是添加该项目的依赖,目前的版本是 1.1.2-beta4

  1. <dependency>
  2. <groupId>com.alibaba</groupId>
  3. <artifactId>easyexcel</artifactId>
  4. <version>1.1.2-beta4</version>
  5. </dependency>

二. 快速验证代码

  1. @Test
  2. public void simpleWrite() {
  3. try {
  4. OutputStream os = new FileOutputStream(new File("new.xlsx"));
  5. ExcelWriter writer = new ExcelWriter(os, ExcelTypeEnum.XLSX, true);
  6. // 2代表sheetNo,不可以重复,如果两个sheet的sheetNo相同则输出时只会有一个sheet
  7. Sheet sheet1 = new Sheet(1, 5, StudentDo.class);
  8. sheet1.setSheetName("第一个sheet");
  9. writer.finish();
  10. System.out.println("数据已写出");
  11. } catch (FileNotFoundException e) {
  12. e.printStackTrace();
  13. }
  14. }
  1. public class StudentDo extends BaseRowModel{
  2. @ExcelProperty(value="学号",index=0)
  3. private Integer id;
  4. @ExcelProperty(value= {"姓名","name","xxx","xxx"},index=1)
  5. private String name;
  6. @ExcelProperty(value="指导老师",index=2)
  7. private String teacher;
  8. public Integer getId() {
  9. return id;
  10. }
  11. public void setId(Integer id) {
  12. this.id = id;
  13. }
  14. public String getName() {
  15. return name;
  16. }
  17. public void setName(String name) {
  18. this.name = name;
  19. }
  20. public String getTeacher() {
  21. return teacher;
  22. }
  23. public void setTeacher(String teacher) {
  24. this.teacher = teacher;
  25. }
  26. @Override
  27. public String toString() {
  28. return "Student [id=" + id + ", name=" + name + ", teacher=" + teacher + "]";
  29. }
  30. }
  • 从ODPS读出数据之后,导出到Excel — 略。

三. 需要的类

【20200123】SpringBoot   EasyExcel - 图2

1. ExcelUtil

工具类,可以直接调用该工具类的方法完成 Excel 的读或者写

2. ExcelListener

监听类,可以根据需要与自己的情况,自定义处理获取到的数据,我这里只是简单地把数据添加到一个 List 里面。

  1. public class ExcelListener extends AnalysisEventListener {
  2. //自定义用于暂时存储data。
  3. //可以通过实例获取该值
  4. private List<Object> datas = new ArrayList<>();
  5. /**
  6. * 通过 AnalysisContext 对象还可以获取当前 sheet,当前行等数据
  7. */
  8. @Override
  9. public void invoke(Object object, AnalysisContext context) {
  10. //数据存储到list,供批量处理,或后续自己业务逻辑处理。
  11. datas.add(object);
  12. //根据自己业务做处理
  13. doSomething(object);
  14. }
  15. private void doSomething(Object object) {
  16. }
  17. @Override
  18. public void doAfterAllAnalysed(AnalysisContext context) {
  19. /*
  20. datas.clear();
  21. 解析结束销毁不用的资源
  22. */
  23. }
  24. public List<Object> getDatas() {
  25. return datas;
  26. }
  27. public void setDatas(List<Object> datas) {
  28. this.datas = datas;
  29. }
  30. }
  31. 复制代码

3. ExcelWriterFactroy

用于导出多个 sheet 的 Excel,通过多次调用 write 方法写入多个 sheet

4. ExcelException

捕获相关 Exception

四. 读取 Excel

读取 Excel 时只需要调用 ExcelUtil.readExcel() 方法

  1. @RequestMapping(value = "readExcel", method = RequestMethod.POST)
  2. public Object readExcel(MultipartFile excel) {
  3. return ExcelUtil.readExcel(excel, new ImportInfo());
  4. }
  5. 复制代码

其中 excel 是 MultipartFile 类型的文件对象,而 new ImportInfo() 是该 Excel 所映射的实体对象,需要继承 BaseRowModel 类,如:

  1. public class ImportInfo extends BaseRowModel {
  2. @ExcelProperty(index = 0)
  3. private String name;
  4. @ExcelProperty(index = 1)
  5. private String age;
  6. @ExcelProperty(index = 2)
  7. private String email;
  8. /*
  9. 作为 excel 的模型映射,需要 setter 方法
  10. */
  11. public String getName() {
  12. return name;
  13. }
  14. public void setName(String name) {
  15. this.name = name;
  16. }
  17. public String getAge() {
  18. return age;
  19. }
  20. public void setAge(String age) {
  21. this.age = age;
  22. }
  23. public String getEmail() {
  24. return email;
  25. }
  26. public void setEmail(String email) {
  27. this.email = email;
  28. }
  29. }
  30. 复制代码

作为映射实体类,通过 @ExcelProperty 注解与 index 变量可以标注成员变量所映射的列,同时不可缺少 setter 方法

五. 导出 Excel

1. 导出的 Excel 只拥有一个 sheet

只需要调用 ExcelUtil.writeExcelWithSheets() 方法:

  1. @RequestMapping(value = "writeExcel", method = RequestMethod.GET)
  2. public void writeExcel(HttpServletResponse response) throws IOException {
  3. List<ExportInfo> list = getList();
  4. String fileName = "一个 Excel 文件";
  5. String sheetName = "第一个 sheet";
  6. ExcelUtil.writeExcel(response, list, fileName, sheetName, new ExportInfo());
  7. }
  8. 复制代码

fileName,sheetName 分别是导出文件的文件名和 sheet 名,new ExportInfo() 为导出数据的映射实体对象,list 为导出数据。
对于映射实体类,可以根据需要通过 @ExcelProperty 注解自定义表头,当然同样需要继承 BaseRowModel 类,如:

  1. public class ExportInfo extends BaseRowModel {
  2. @ExcelProperty(value = "姓名" ,index = 0)
  3. private String name;
  4. @ExcelProperty(value = "年龄",index = 1)
  5. private String age;
  6. @ExcelProperty(value = "邮箱",index = 2)
  7. private String email;
  8. @ExcelProperty(value = "地址",index = 3)
  9. private String address;
  10. }
  11. 复制代码

value 为列名,index 为列的序号
如果需要复杂一点,可以实现如下图的效果:
【20200123】SpringBoot   EasyExcel - 图3
对应的实体类写法如下:

  1. public class MultiLineHeadExcelModel extends BaseRowModel {
  2. @ExcelProperty(value = {"表头1","表头1","表头31"},index = 0)
  3. private String p1;
  4. @ExcelProperty(value = {"表头1","表头1","表头32"},index = 1)
  5. private String p2;
  6. @ExcelProperty(value = {"表头3","表头3","表头3"},index = 2)
  7. private int p3;
  8. @ExcelProperty(value = {"表头4","表头4","表头4"},index = 3)
  9. private long p4;
  10. @ExcelProperty(value = {"表头5","表头51","表头52"},index = 4)
  11. private String p5;
  12. @ExcelProperty(value = {"表头6","表头61","表头611"},index = 5)
  13. private String p6;
  14. @ExcelProperty(value = {"表头6","表头61","表头612"},index = 6)
  15. private String p7;
  16. @ExcelProperty(value = {"表头6","表头62","表头621"},index = 7)
  17. private String p8;
  18. @ExcelProperty(value = {"表头6","表头62","表头622"},index = 8)
  19. private String p9;
  20. }
  21. 复制代码

2. 导出的 Excel 拥有多个 sheet

调用 ExcelUtil.writeExcelWithSheets() 处理第一个 sheet,之后调用 write() 方法依次处理之后的 sheet,最后使用 finish() 方法结束

  1. public void writeExcelWithSheets(HttpServletResponse response) throws IOException {
  2. List<ExportInfo> list = getList();
  3. String fileName = "一个 Excel 文件";
  4. String sheetName1 = "第一个 sheet";
  5. String sheetName2 = "第二个 sheet";
  6. String sheetName3 = "第三个 sheet";
  7. ExcelUtil.writeExcelWithSheets(response, list, fileName, sheetName1, new ExportInfo())
  8. .write(list, sheetName2, new ExportInfo())
  9. .write(list, sheetName3, new ExportInfo())
  10. .finish();
  11. }
  12. 复制代码

write 方法的参数为当前 sheet 的 list 数据,当前 sheet 名以及对应的映射类

参考资料