前言:

推荐免费POI及EasyExcel视频:【狂神说Java】POI及EasyExcel一小时搞定_哔哩哔哩_bilibili

笔记代码下载地址:

蓝奏云:下载地址 密码:joker

百度云:下载地址 提取码:uazm

POI和EasyExcel

Apache POI

Apache POI 是由 Apache 基金会提供的一个 API,它是不同 java 库的集合。这些库提供了读取、写入和操作不同微软文件的功能,如 excel 工作表、power-point 和 word 文件。

Apache POI - Download Release Artifacts

基本功能

  • HSSF-提供读写MicrosoftExcel格式档案的功能
  • HSSF-提供读写MicrosoftExcel OOXML格式档案的功能
  • HWPF-提供读写MicrosoftWord格式档案的功能
  • HSLF-提供读写MicrosoftPowerPoint格式档案的功能
  • HDGF-提供读写MicrosoftVisio格式档案的功能

EasyExcel

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

alibaba/easyexcel: 快速、简洁、解决大文件内存溢出的java处理Excel工具 (github.com)

应用场景

  • 将用户信息导出为Excel表格

  • 将Excel表中的信息录入到网站数据库

Excel基本写操作

Apache POI - Download Release Artifacts

POI-Excel写

  1. 创建一个空项目,空项目下创建Maven ModulePOI

  2. 引入pom依赖

    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
    <!--    引入依赖-->
    <dependencies>
    <!-- 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.1</version>
    </dependency>
    <!-- junit-->
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13</version>
    </dependency>
    </dependencies>

    03|07版本写入,就是对象不同,方法一样的。

    03版本最多只有65535行

  3. Excel主要对象

    • 工作簿:Workbook

    • 工作表:Sheet

    • 行:Row

    • 列(单元格):Cell

  4. Excel基本写测试

    03版本

    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
    package com.jokerdig;

    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.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;

    /**
    * @author Joker大雄
    * @data 2022/8/30 - 10:34
    **/
    public class ExcelWriteTest {
    // 存放路径
    String PATH= "D:\\Project\\project3\\POI&EasyExcel\\excel\\";
    // 03版本的excel
    @Test
    public void testWrite03() throws IOException {
    // 1. 创建工作簿
    Workbook workbook = new HSSFWorkbook();
    // 2. 创建工作表
    Sheet sheet = workbook.createSheet("学习统计表");
    // 3. 创建第一行
    Row row1 = sheet.createRow(0);
    // 4. 创建单元格
    Cell cell1_1 = row1.createCell(0);
    // 5. 写入值
    cell1_1.setCellValue("今日学习时间");
    // 第二个单元格
    Cell cell1_2 = row1.createCell(1);
    // 时间工具类
    String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
    cell1_2.setCellValue(time);
    // 创建第二行
    Row row2 = sheet.createRow(1);
    Cell cell2_1 = row2.createCell(0);
    cell2_1.setCellValue("今日学习进度");
    Cell cell2_2 = row2.createCell(1);
    cell2_2.setCellValue("60%");
    // 6. 生成Excel表 03版本使用.xls
    FileOutputStream outputStream = new FileOutputStream(PATH + "学习信息统计03.xls");
    workbook.write(outputStream);
    // 关闭流
    outputStream.close();
    System.out.println("03Excel生成完毕");
    }
    }

    运行结果

    1
    2
    3
    03Excel生成完毕

    Process finished with exit code 0

    21

    07版本

    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
    // 07版本的excel
    @Test
    public void testWrite07() throws IOException {
    // 1. 创建工作簿
    Workbook workbook = new XSSFWorkbook();
    // 2. 创建工作表
    Sheet sheet = workbook.createSheet("学习统计表");
    // 3. 创建第一行
    Row row1 = sheet.createRow(0);
    // 4. 创建单元格
    Cell cell1_1 = row1.createCell(0);
    // 5. 写入值
    cell1_1.setCellValue("今日学习时间");
    // 第二个单元格
    Cell cell1_2 = row1.createCell(1);
    // 时间工具类
    String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
    cell1_2.setCellValue(time);
    // 创建第二行
    Row row2 = sheet.createRow(1);
    Cell cell2_1 = row2.createCell(0);
    cell2_1.setCellValue("今日学习进度");
    Cell cell2_2 = row2.createCell(1);
    cell2_2.setCellValue("60%");
    // 6. 生成Excel表 07版本使用.xlsx
    FileOutputStream outputStream = new FileOutputStream(PATH + "学习信息统计07.xlsx");
    workbook.write(outputStream);
    // 关闭流
    outputStream.close();
    System.out.println("07Excel生成完毕");
    }

    运行结果

    1
    2
    3
    07Excel生成完毕

    Process finished with exit code 0

    14

大数据量写入

大文件写HSSF

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

java.lang.IllegalArgumentException: Invalid row number (65536) outside allowable range (0..65535)

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 大文件写03
@Test
public void testWrite03BigData() throws IOException {
// 时间
long begin = System.currentTimeMillis();
// 创建一个工作簿
Workbook workbook = new HSSFWorkbook();
// 创建表
Sheet sheet = workbook.createSheet();
// 写入数据
for (int rowNum = 0; rowNum < 65536; rowNum++) {
Row row = sheet.createRow(rowNum);
for (int cellNum = 0; cellNum < 10; cellNum++) {
Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
System.out.println("数据写入完成");
FileOutputStream outputStream = new FileOutputStream(PATH + "testWrite03BigData.xls");
workbook.write(outputStream);
outputStream.close();
long end = System.currentTimeMillis();
System.out.println((double) (end-begin)/1000);
}

运行结果

1
2
3
4
数据写入完成
1.67

Process finished with exit code 0

大文件写XSSF

缺点:写数据速度满,非常好内存,也会发生内存移除,如写入100w条数据。

优点:可以写较大的数据量,如20w条。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 大文件写07
@Test
public void testWrite07BigData() throws IOException {
// 时间
long begin = System.currentTimeMillis();
// 创建一个工作簿
Workbook workbook = new XSSFWorkbook();
// 创建表
Sheet sheet = workbook.createSheet();
// 写入数据
for (int rowNum = 0; rowNum < 65536; rowNum++) {
Row row = sheet.createRow(rowNum);
for (int cellNum = 0; cellNum < 10; cellNum++) {
Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
System.out.println("数据写入完成");
FileOutputStream outputStream = new FileOutputStream(PATH + "testWrite07BigData.xlsx");
workbook.write(outputStream);
outputStream.close();
long end = System.currentTimeMillis();
System.out.println((double) (end-begin)/1000);
}

运行结果

1
2
3
4
数据写入完成
11.945

Process finished with exit code 0

大文件写SXSSF

优点:可以写非常大的数据量,如100w条甚至更多,写数据速度快,占用内存少!

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
// 大文件写07加速
@Test
public void testWrite07BigDataS() throws IOException {
// 时间
long begin = System.currentTimeMillis();
// 创建一个工作簿
Workbook workbook = new SXSSFWorkbook();
// 创建表
Sheet sheet = workbook.createSheet();
// 写入数据
for (int rowNum = 0; rowNum < 65536; rowNum++) {
Row row = sheet.createRow(rowNum);
for (int cellNum = 0; cellNum < 10; cellNum++) {
Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
System.out.println("数据写入完成");
FileOutputStream outputStream = new FileOutputStream(PATH + "testWrite07BigDataS.xlsx");
workbook.write(outputStream);
outputStream.close();
// 关闭临时文件
((SXSSFWorkbook)workbook).dispose();
long end = System.currentTimeMillis();
System.out.println((double) (end-begin)/1000);
}

运行结果

1
2
3
4
数据写入完成
2.932

Process finished with exit code 0

Excel基本读取及注意点

03读取

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
package com.jokerdig;

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.usermodel.XSSFWorkbook;
import org.junit.Test;

import java.io.FileInputStream;
import java.io.IOException;

/**
* @author Joker大雄
* @data 2022/8/30 - 13:19
**/
public class ExcelReadTest {
// 存放路径
String PATH= "D:\\Project\\project3\\POI&EasyExcel\\excel\\";

// 03版本读excel
@Test
public void testRead03() throws IOException {
// 获取文件流
FileInputStream inputStream = new FileInputStream(PATH + "学习信息统计03.xls");
// 创建工作簿
Workbook workbook = new HSSFWorkbook(inputStream);
// 得到表
Sheet sheetAt = workbook.getSheetAt(0);
// 得到行
Row row = sheetAt.getRow(0);
// 得到单元格
Cell cell = row.getCell(0);
// 获取值的时候,一定要注意类型要对应
System.out.println(cell.getStringCellValue());
inputStream.close();
}
}

运行结果

1
2
3
今日学习时间

Process finished with exit code 0

07读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 07版本读excel
@Test
public void testRead07() throws IOException {
// 获取文件流
FileInputStream inputStream = new FileInputStream(PATH + "学习信息统计07.xlsx");
// 创建工作簿
Workbook workbook = new XSSFWorkbook(inputStream);
// 得到表
Sheet sheetAt = workbook.getSheetAt(0);
// 得到行
Row row = sheetAt.getRow(0);
// 得到单元格
Cell cell = row.getCell(0);
// 获取值的时候,一定要注意类型要对应
System.out.println(cell.getStringCellValue());
inputStream.close();
}

运行结果

1
2
3
今日学习时间

Process finished with exit code 0

读取不同类型的数据

读取文件下载:

下载地址:百度云 提取码:xssn

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
69
70
71
72
73
74
75
76
77
78
// 读取不同类型的数据
@Test
public void testReadCellType()throws IOException{
// 获取文件流
FileInputStream inputStream = new FileInputStream(PATH + "information.xlsx");
// 创建工作簿
Workbook workbook = new XSSFWorkbook(inputStream);
Sheet sheetAt = workbook.getSheetAt(0);
// 获取标题内容
Row rowTitle = sheetAt.getRow(0);
if(rowTitle!=null){
// 获取总数
int cellCount = rowTitle.getPhysicalNumberOfCells();
for (int cellNum = 0; cellNum < cellCount-1; cellNum++) {
Cell cell = rowTitle.getCell(cellNum);
if(cell!=null){
int cellType = cell.getCellType();
String cellValue = cell.getStringCellValue();
System.out.print(cellValue+" | ");
}
}
System.out.println();
}
// 获取表中数据
int rowCount = sheetAt.getPhysicalNumberOfRows();
for (int rowNum = 1; rowNum < rowCount; rowNum++) {
Row rowData = sheetAt.getRow(rowNum);
if(rowData!=null){
// 读取列
int cellCount = rowTitle.getPhysicalNumberOfCells();
for (int cellNum = 0; cellNum < cellCount; cellNum++) {
// System.out.print("["+(rowNum+1)+"-"+(cellNum+1)+"]");
Cell cell = rowData.getCell(cellNum);
// 匹配列的数据类型
if(cell!=null){
int cellType = cell.getCellType();
String cellValue = "";
switch (cellType){
// 字符串
case XSSFCell.CELL_TYPE_STRING:
System.out.print("[String]");
cellValue = cell.getStringCellValue();
break;
// 布尔值
case XSSFCell.CELL_TYPE_BOOLEAN:
System.out.print("[Boolean]");
cellValue =String.valueOf(cell.getBooleanCellValue());
break;
// 数字
case XSSFCell.CELL_TYPE_NUMERIC:
System.out.print("[Numeric]");
// 数字类型 日期 普通数字
if(DateUtil.isCellDateFormatted(cell)){
Date date = cell.getDateCellValue();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
cellValue = format.format(date);
}else{
// 普通数字
cell.setCellType(XSSFCell.CELL_TYPE_STRING);
cellValue = cell.toString();
}
break;
// 为空
case XSSFCell.CELL_TYPE_BLANK:
System.out.print("[Blank]");
break;
// error
case XSSFCell.CELL_TYPE_ERROR:
System.out.print("[Error]");
break;
}
System.out.println(cellValue);
}
}
}
}
inputStream.close();
}

运行结果

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
编号 | 卡号 | 持卡人 | 手机号 | 消费日期 | 小票号 | 商品编号 | 商品条码 | 商品名称 | 商品单位 | 原价 | 销售价 | 销售数量 | 销售金额 | 优惠金额 | 是否上架 | 
[Numeric]1
[Numeric]100010
[String]Jokerdig
[Numeric]1399999999
[Numeric]2022-09-01
[String]0000202200146
[String]PV70012
[String]PV70012
[String]果子绘
[String]袋
[Numeric]300.5
[Numeric]100
[Numeric]3
[Numeric]300
[Numeric]200
[Boolean]true
[Numeric]2
[Numeric]100011
[String]Joker大雄
[Numeric]1398899889
[Numeric]2022-08-30
[String]0000202200140
[String]PV70016
[String]PV70016
[String]荷美尔
[String]盒
[Numeric]233.23
[Numeric]150
[Numeric]1
[Numeric]233
[Boolean]false

Process finished with exit code 0

了解计算公式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Test
public void testFormula() throws IOException {
// 获取文件流
FileInputStream inputStream = new FileInputStream(PATH + "sum.xlsx");
XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
XSSFSheet sheet = workbook.getSheetAt(0);
XSSFRow row = sheet.getRow(4);
XSSFCell cell = row.getCell(0);
// 拿到计算公式
XSSFFormulaEvaluator formulaEvaluator = new XSSFFormulaEvaluator(workbook);

// 输出单元格内容
int cellType = cell.getCellType();
switch(cellType){
case Cell.CELL_TYPE_FORMULA:
String cellFormula = cell.getCellFormula();
System.out.println(cellFormula);
// 计算
CellValue evaluate = formulaEvaluator.evaluate(cell);
String cellValue = evaluate.formatAsString();
System.out.println(cellValue);
break;
}
}

运行结果

1
2
3
4
SUM(A2:A4)
600.0

Process finished with exit code 0

EasyExcel使用

官方文档:EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel (alibaba.com)

  1. 新建moduleEasyExcel

  2. 导入pom依赖

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.0.1</version>
    </dependency>
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version>
    </dependency>
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    </dependency>
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.62</version>
    </dependency>
  3. 测试写

    新建包com.jokerdig.easyExcel,在包下新建DemoData

    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
    package com.jokerdig.easyExcel;

    import com.alibaba.excel.annotation.ExcelIgnore;
    import com.alibaba.excel.annotation.ExcelProperty;
    import lombok.EqualsAndHashCode;
    import lombok.Getter;
    import lombok.Setter;

    import java.util.Date;

    /**
    * @author Joker大雄
    * @data 2022/8/30 - 15:01
    **/
    @Getter
    @Setter
    @EqualsAndHashCode
    public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    @ExcelProperty("数字标题")
    private Double doubleData;
    /**
    * 忽略这个字段
    */
    @ExcelIgnore
    private String ignore;
    }

    EasyTest

    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
    package com.jokerdig.easyExcel;

    import com.alibaba.excel.EasyExcel;
    import com.alibaba.excel.ExcelWriter;
    import com.alibaba.excel.util.ListUtils;
    import com.alibaba.excel.write.metadata.WriteSheet;
    import org.junit.Test;

    import java.util.Date;
    import java.util.List;

    /**
    * @author Joker大雄
    * @data 2022/8/30 - 15:08
    **/
    public class EasyTest {
    // 存放路径
    String PATH= "D:\\Project\\project3\\POI&EasyExcel\\excel\\";

    private List<DemoData> data() {
    List<DemoData> list = ListUtils.newArrayList();
    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;
    }

    @Test
    public void simpleWrite() {
    // 注意 simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大参照 重复多次写入

    // 写法1 JDK8+
    // since: 3.0.0-beta1
    String fileName = PATH+"WriteTest1.xlsx";
    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    EasyExcel.write(fileName, DemoData.class)
    .sheet("模板")
    .doWrite(() -> {
    // 分页查询数据
    return data();
    });

    // 写法2
    fileName =PATH+"WriteTest2.xlsx";
    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
    }
    }
  4. 运行结果

    13

  5. 测试读

    DemoDAO

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    package com.jokerdig.easyExcel;

    import java.util.List;

    /**
    * 假设这个是你的DAO存储。当然还要这个类让spring管理,当然你不用需要存储,也不需要这个类。
    **/
    public class DemoDAO {
    public void save(List<DemoData> list) {
    // 如果是mybatis,尽量别直接调用多次insert,自己写一个mapper里面新增一个方法batchInsert,所有数据一次性插入
    }
    }

    DemoDataListener

    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
    package com.jokerdig.easyExcel;

    import com.alibaba.excel.context.AnalysisContext;
    import com.alibaba.excel.read.listener.ReadListener;
    import com.alibaba.excel.util.ListUtils;
    import com.alibaba.fastjson.JSON;
    import lombok.extern.slf4j.Slf4j;

    import java.util.List;

    // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
    @Slf4j
    public class DemoDataListener implements ReadListener<DemoData> {

    /**
    * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
    */
    private static final int BATCH_COUNT = 5;
    /**
    * 缓存的数据
    */
    private List<DemoData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    /**
    * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
    */
    private DemoDAO demoDAO;

    public DemoDataListener() {
    // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
    demoDAO = new DemoDAO();
    }
    // 读取数据会执行 invoke 方法
    // DemoData 类型
    // AnalysisContext 分析上文
    @Override
    public void invoke(DemoData data, AnalysisContext context) {
    System.out.println(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(cachedDataList);
    log.info("存储数据库成功!");
    }
    }

    EasyTest

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // 读
    @Test
    public void simpleRead() {
    // 写法1:JDK8+ ,不用额外写一个DemoDataListener
    // since: 3.0.0-beta1
    String fileName = PATH+"WriteTest1.xlsx";
    // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
    // 这里每次会读取100条数据 然后返回过来 直接调用使用数据就行
    System.out.println("============================方法1========================");
    EasyExcel.read(fileName, DemoData.class, new PageReadListener<DemoData>(dataList -> {
    for (DemoData demoData : dataList) {
    System.out.println(JSON.toJSONString(demoData));;
    }
    })).sheet().doRead();
    // 写法2
    // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
    fileName = PATH+"WriteTest2.xlsx";
    // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
    System.out.println("============================方法2========================");
    EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();

    }
  6. 运行结果

    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
    ============================方法1========================
    SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
    SLF4J: Defaulting to no-operation (NOP) logger implementation
    SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
    {"date":1661843837623,"doubleData":0.56,"string":"字符串0"}
    {"date":1661843837623,"doubleData":0.56,"string":"字符串1"}
    {"date":1661843837623,"doubleData":0.56,"string":"字符串2"}
    {"date":1661843837623,"doubleData":0.56,"string":"字符串3"}
    {"date":1661843837623,"doubleData":0.56,"string":"字符串4"}
    {"date":1661843837623,"doubleData":0.56,"string":"字符串5"}
    {"date":1661843837623,"doubleData":0.56,"string":"字符串6"}
    {"date":1661843837623,"doubleData":0.56,"string":"字符串7"}
    {"date":1661843837623,"doubleData":0.56,"string":"字符串8"}
    {"date":1661843837623,"doubleData":0.56,"string":"字符串9"}
    ============================方法2========================
    {"date":1661843838122,"doubleData":0.56,"string":"字符串0"}
    {"date":1661843838122,"doubleData":0.56,"string":"字符串1"}
    {"date":1661843838122,"doubleData":0.56,"string":"字符串2"}
    {"date":1661843838122,"doubleData":0.56,"string":"字符串3"}
    {"date":1661843838122,"doubleData":0.56,"string":"字符串4"}
    {"date":1661843838122,"doubleData":0.56,"string":"字符串5"}
    {"date":1661843838122,"doubleData":0.56,"string":"字符串6"}
    {"date":1661843838122,"doubleData":0.56,"string":"字符串7"}
    {"date":1661843838122,"doubleData":0.56,"string":"字符串8"}
    {"date":1661843838122,"doubleData":0.56,"string":"字符串9"}

    Process finished with exit code 0
  7. 固定写法

    • 写入,固定类格式进行写入

    • 读取,根据监听器设置的规则进行读取