详细解析POI 和 EasyExcel

在数据量需要被批量导入、导出的时候,就可以使用POI和easyExcel

常用场景:

1、将用户信息导出为excel表格(导出数据...)

2、将Excel表中的信息录入到网站数据库(习题上传...)大大减轻网站录入量!开发中经常会设计到excel的处理,如导出Excel,导入Excel到数据库中!

操作Excel目前比较流行的就是 Apache POI和阿里巴巴的easyExcel !

Apache POI

官网:https://poi.apache.org/

EasyExcel

easyExcel官网:GitHub - alibaba/easyexcel: 快速、简单避免OOM的java处理Excel工具

官方文档地址:https://www.yuque.com/easyexcel/doc/easyexcel

github地址:https://github.com/alibaba/easyexcel

EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。

EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。

内存问题:POl = 100w先加载到内存OOM。。再写入文件es= 1

POI-Excel操作:

1.导入依赖

java 复制代码
<!-- xls 03 -->
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi</artifactId>
  <version>3.9</version>
</dependency>
<!-- xlsx 07 -->
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi-ooxml</artifactId>
  <version>3.9</version>
</dependency>
<!-- 日期格式化工具 -->
<dependency>
  <groupId>joda-time</groupId>
  <artifactId>joda-time</artifactId>
  <version>2.10.10</version>
</dependency>
 
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <scope>test</scope>
</dependency>
  1. 对于03版依赖和07版依赖的区别:
    03版最多只能到65530行,而07版没有限制,.xls格式文件对应03版,.xlsx格式文件对应07版;

3.Excel中的对象

2.1 工作簿 2.2 工作表 2.3 行 2.4 单元格

这些对象,就是我们在Java中需要操作的对象,把这个好好理解下,有助于后面的学习。

4.写操作

4.1 工作簿(WorkBook)的继承和实现关系:

HSSFWorkbook:03版工作簿

XSSFWorkbook:07版工作簿

SXSSFWorkbook:07版工作簿增强版

4.2 基础操作:

java 复制代码
package com.ggz.poi;
 
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.joda.time.DateTime;
import org.junit.Test;
 
import java.io.FileOutputStream;
import java.io.IOException;
 
public class ExcelWriteTest {
    String path = "C:\\Users\\Administrator\\IdeaProjects\\code2\\pioeasyexcel\\poi";
    @Test
    public void testExcelWrite03Version() throws IOException {
 
        // 1.创建一个工作簿
        Workbook workbook = new HSSFWorkbook();
        // 2.创建工作表
        Sheet sheet1 = workbook.createSheet("表名1"); // 表名默认是sheet0
        // 3.创建第一行
        Row row1 = sheet1.createRow(0);
        // 4.创建单元格(1,1)
        Cell cell11 = row1.createCell(0);
        cell11.setCellValue("第一次使用poi");
        // (1,2)
        Cell cell12 = row1.createCell(1);
        cell12.setCellValue("好激动啊");
        // 创建第二行
        Row row2 = sheet1.createRow(1);
        //  (2,1)
        Cell cell21 = row2.createCell(0);
        cell21.setCellValue("现在时间是:");
        // (2,2)
        Cell cell22 = row2.createCell(1);
        cell22.setCellValue(new DateTime().toString("yyyy年MM月dd日 HH:mm:ss"));
 
        // 生成文件
        FileOutputStream fileOutputStream = new FileOutputStream(path + "\\poi03hss.xls");
        workbook.write(fileOutputStream);
        fileOutputStream.close();
        System.out.println("生成完毕");
    }
 
    @Test
    public void testExcelWrite07VersionXss() throws IOException {
 
        // 1.创建一个工作簿
        Workbook workbook = new XSSFWorkbook();
        // 2.创建工作表
        Sheet sheet1 = workbook.createSheet("表名2"); // 表名默认是sheet0
        // 3.创建第一行
        Row row1 = sheet1.createRow(0);
        // 4.创建单元格(1,1)
        Cell cell11 = row1.createCell(0);
        cell11.setCellValue("第一次使用poi");
        // (1,2)
        Cell cell12 = row1.createCell(1);
        cell12.setCellValue("好激动啊");
        // 创建第二行
        Row row2 = sheet1.createRow(1);
        //  (2,1)
        Cell cell21 = row2.createCell(0);
        cell21.setCellValue("现在时间是:");
        // (2,2)
        Cell cell22 = row2.createCell(1);
        cell22.setCellValue(new DateTime().toString("yyyy年MM月dd日 HH:mm:ss"));
 
        // 生成文件
        FileOutputStream fileOutputStream = new FileOutputStream(path + "\\poi07xss.xlsx");
        workbook.write(fileOutputStream);
        fileOutputStream.close();
        System.out.println("生成完毕");
    }
 
    @Test
    public void testExcelWrite07VersionSxss() throws IOException {
 
        // 1.创建一个工作簿
        Workbook workbook = new SXSSFWorkbook();
        // 2.创建工作表
        Sheet sheet1 = workbook.createSheet("表名2"); // 表名默认是sheet0
        // 3.创建第一行
        Row row1 = sheet1.createRow(0);
        // 4.创建单元格(1,1)
        Cell cell11 = row1.createCell(0);
        cell11.setCellValue("第一次使用poi");
        // (1,2)
        Cell cell12 = row1.createCell(1);
        cell12.setCellValue("好激动啊");
        // 创建第二行
        Row row2 = sheet1.createRow(1);
        //  (2,1)
        Cell cell21 = row2.createCell(0);
        cell21.setCellValue("现在时间是:");
        // (2,2)
        Cell cell22 = row2.createCell(1);
        cell22.setCellValue(new DateTime().toString("yyyy年MM月dd日 HH:mm:ss"));
 
        // 生成文件
        FileOutputStream fileOutputStream = new FileOutputStream(path + "\\poi07sxss.xlsx");
        workbook.write(fileOutputStream);
        fileOutputStream.close();
        System.out.println("生成完毕");
    }
 
 
}

4.3 BigData

4.3.1 HSSFWorkbook:03版工作簿 (大文件写)

缺点 ∶ 最多只能处理65536行,否则会抛出异常

优点 : 过程中写入缓存,不操作磁盘,最后一次性写入磁盘,速度快

java 复制代码
@Test
public void testBigDataWrite03VersionHss() throws IOException {
    long start = System.currentTimeMillis();
    // 1.创建一个工作簿
    Workbook workbook = new HSSFWorkbook();
    // 2.创建工作表
    Sheet sheet1 = workbook.createSheet("表名2"); // 表名默认是sheet0
    // 循环创建行
    for (int rowNum = 0; rowNum < 65536; rowNum++) {
        Row row = sheet1.createRow(rowNum);
        // 循环创建单元格
        for (int cellNum = 0; cellNum < 10; cellNum++) {
            Cell cell = row.createCell(cellNum);
            cell.setCellValue(new DateTime().toString("HH:mm:ss"));
        }
    }
    System.out.println("HSS创建完毕!");
 
    // 生成文件
    FileOutputStream fileOutputStream = new FileOutputStream(path + "\\BigDataPoi03.xls");
    workbook.write(fileOutputStream);
    fileOutputStream.close();
    System.out.println("SSH生成完毕");
 
    long end = System.currentTimeMillis();
    System.out.println((double) (end - start) / 1000);
}

运行结果:

4.3.2 XSSFWorkbook:07版工作簿

java 复制代码
@Test
public void testBigDataWrite07VersionXss() throws IOException {
    long start = System.currentTimeMillis();
    // 1.创建一个工作簿
    Workbook workbook = new XSSFWorkbook();
    // 2.创建工作表
    Sheet sheet1 = workbook.createSheet("表名2"); // 表名默认是sheet0
    // 循环创建行
    for (int rowNum = 0; rowNum < 65536; rowNum++) {
        Row row = sheet1.createRow(rowNum);
        // 循环创建单元格
        for (int cellNum = 0; cellNum < 10; cellNum++) {
            Cell cell = row.createCell(cellNum);
            cell.setCellValue(new DateTime().toString("HH:mm:ss"));
        }
    }
    System.out.println("XSS创建完毕!");
 
    // 生成文件
    FileOutputStream fileOutputStream = new FileOutputStream(path + "\\BigDataPoi07Xss.xls");
    workbook.write(fileOutputStream);
    fileOutputStream.close();
    System.out.println("XSS生成完毕");
 
    long end = System.currentTimeMillis();
    System.out.println((double) (end - start) / 1000);
}

运行结果:

4.3.2 SXSSFWorkbook:07版工作簿增强版

java 复制代码
@Test
public void testBigDataWrite07VersionSxss() throws IOException {
    long start = System.currentTimeMillis();
    // 1.创建一个工作簿
    Workbook workbook = new SXSSFWorkbook();
    // 2.创建工作表
    Sheet sheet1 = workbook.createSheet("表名2"); // 表名默认是sheet0
    // 循环创建行
    for (int rowNum = 0; rowNum < 65536; rowNum++) {
        Row row = sheet1.createRow(rowNum);
        // 循环创建单元格
        for (int cellNum = 0; cellNum < 10; cellNum++) {
            Cell cell = row.createCell(cellNum);
            cell.setCellValue(new DateTime().toString("HH:mm:ss"));
        }
    }
    System.out.println("SXSS创建完毕!");
 
    // 生成文件
    FileOutputStream fileOutputStream = new FileOutputStream(path + "\\BigDataPoi07SXss.xls");
    workbook.write(fileOutputStream);
    fileOutputStream.close();
 
    // 清除临时文件
    ((SXSSFWorkbook)workbook).dispose();
 
    System.out.println("SXSS生成完毕");
 
    long end = System.currentTimeMillis();
    System.out.println((double) (end - start) / 1000);
}

执行结果:

  1. POI-Excel读操作:

5.1基础操作:

java 复制代码
package com.ggz.poi;
 
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;
 
import java.io.FileInputStream;
import java.io.IOException;
 
public class ExcelReadTest {
    String path = "C:\\Users\\Administrator\\IdeaProjects\\code2\\pioeasyexcel\\poi";
    @Test
    public void testReadHss() throws IOException {
        // 获取文件流
        FileInputStream fileInputStream = new FileInputStream(path + "\\会员消费商品明细表.xls");
        // 创建一个工作簿, Excel里面的操作,这边都有
        HSSFWorkbook workbook = new HSSFWorkbook(fileInputStream);
        // 创建工作表
        HSSFSheet sheet = workbook.getSheetAt(0);
        // 获取一行
        HSSFRow row = sheet.getRow(0);
        // 获取一个单元格(1,1)
        HSSFCell cell = row.getCell(0);
 
        System.out.println(cell.getStringCellValue());
				fileInputStream.close();
    }
 
    @Test
    public void testReadXss() throws IOException {
        // 获取文件流
        FileInputStream fileInputStream = new FileInputStream(path + "\\BigDataPoi07SXss.xls");
        // 创建一个工作簿, Excel里面的操作,这边都有
        XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream);
        // 创建工作表
        XSSFSheet sheet = workbook.getSheetAt(0);
        // 获取一行
        XSSFRow row = sheet.getRow(0);
        // 获取一个单元格(1,1)
        XSSFCell cell = row.getCell(0);
 
        System.out.println(cell.getStringCellValue());
				fileInputStream.close();
    }
 
}

5.2 复杂数据类型读取:

主要是注意数据类型转换问题!看起来很复杂,其实就是双重循环和判断,不过这对我来说没什么。

java 复制代码
package com.ggz.poi;
 
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.joda.time.DateTime;
import org.junit.Test;
 
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Date;
 
public class EasyExcel {
    private final String PATH = "C:\\Users\\Administrator\\IdeaProjects\\code2\\pioeasyexcel\\poi";
    @Test
    public void testReadHSS() throws IOException {
        // 通过流获取工作簿、工作表等对象
        FileInputStream fileInputStream = new FileInputStream(PATH + "\\会员消费商品明细表.xls");
        Workbook workbook = new HSSFWorkbook(fileInputStream);
        Sheet sheet = workbook.getSheetAt(0);
 
        // 获取标题内容
        Row rowTitle = sheet.getRow(0);
        if(rowTitle != null){
            int cellTotal = rowTitle.getPhysicalNumberOfCells();
            for (int cellNum = 0; cellNum < cellTotal; cellNum++) {
                Cell cell = rowTitle.getCell(cellNum);
                if (cell != null){
                    int cellType = cell.getCellType();
                    String stringCellValue = cell.getStringCellValue();
                    System.out.print(stringCellValue + " | ");
                }
            }
            System.out.println();
        }
 
        // 获取内容
        int rowTotal = sheet.getPhysicalNumberOfRows();
        for (int rowNum = 1; rowNum < rowTotal; rowNum++) {
            Row row = sheet.getRow(rowNum);
            if(row != null){
                int cellTotal = row.getPhysicalNumberOfCells();
                for (int cellNum = 0; cellNum < cellTotal; cellNum++) {
                    Cell cell = row.getCell(cellNum);
                    int cellType = cell.getCellType();
                    // 判断内容类型
                    switch (cellType){
                        case HSSFCell.CELL_TYPE_STRING:     // String类型
                            String stringCellValue = cell.getStringCellValue();
                            System.out.print(stringCellValue + " | ");
                            break;
                        case HSSFCell.CELL_TYPE_NUMERIC:    // 数字类型(日期、普通数字)
                            if (HSSFDateUtil.isCellDateFormatted(cell)){ // 日期类型
                                Date dateCellValue = cell.getDateCellValue();
                                String time = new DateTime(dateCellValue).toString("yyyy-MM-dd");
                                System.out.print(time + " | ");
                            } else {    // 普通数字
                                double numericCellValue = cell.getNumericCellValue();
                                System.out.print(numericCellValue + " | ");
                            }
                            break;
                        case HSSFCell.CELL_TYPE_BLANK:      // 空白
                            System.out.print("   | ");
                            break;
                        case HSSFCell.CELL_TYPE_BOOLEAN:    // 布尔值
                            boolean booleanCellValue = cell.getBooleanCellValue();
                            System.out.print(booleanCellValue + " | ");
                            break;
                        case HSSFCell.CELL_TYPE_ERROR:      // 错误类型
                            System.out.print("数据类型错误");
                            break;
                    }
                }
                System.out.println();
            }
        }
        fileInputStream.close();
    }
 
}

5.3 计算公式

java 复制代码
@Test
public void testFormula() throws Exception{
    FileInputStream fileInputStream = new FileInputStream(PATH + "\\计算公式.xls");
    Workbook workbook = new HSSFWorkbook(fileInputStream);
    Sheet sheetAt = workbook.getSheetAt(0);
 
    // 获取表中的计算公式
    FormulaEvaluator evaluator = new HSSFFormulaEvaluator((HSSFWorkbook) workbook);
 
    int physicalNumberOfRows = sheetAt.getPhysicalNumberOfRows();
    for (int rowNum = 0; rowNum < physicalNumberOfRows; rowNum++) {
        Row row = sheetAt.getRow(rowNum);
        if (row != null){
            int physicalNumberOfCells = row.getPhysicalNumberOfCells();
            for (int cellNum = 0; cellNum < physicalNumberOfCells; cellNum++) {
                Cell cell = row.getCell(cellNum);
                if (cell != null){
                    int cellType = cell.getCellType();
                    // 判断内容类型
                    switch (cellType){
 
                        case HSSFCell.CELL_TYPE_FORMULA:    // 公式
                            // 计算公式
                            String formula = cell.getCellFormula();
                            CellValue evaluate = evaluator.evaluate(cell);
                            String e = evaluate.formatAsString();
                            System.out.print(e + " | ");
                            break;
 
                        case HSSFCell.CELL_TYPE_STRING:     // String类型
                            String stringCellValue = cell.getStringCellValue();
                            System.out.print(stringCellValue + " | ");
                            break;
                        case HSSFCell.CELL_TYPE_NUMERIC:    // 数字类型(日期、普通数字)
                            if (HSSFDateUtil.isCellDateFormatted(cell)){ // 日期类型
                                Date dateCellValue = cell.getDateCellValue();
                                String time = new DateTime(dateCellValue).toString("yyyy-MM-dd");
                                System.out.print(time + " | ");
                            } else {    // 普通数字
                                double numericCellValue = cell.getNumericCellValue();
                                System.out.print(numericCellValue + " | ");
                            }
                            break;
                        case HSSFCell.CELL_TYPE_BLANK:      // 空白
                            System.out.print("   | ");
                            break;
                        case HSSFCell.CELL_TYPE_BOOLEAN:    // 布尔值
                            boolean booleanCellValue = cell.getBooleanCellValue();
                            System.out.print(booleanCellValue + " | ");
                            break;
                        case HSSFCell.CELL_TYPE_ERROR:      // 错误类型
                            System.out.print("数据类型错误");
                            break;
                    }
                }
 
            }
            System.out.println();
        }
    }
}

EasyExcel操作:

按照我的流程,结合官方文档给出的代码去写,妥妥的没问题。

1.导入依赖:

注意:easyExcel依赖本身就依赖了 poi 和 poi-ooxml 两个包,注意避免冲突。

亲测:当我们排除 easyExcel 中的poi 和 poi-ooxml 两个包,会导致版本的冲突,找不到一些方法,这可能是依赖版本升级以后,有些方法被弃用导致的。最稳妥的做法就是将我们自己导入的 poi 那两个依赖去掉。

java 复制代码
         <!-- slf4j -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <scope>compile</scope>
        </dependency>
        <!--fastJson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.75</version>
        </dependency>
        <!-- easyExcel-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.0-beta2</version>
        </dependency>
        <!-- xls 03 -->
       <!-- <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.9</version>
        </dependency>-->
        <!-- xlsx 07 -->
        <!--<dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.9</version>
        </dependency>-->

2.写入测试

demo:最简单的写

2.1 创建实体:

官方文档代码中有@Data注解,其实就是 lombok 这个依赖的注解,可以在程序启动时,自动帮我们生成 get、set 方法。有兴趣的小伙伴自行研究,字段较少,我使用的原始的方法,自己写的get、set、构造方法等,就不贴出来了。

ps:Lombok很强大,可以只使用注解就能实现在程序启动时自动生成 get、set、toString、hash、构造方法等,用于简化代码,允许链式编程等等,不过也有弊端,就等可爱的你,自己去发现了。

java 复制代码
package com.ggz.poi.entity;
 
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
 
import java.util.Date;
 
// @Data
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    @ExcelProperty("数字标题")
    private Double doubleData;
    /**
     * 忽略这个字段
     */
    @ExcelIgnore
    private String ignore;

2.2 生成数据:

如果是在日常开发中,数据的来源往往是来自数据库、缓存等。

java 复制代码
private List<DemoData> data() {
    List<DemoData> list = new ArrayList<DemoData>();
    for (int i = 0; i < 10; i++) {
        DemoData data = new DemoData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

2.3 写入文件:

easyExcel 官方文档中给出了3种写入的操作方式,我这里选用的是最简单的。

java 复制代码
@Test
public void testEasyExcelWrite(){
    // 写法2
    String fileName = PATH + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    // 如果这里想使用03 则 传入excelType参数即可
    // fileName 文件写出的目录和工作簿名称
    // DemoData.class 写出对象的字节码文件
    // sheet("模板") 工作表名称
    // data() 写入到工作表的数据
    EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
}

2.4 生成结果:

3.读取测试

demo:最简单的读

3.1 创建实体:

可以继续使用刚刚写入时的 DemoData 实体。

3.2 配置监听:

java 复制代码
package com.ggz.poi.listener;
 
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.ggz.poi.entity.DemoData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import java.util.ArrayList;
import java.util.List;
 
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
public class DemoDataListener extends AnalysisEventListener<DemoData> {
    private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class);
    /**
     * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 3000;
    /**
     * 缓存的数据
     */
    private List<DemoData> list = new ArrayList<>(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) {
        LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));
        list.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (list.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            list = new ArrayList<>(BATCH_COUNT);
        }
    }
 
    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        LOGGER.info("所有数据解析完成!");
    }
 
    /**
     * 加上存储数据库
     */
    private void saveData() {
        LOGGER.info("{}条数据,开始存储数据库!", list.size());
        // demoDAO.save(list);
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i).toString());
        }
        LOGGER.info("存储数据库成功!");
    }
 
}

3.3 读取文件:

java 复制代码
private static final Logger LOGGER = LoggerFactory.getLogger(EasyExcelTest.class);
/**
     * 最简单的读
     * <p>
     * 1. 创建excel对应的实体对象 参照{@link DemoData}
     * <p>
     * 2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoDataListener}
     * <p>
     * 3. 直接读即可
     */
@Test
public void testSimpleRead(){
    // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
    // 写法3:
    String fileName = PATH + "simpleWrite1632457706893.xlsx";
    // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
    EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();
}

3.4 执行结果:

我这里 slf 日志没有打印,原因是 slf4j 依赖有问题,导个依赖就好了,前面补上了。如果是复制的我贴出来的依赖,是没有问题的。

固定套路:

1、写入,固定类格式进行写入

2、读取,根据监听器设置的规则进行读取!

相关推荐
兮动人1 小时前
SpringBoot加载配置文件的优先级
java·spring boot·后端·springboot加载配置
m0_748254662 小时前
Spring Boot 热部署
java·spring boot·后端
佳佳_3 小时前
Spring Boot SSE 示例
spring boot·后端
臣妾写不来啊4 小时前
使用dify的api连接外部知识库,dify连接ragflow的知识库(附java代码)
java·开发语言·spring boot
李长渊哦4 小时前
Spring Boot 接口延迟响应的实现与应用场景
spring boot·后端·php
Cent'Anni5 小时前
【RabbitMQ】事务
java·spring boot·rabbitmq
小杨4045 小时前
springboot框架项目应用实践五(websocket实践)
spring boot·后端·websocket
浪九天5 小时前
Java直通车系列28【Spring Boot】(数据访问Spring Data JPA)
java·开发语言·spring boot·后端·spring
一只爱打拳的程序猿6 小时前
【SpringBoot】实现登录功能
javascript·css·spring boot·mybatis·html5
源码姑娘8 小时前
基于协同过滤算法的音乐推荐系统(源码+部署教程)
spring boot·毕业设计