• 【在线教育】EasyExcel入门


    文章目录

    1. EasyExcel 入门

    1.1 EasyExcel概述

    1.2 EasyExcel 特点

    1.3 环境搭建

    1.3.1 测试父项目

    1.3.2 测试excel项目

    1.4 基本操作

    1.4.1 测试JavaBean

    1.4.2 测试文件路径

    1.4.3 写操作

    1.4.3 读操作

    1.5 复杂操作

    1.5.1 复合表头

    1.5.2 写操作:多表

    1.5.3 读操作:多表

    1.6.4 写操作:多对象

    1.6 扩展:excel备份数据库

    1. EasyExcel 入门

    1.1 EasyExcel概述

    EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel工具。

    官网:EasyExcel(文档已经迁移) · 语雀

    github地址:GitHub - alibaba/easyexcel: 快速、简洁、解决大文件内存溢出的java处理Excel工具

    1.2 EasyExcel 特点

    • Java解析、生成Excel比较有名的框架有Apache poi、jxl,但他们都存在一个严重的问题就是非常的耗内存。

    • EasyExcel 重写了poi,使一个3M的excel只需要几M内存,并且再大的excel不会出现内存溢出。

      • 64M内存1分钟内读取75M(46W行25列)的Excel。

    1.3 环境搭建

    1.3.1 测试父项目

    • 项目名:zx-test-parent

    • 修改pom文件

          
              
              
                  org.springframework.boot
                  spring-boot-starter-test
              
          

    1.3.2 测试excel项目

    • 项目名:zx-test-excel

    • 修改pom,添加依赖

          
              
                  com.alibaba
                  easyexcel
                  3.1.1
              
              
                  org.projectlombok
                  lombok
              
          

    1.4 基本操作

    1.4.1 测试JavaBean

    package com.czxy.zx.demo01;
    ​
    import com.alibaba.excel.annotation.ExcelProperty;
    import lombok.Data;
    ​
    import java.util.Date;
    ​
    /**
     * Created by liangtong.
     */
    @Data
    public class Student {
        @ExcelProperty("编号")
        private String id;
    ​
        @ExcelProperty("姓名")
        private String name;
    ​
        @ExcelProperty("年龄")
        private Integer age;
    ​
        @ExcelProperty("电话")
        private String telephone;
    ​
        @ExcelProperty("邮箱")
        private String email;
    ​
        @ExcelProperty("生日")
        private Date brithday;
    }
    ​

    1.4.2 测试文件路径

    package com.czxy.zx.demo01;
    ​
    import org.junit.jupiter.api.Test;
    ​
    /**
     * @author 桐叔
     * @email liangtong@itcast.cn
     */
    public class TestExcel {
        /**
         * 获得根路径
         * @return
         */
        public String getPath() {
            return this.getClass().getResource("/").getPath();
        }
    ​
        @Test
        public void testPath() {
            // 测试文件路径
            String path = getPath() + "student_demo.xls";
            System.out.println(path);
        }
    ​
    ​
    }

    1.4.3 写操作

    • excel 属于 office组件一个软件

    • 存在若干版本,大体上划分2种情况,2007前的,2007年后的

      • 2003版:扩展名 xls,内容比较少,最大单元格 IV65536 ,256列(IV)

      • 2007版:扩展名 xlsx,内容较多,最大单元格 XFD1048576,16384列(XFD)

       /**
         * 准备数据
         * @return
         */
        private List getData(){
            List list = new ArrayList();
            for(int i = 0 ; i < 10 ; i ++){
                Student student = new Student();
                student.setId("stu" + i);
                student.setName("wang" + i);
                student.setAge( 18 + i );
                student.setTelephone("1361234" + i);
                student.setEmail("wang" + i + "@czxy.com");
                student.setBrithday(new Date());
                list.add(student);
            }
            return list;
        }
    ​
        @Test
        public void testWrite(){
            String file = getPath() + "student_demo.xls";
            //EasyExcel.write(位置,对象).sheet("表名").doWrite(数据);
            EasyExcel.write(file,Student.class).sheet("班级").doWrite(getData());
        }
    ​

    1.4.3 读操作

    • 处理类:

      • 处理类需要实现 AnalysisEventListener 接口

      package com.czxy.zx.demo01;
      ​
      import com.alibaba.excel.context.AnalysisContext;
      import com.alibaba.excel.event.AnalysisEventListener;
      import com.czxy.zx.domain.Student;
      ​
      /**
       * @author 桐叔
       * @email liangtong@itcast.cn
       */
      public class StudentListener extends AnalysisEventListener {
          @Override
          public void invoke(Student student, AnalysisContext analysisContext) {
              System.out.println(student);
          }
      ​
          @Override
          public void doAfterAllAnalysed(AnalysisContext analysisContext) {
              System.out.println("解析完成");
          }
      }
      ​
    • 测试

          @Test
          public void testRead(){
              String file = getPath() + "student_demo.xls";
              //EasyExcel.read(文件, 封装对象, 处理类).sheet("表").doRead();
              EasyExcel.read(file, Student.class, new StudentListener()).sheet("班级").doRead();
          }

    1.5 复杂操作

    1.5.1 复合表头

    package com.czxy.zx.demo02;
    ​
            import com.alibaba.excel.annotation.ExcelProperty;
            import com.alibaba.excel.annotation.format.DateTimeFormat;
            import com.alibaba.excel.annotation.write.style.ColumnWidth;
            import com.alibaba.excel.annotation.write.style.ContentRowHeight;
            import com.alibaba.excel.annotation.write.style.HeadRowHeight;
            import lombok.Data;
    ​
            import java.util.Date;
    ​
    /**
     * @author 桐叔
     * @email liangtong@itcast.cn
     */
    @Data
    @ContentRowHeight(20)
    @HeadRowHeight(20)  //行高
    @ColumnWidth(25)    //列宽
    public class Student2 {
        @ExcelProperty("编号")
        private String id;
    ​
        @ExcelProperty({"基本信息","姓名"})   //复制表头
        private String name;
    ​
        @ExcelProperty({"基本信息","年龄"})
        private Integer age;
    ​
        @ExcelProperty("电话")
        private String telephone;
    ​
        @ExcelProperty("邮箱")
        private String email;
    ​
        @ExcelProperty("生日")
        @DateTimeFormat("yyyy年MM月dd日")
        private Date brithday;
    }

    1.5.2 写操作:多表

    package com.czxy.zx.demo02;
    ​
    import com.alibaba.excel.EasyExcel;
    import com.alibaba.excel.ExcelWriter;
    import com.alibaba.excel.write.metadata.WriteSheet;
    import com.czxy.zx.demo01.Student;
    import org.junit.Test;
    ​
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    ​
    /**
     * @author 桐叔
     * @email liangtong@itcast.cn
     */
    public class TestExcel2 {
        /**
         * 获得根路径
         * @return
         */
        public String getPath() {
            return this.getClass().getResource("/").getPath();
        }
    ​
        /**
         * 准备数据
         * @return
         */
        private List getData(Integer flag){
            List list = new ArrayList();
            for(int m = 0 ; m < 10 ; m ++){
                String i = "" + flag + m ;
                Student2 student = new Student2();
                student.setId("stu" + i);
                student.setName("wang" + i);
                student.setAge( 18 );
                student.setTelephone("1361234" + i);
                student.setEmail("wang" + i + "@czxy.com");
                student.setBrithday(new Date());
                list.add(student);
            }
            return list;
        }
    ​
        @Test
        public void testMoreSheetWrite(){
            String file = getPath() + "student_demo2.xls";
    ​
            ExcelWriter excelWriter = EasyExcel.write(file).build();
    ​
            for (int i = 0; i < 5; i++) {
                WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).head(Student2.class).build();
                // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
                List data = getData(i);
                excelWriter.write(data, writeSheet);
            }
    ​
            excelWriter.finish();
        }
    ​
    ​
    }
    ​

    1.5.3 读操作:多表

    • 具有缓存处理类

      package com.czxy.zx.demo02;
      ​
      import com.alibaba.excel.context.AnalysisContext;
      import com.alibaba.excel.event.AnalysisEventListener;
      ​
      import java.util.ArrayList;
      import java.util.List;
      ​
      /**
       * Created by liangtong.
       */
      public class Student2Listener extends AnalysisEventListener {
      ​
          // 批量操作数
          private static final int BATCH_COUNT = 10;
          // 用于缓存信息
          private List cache = new ArrayList();
      ​
          public void invoke(Student2 student, AnalysisContext analysisContext) {
              //保存学生信息
              cache.add(student);
              if(cache.size() >= BATCH_COUNT){
                  // 保存数据
                  saveData();
              }
          }
      ​
          public void doAfterAllAnalysed(AnalysisContext analysisContext) {
              //最后的不够 BATCH_COUNT 倍数
              saveData();
          }
      ​
          private void saveData() {
              // 集合不为空
              if(! cache.isEmpty()) {
                  // 处理缓存数据
                  System.out.println(cache);
                  // 清空缓存
                  cache.clear();
              }
          }
      }
      ​
    • 读操作

      @Test
          public void testMoreRead(){
              String file = getPath() + "student_demo2.xls";
              //EasyExcel.read(文件, 封装对象, 处理类).sheet("表").doRead();
      ​
              ExcelReader excelReader = EasyExcel.read(file, Student2.class, new Student2Listener()).build();
              // 确定需要解析的sheet
              for (int i = 0; i < 5; i++) {
                  ReadSheet readSheet = EasyExcel.readSheet("模板" + i).build();
                  excelReader.read(readSheet);
              }
      ​
              excelReader.finish();
          }

    1.6.4 写操作:多对象

    • Student

      @Data
      @NoArgsConstructor
      @AllArgsConstructor
      public class Student {
          @ExcelProperty("姓名")
          private String name;
          @ExcelProperty("年龄")
          private Integer age;
      }
      ​

    • Book

      @Data
      @NoArgsConstructor
      @AllArgsConstructor
      @HeadRowHeight(50)
      @HeadFontStyle(fontName = "黑体",italic =  BooleanEnum.TRUE, color = Font.COLOR_RED, underline = 2)
      public class Book {
          @ExcelProperty("编号")
          private String id;
      ​
          @ExcelProperty({"作者信息","姓名"})
          private String authorName;
      ​
          @ExcelProperty({"作者信息","年龄"})
          private Integer authorAge;
      ​
          @ExcelProperty({"书籍基本信息","标题"})
          private String title;
      ​
          @ContentFontStyle(fontName = "楷书",italic =  BooleanEnum.TRUE, color = Font.COLOR_RED, underline = -1)
          @ExcelProperty({"书籍基本信息","价格"})
          private Double price;
          @ExcelProperty({"书籍基本信息","出版日期"})
          @DateTimeFormat("yyyy年MM月dd日")
          private Date publishDate;
      }
    • 实现

      package com.czxy.zx.demo03;
      ​
      import com.alibaba.excel.EasyExcel;
      import com.alibaba.excel.ExcelWriter;
      import com.alibaba.excel.write.metadata.WriteSheet;
      import com.czxy.zx.demo01.Student;
      import com.czxy.zx.demo02.Book;
      import org.junit.Test;
      ​
      import java.util.*;
      ​
      /**
       * @author 桐叔
       * @email liangtong@itcast.cn
       */
      public class TestManyObject {
      ​
          // 获得当前项目的运行时的根目录
          public String getPath() {
              return this.getClass().getResource("/").getPath();
          }
      ​
          // 模拟数据
          public List getStudentData() {
              List list = new ArrayList<>();
              for (int i = 0; i < 20; i++) {
                  list.add(new Student("张三" + i, 18 + i));
              }
              return list;
          }
      ​
          public List getBookData() {
              List list = new ArrayList<>();
              for (int i = 0; i < 20; i++) {
                  list.add(new Book(i+"" , "张三" + i , 18 +i, "坏蛋是怎么"+i, 998d+i, new Date()));
              }
              return list;
          }
      ​
          // 遍历map即可
          private Map, List> getData() {
              Map, List> map = new HashMap<>();
              map.put(Student.class, getStudentData());
              map.put(Book.class, getBookData());
              return map;
          }
      ​
          @Test
          public void testManyObject() {
              String file = getPath() + "many_object.xlsx";
              //1 开始写
              ExcelWriter excelWriter = EasyExcel.write(file).build();
              //2 依次写每一个对象
              for(Map.Entry, List> entry : getData().entrySet()) {
                  Class clazz = entry.getKey();            //类型
                  List data = entry.getValue();            //数据
                  WriteSheet writeSheet = EasyExcel.writerSheet(clazz.getSimpleName()).head(clazz).build();
                  excelWriter.write(data, writeSheet);
              }
      ​
              //3 写完成
              excelWriter.finish();
          }
      }
      ​

    1.6 扩展:excel备份数据库

    • 步骤

      • 步骤1:添加坐标

      • 步骤2:编写封装类

      • 步骤3:编写核心类

    • 步骤1:添加坐标

          
              
                  com.alibaba
                  easyexcel
                  3.0.5
              
              
                  org.projectlombok
                  lombok
              
              
                  mysql
                  mysql-connector-java
              
              
                  commons-dbutils
                  commons-dbutils
                  1.7
              
          

    • 步骤2:编写封装类

      package com.czxy.zx.demo03;
      ​
      import com.alibaba.excel.annotation.ExcelProperty;
      import com.alibaba.excel.annotation.write.style.ColumnWidth;
      import com.alibaba.excel.annotation.write.style.ContentRowHeight;
      import com.alibaba.excel.annotation.write.style.HeadRowHeight;
      import lombok.Data;
      ​
      import java.util.Date;
      import java.util.List;
      ​
      /**
       * 课程
       *
       */
      @Data
      @ContentRowHeight(20)
      @HeadRowHeight(20)  //行高
      @ColumnWidth(25)    //列宽
      public class Chapter {
      ​
          @ExcelProperty("章节ID")
          private String id;
      ​
          @ExcelProperty("课程ID")
          private String courseId;
      ​
          @ExcelProperty("章节名称")
          private String title;
      ​
          @ExcelProperty("显示排序")
          private Integer sort;
      ​
          @ExcelProperty("创建时间")
          private Date gmtCreate;
      ​
          @ExcelProperty("更新时间")
          private Date gmtModified;
      ​
      }
      ​
      package com.czxy.zx.demo03;
      ​
      import com.alibaba.excel.annotation.ExcelProperty;
      import com.alibaba.excel.annotation.format.DateTimeFormat;
      import com.alibaba.excel.annotation.write.style.ColumnWidth;
      import com.alibaba.excel.annotation.write.style.ContentRowHeight;
      import com.alibaba.excel.annotation.write.style.HeadRowHeight;
      import lombok.Data;
      ​
      import java.util.Date;
      ​
      /**
       * 课程
       *
       */
      @Data
      @ContentRowHeight(20)
      @HeadRowHeight(20)  //行高
      @ColumnWidth(25)    //列宽
      public class Course {
      ​
          @ExcelProperty("课程ID")
          private String id;
      ​
          @ExcelProperty("课程讲师ID")
          private String teacherId;
      ​
          @ExcelProperty("课程专业ID二级分类ID")
          private String subjectId;
      ​
          @ExcelProperty("一级分类ID")
          private String subjectParentId;
      ​
          @ExcelProperty("课程标题")
          private String title;
      ​
          @ExcelProperty("课程销售价格,设置为0则可免费观看")
          private Double price;
      ​
          @ExcelProperty("总课时")
          private Integer lessonNum;
      ​
          @ExcelProperty("课程封面图片路径")
          private String cover;
      ​
          @ExcelProperty("销售数量")
          private Long buyCount;
      ​
          @ExcelProperty("浏览数量")
          private Long viewCount;
      ​
          @ExcelProperty("乐观锁")
          private Long version;
      ​
          @ExcelProperty("视频状态 Draft未发布  Normal已发布")
          private String status;
      ​
          @ExcelProperty("创建时间")
          @DateTimeFormat("yyyy年MM月dd日")
          private Date gmtCreate;
      ​
          @ExcelProperty("更新时间")
          @DateTimeFormat("yyyy年MM月dd日")
          private Date gmtModified;
      ​
      ​
      }
      ​

    • 步骤3:编写核心类

      package com.czxy.zx.demo03;
      ​
      import com.alibaba.excel.EasyExcel;
      import com.alibaba.excel.ExcelWriter;
      import com.alibaba.excel.write.metadata.WriteSheet;
      import com.czxy.zx.demo02.Student2;
      import org.apache.commons.dbutils.BasicRowProcessor;
      import org.apache.commons.dbutils.DbUtils;
      import org.apache.commons.dbutils.GenerousBeanProcessor;
      import org.apache.commons.dbutils.QueryRunner;
      import org.apache.commons.dbutils.handlers.BeanListHandler;
      import org.junit.Test;
      ​
      import java.sql.*;
      import java.util.*;
      ​
      /**
       * @author 桐叔
       * @email liangtong@itcast.cn
       */
      public class TestBackdb {
      ​
          public Class getClassByTableName(String tableName) {
              Map map = new HashMap<>();
              map.put("edu_chapter", Chapter.class);
              map.put("edu_course", Course.class);
              return map.get(tableName);
          }
      ​
          public String getPath() {
              return this.getClass().getResource("/").getPath();
          }
      ​
      ​
          public Connection getConnection() {
              try {
                  Class.forName("com.mysql.jdbc.Driver");
                  String url = "jdbc:mysql://127.0.0.1:3306/zx_edu_course?useUnicode=true&characterEncoding=utf8";
                  String username = "root";
                  String password = "1234";
      ​
                  Properties props =new Properties();
                  props.setProperty("user", username);
                  props.setProperty("password", password);
                  props.setProperty("remarks", "true");               //设置可以获取remarks信息
                  props.setProperty("useInformationSchema", "true");  //设置可以获取tables remarks信息
      ​
                  return DriverManager.getConnection(url, props);
              } catch (Exception e) {
                  throw new RuntimeException(e);
              }
          }
      ​
          @Test
          public void testDB() throws Exception {
              String file = getPath() + "db.xls";
              QueryRunner queryRunner = new QueryRunner();
              ExcelWriter excelWriter = EasyExcel.write(file).build();
              String dbName = "zx_edu_course";
              //获得连接
              Connection conn = getConnection();
              //语句执行者
              Statement st = conn.createStatement();
      ​
              //数据库的元数据
              DatabaseMetaData databaseMetaData = conn.getMetaData();
      ​
              //获得所有的数据库
              ResultSet catalogResultSet = databaseMetaData.getCatalogs();
      ​
              //遍历所有的数据库
              while(catalogResultSet.next()) {
                  //获得数据库的名称
                  String databaseName = catalogResultSet.getString(1);
                  if(dbName.equals(databaseName)) {
                      //使用数据库
                      st.execute("use " + databaseName);
                      ResultSet tableResultSet = databaseMetaData.getTables(databaseName, null, null, null);
                      //遍历所有的表名
                      while(tableResultSet.next()) {
                          //表名
                          String tableName = tableResultSet.getString(3);             //TABLE_NAME
                          String tableRemarks = tableResultSet.getString("REMARKS"); //获得表的备注
                          // 通过表名获得excel处理类
                          Class excelBeanClass = getClassByTableName(tableName);
                          if(excelBeanClass != null) {
                              //获得当前表的所有数据
                              String sql = "select * from " + tableName;
                              //
                              List data = (List) queryRunner.query(conn, sql, new BeanListHandler<>(excelBeanClass, new BasicRowProcessor(new GenerousBeanProcessor()) ));
                              // 创建sheet
                              WriteSheet writeSheet = EasyExcel.writerSheet(tableRemarks != null ? tableRemarks : tableName).head(excelBeanClass).build();
                              excelWriter.write(data, writeSheet);
                          }
                      }
                  }
              }
              //写入完成
              excelWriter.finish();
          }
      ​
      }
      ​

  • 相关阅读:
    前端工具——01-VS Code的使用
    求程序段中++x或者x++的频度,时间复杂度、执行次数
    学习之浅谈python如何做接口自动化
    jQuery小结四
    javaee之黑马乐优商城2
    Nitrux 3.0 正式发布并全面上市
    K8S群集调度
    c++ 模板 指针类型偏特化
    Veeam Backup Enterprise Manager身份验证绕过漏洞(CVE-2024-29849)
    JWFD开源工作流大模型设计器
  • 原文地址:https://blog.csdn.net/weixin_45481821/article/details/126673362