EasyExcel简单入门

1.导入依赖

        
            com.alibaba
            easyexcel
            3.0.5
        

2.读excel

2.1excel表

姓名

年龄

创建时间

张三

20

2021-05-05 07:05:55

李四

15

2019-10-05 10:17:42

王五

22

2022-11-15 16:20:23

2.2使用一个对象接收Excel里的数据

@Getter
@Setter
@EqualsAndHashCode
public class ExcelData {
    /**
     * 强制读取第0个 这里不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配
     */
    @ExcelProperty(index = 0)
    private String name;
    /**
     * 用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据
     */
    @ExcelProperty("年龄")
    private Integer age;
    @ExcelProperty("创建时间")
    private Date date;
}

2.3创建一个监听器来实现读取数据

// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
@Slf4j
public class DemoDataListener implements ReadListener {
​
    /**
     * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 100;
    /**
     * 缓存的数据
     */
    private List cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    /**
     * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
     */
    private DemoDAO demoDAO;
​
    public DemoDataListener() {
        // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
        demoDAO = new DemoDAO();
    }
​
    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     *
     * @param demoDAO
     */
    public DemoDataListener(DemoDAO demoDAO) {
        this.demoDAO = demoDAO;
    }
​
    /**
     * 这个每一条数据解析都会来调用
     *
     * @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());
        demoDAO.save(cache
        
        
        dDataList);
        log.info("存储数据库成功!");
    }
}
package com.itheima.demo;
​
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.builder.ExcelReaderSheetBuilder;
import com.itheima.domain.Student;
import com.itheima.listener.StudentReadListener;
​
import java.io.FileNotFoundException;
​
/**
 * @Author Vsunks.v
 * @Date 2020/3/11 23:28
 * @Description:
 */
public class StudentReadDemo {
    public static void main(String[] args) throws FileNotFoundException {
        // 读取文件,读取完之后会自动关闭
        /*
            pathName        文件路径;"d:\\信息.xls"
            head            每行数据对应的实体;Student.class
            readListener    读监听器,每读一样就会调用一次该监听器的invoke方法
        
            sheet方法参数: 工作表的顺序号(从0开始)或者工作表的名字,不传默认为0
        */
        // 封装工作簿对象
        ExcelReaderBuilder workBook = EasyExcel.read
                ("d:\\信息.xls", Student.class, new DemoDataListener());
​
        // 封装工作表
        ExcelReaderSheetBuilder sheet1 = workBook.sheet();
        // 读取
        sheet1.doRead();
    }
}

2.3写excel

   /**
     * 最简单的写
     * 

* 1. 创建excel对应的实体对象 参照{@link ExcelData} *

* 2. 直接写即可 */ @Test public void simpleWrite() { // 注意 simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大参照 重复多次写入 // 写法1 JDK8+ // since: 3.0.0-beta1 String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 // 如果这里想 03 则 传入excelType参数即可 EasyExcel.write(fileName, ExcelData.class) .sheet("模板") .doWrite(() -> { // 分页查询数据 return data(); }); ​ // 写法2 fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 // 如果这里想使用03 则 传入excelType参数即可 EasyExcel.write(fileName, ExcelData.class).sheet("模板").doWrite(data()); ​ // 写法3 fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写 ExcelWriter excelWriter = null; try { excelWriter = EasyExcel.write(fileName, ExcelData.class).build(); WriteSheet writeSheet = EasyExcel.writerSheet("模板").build(); excelWriter.write(data(), writeSheet); } finally { // 千万别忘记finish 会帮忙关闭流 if (excelWriter != null) { excelWriter.finish(); } } }

3.1excel文件上传

@Controller
​
public class WebUploadAndDownload {
​
/**
​
\* ⽂件上传
​
\* 1. 编写excel中每⼀⾏对应的实体类
​
\* 2. 由于默认异步读取excel,所以需要逐⾏读取的回调监听器
​
\* 3. 开始读取Excel
​
*/
​
@PostMapping("upload")
​
@ResponseBody
​
public String upload(MultipartFile file)throws IOException {
​//获取文件流进行上传
ExcelReaderBuilder workBook = EasyExcel.read(file.getInputStream(), Student.class, studentReadListener);
 workBook.sheet().doRead();
​
return"success";
​
}

3.2excel文件下载

编写实体类

@Data
​
@NoArgsConstructor
​
@AllArgsConstructor
​
public class Student {
​
/**
* id
*/
@ExcelIgnore
​
private String id;
​
/**
* 学⽣姓名
*/
​
//@ExcelProperty({"学员信息表", "学⽣姓名"})
​
@ExcelProperty("学⽣姓名")
​
private String name;
​
/**
* 学⽣性别
*/
​
//@ExcelProperty({"学员信息表", "学⽣性别"})
​
@ExcelProperty("学⽣性别")
​
private String gender;
​
/**
* 学⽣出⽣⽇期
*/
​
//@ExcelProperty({"学员信息表", "学⽣出⽣⽇期"}) @ExcelProperty("学⽣出⽣⽇期")
​
private Date birthday;
​
}
​
// 循环⽣成10个学⽣对象
​
private static List initData(){
​
ArrayList students =new ArrayList<>(); for(int i =0; i <10; i++){
​
Student data =new Student();
​
data.setName("学号0"+ i);
​
data.setBirthday(new Date());
​
data.setGender("男");
​
students.add(data);
​
}
​
return students;
​
}

下载编码

public class WebUploadAndDownload {
​
/**
* ⽂件下载
* 1. 编写实体类并创建对象以便写⼊表格
* 2. 设置响应参数:⽂件的ContentType和⽂件名,同时设置编码避免乱码
* 3. 直接写,内部会调⽤finish⽅法⾃动关闭OutputStream
​
*/
​
@GetMapping("download")
​
public void download(HttpServletResponse response)throws IOException {
​
response.setContentType("application/vnd.ms-excel");
​
response.setCharacterEncoding("utf-8");
​
// 防⽌中⽂乱码
​
String fileName = URLEncoder.encode("测试","UTF-8");
​
response.setHeader("Content-Disposition","attachment; filename*=UTF-8''"+ fileName +".xlsx");
​
ExcelWriterBuilder workBook = EasyExcel.write(response.getOutputStream(), Student.class);
​
ExcelWriterSheetBuilder sheet = workBook.sheet("模板");
​
sheet.doWrite(initData());
​
}
​
}

4常用参数API

关于常见类解析

  • EasyExcel 入口类,用于构建开始各种操作
  • ExcelReaderBuilder ExcelWriterBuilder 构建出一个 ReadWorkbook WriteWorkbook,可以理解成一个excel对象,一个excel只要构建一个
  • ExcelReaderSheetBuilder ExcelWriterSheetBuilder 构建出一个 ReadSheet WriteSheet对象,可以理解成excel里面的一页,每一页都要构建一个
  • ReadListener 在每一行读取完毕后都会调用ReadListener来处理数据
  • WriteHandler 在每一个操作包括创建单元格、创建表格等都会调用WriteHandler来处理数据
  • 所有配置都是继承的,Workbook的配置会被Sheet继承,所以在用EasyExcel设置参数的时候,在EasyExcel...sheet()方法之前作用域是整个sheet,之后针对单个sheet

注解

  • ExcelProperty

指定当前字段对应excel中的那一列。可以根据名字或者Index去匹配。当然也可以不写,默认第一个字段就是index=0,以此类推。千万注意,要么全部不写,要么全部用index,要么全部用名字去匹配。千万别三个混着用,除非你非常了解源代码中三个混着用怎么去排序的。

  • ExcelIgnore

默认所有字段都会和excel去匹配,加了这个注解会忽略该字段

  • DateTimeFormat

日期转换,用String去接收excel日期格式的数据会调用这个注解。里面的value参照java.text.SimpleDateFormat

  • NumberFormat

数字转换,用String去接收excel数字格式的数据会调用这个注解。里面的value参照java.text.DecimalFormat

  • ExcelIgnoreUnannotated

默认不加ExcelProperty 的注解的都会参与读写,加了不会参与

参数

通用参数

ReadWorkbook,ReadSheet 都会有的参数,如果为空,默认使用上级。

  • converter

转换器,默认加载了很多转换器。也可以自定义。

  • readListener

监听器,在读取数据的过程中会不断的调用监听器。

  • headRowNumber

需要读的表格有几行头数据。默认有一行头,也就是认为第二行开始起为数据。

  • head

 与clazz二选一。读取文件头对应的列表,会根据列表匹配数据,建议使用class。

  • clazz

与head二选一。读取文件的头对应的class,也可以使用注解。如果两个都不指定,则会读取全部数据。

  • autoTrim

字符串、表头等数据自动trim

  • password

读的时候是否需要使用密码

6.2.2.2ReadWorkbook(理解成excel对象)参数

  • excelType

当前excel的类型 默认会自动判断

  • inputStream

与file二选一。读取文件的流,如果接收到的是流就只用,不用流建议使用file参数。因为使用了inputStream easyexcel会帮忙创建临时文件,最终还是file

  • file

与inputStream二选一。读取文件的文件。

  • autoCloseStream

自动关闭流。

  • readCache

默认小于5M用 内存,超过5M会使用 EhCache,这里不建议使用这个参数。

  • useDefaultListener

@since 2.1.4 默认会加入ModelBuildEventListener 来帮忙转换成传入class的对象,设置成false后将不会协助转换对象,自定义的监听器会接收到Map对象,如果还想继续接听到class对象,请调用readListener方法,加入自定义的beforeListener、 ModelBuildEventListener、 自定义的afterListener即可。

ReadSheet(就是excel的一个Sheet)参数

  • sheetNo

需要读取Sheet的编码,建议使用这个来指定读取哪个Sheet

  • sheetName

根据名字去匹配Sheet,excel 2003不支持根据名字去匹配

注解

  • ExcelProperty

index 指定写到第几列,默认根据成员变量排序。value指定写入的名称,默认成员变量的名字,多个value可以参照快速开始中的复杂头

  • ExcelIgnore

默认所有字段都会写入excel,这个注解会忽略这个字段

  • DateTimeFormat

日期转换,将Date写到excel会调用这个注解。里面的value参照java.text.SimpleDateFormat

  • NumberFormat

数字转换,用Number写excel会调用这个注解。里面的value参照java.text.DecimalFormat

  • ExcelIgnoreUnannotated

默认不加ExcelProperty 的注解的都会参与读写,加了不会参与

参数

通用参数

WriteWorkbook,WriteSheet ,WriteTable都会有的参数,如果为空,默认使用上级。

  • converter

转换器,默认加载了很多转换器。也可以自定义。

  • writeHandler

写的处理器。可以实现WorkbookWriteHandler,SheetWriteHandler,RowWriteHandler,CellWriteHandler,在写入excel的不同阶段会调用

  • relativeHeadRowIndex

距离多少行后开始。也就是开头空几行

  • needHead

是否导出头

  • head

 与clazz二选一。写入文件的头列表,建议使用class。

  • clazz

与head二选一。写入文件的头对应的class,也可以使用注解。

  • autoTrim

字符串、表头等数据自动trim

WriteWorkbook(理解成excel对象)参数

  • excelType

当前excel的类型 默认xlsx

  • outputStream

与file二选一。写入文件的流

  • file

与outputStream二选一。写入的文件

  • templateInputStream

模板的文件流

  • templateFile

模板文件

  • autoCloseStream

自动关闭流。

  • password

写的时候是否需要使用密码

  • useDefaultStyle

写的时候是否是使用默认头

6.3.2.3WriteSheet(就是excel的一个Sheet)参数

  • sheetNo

需要写入的编码。默认0

  • sheetName

需要些的Sheet名称,默认同sheetNo

WriteTable(就把excel的一个Sheet,一块区域看一个table)参数

  • tableNo

需要写入的编码。默认0

你可能感兴趣的:(java,数据库,mysql)