POI and EasyExcel Tutorial

1. POI and EasyExcel

KuangStudy

POI and EasyExcel learning video: Kuangshen said POI and EasyExcel tutorial

KuangStudy
https://www.kuangstudy.com/course

POI及EasyExcel学习视频:
https://www.bilibili.com/video/BV1Ua4y1x7BK?p=1

POI教程:
https://www.yiibai.com/apache_poi/

Easy Excel:
https://easyexcel.opensource.alibaba.com/

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

1. Introduction

1. Application scenarios

将用户信息导出为excel表格
讲Excel表中的信息录入到网站数据库,大大减小网站数据的录入量!
开发中经常会涉及到excel的处理,如导出Excel到数据库中!

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

2、Apache POI

Apache POI official website: https://poi.apache.org/

	Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office格式档案读和写的功能。POI为“Poor Obfuscation Implementation”的首字母缩写,意为“简洁版的模糊实现”。
	Apache POI是一种流行的API,它允许程序员使用Java程序创建,修改和显示MS Office文件。这由Apache软件基金会开发使用Java分布式设计或修改Microsoft Office文件的开源库。它包含类和方法对用户输入数据或文件到MS Office文档进行解码。

1641280109930

3、 EasyExcel

easyExcel official website address: https://github.com/alibaba/easyexcel

easyExcel API:https://www.yuque.com/easyexcel/doc/easyexcel

1641280576712

EasyExcel is a simple, memory-saving open source project for reading and writing Excel based on Java. In the case of saving memory as much as possible, it supports reading and writing Excel of hundreds of M.

1641280699239

Two, POI-Execel write

1. Create an empty project, create a new module, and modify the jdk configuration

2. Import maven dependencies

<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>com.alibaba</groupId>-->
            <!--<artifactId>easyexcel</artifactId>-->
            <!--<version>2.1.7</version>-->
        <!--</dependency>-->

    <!--<dependency>-->
        <!--<groupId>com.alibaba</groupId>-->
        <!--<artifactId>fastjson</artifactId>-->
        <!--<version>1.2.62</version>-->
    <!--</dependency>-->
    <!--lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.12</version>
    </dependency>

    <!--日期格式化工具-->
    <dependency>
        <groupId>joda-time</groupId>
        <artifactId>joda-time</artifactId>
        <version>2.10.1</version>
    </dependency>

    <!--test-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>	

3. Find the project source directory and create 03.xls and 07.xlsx

1、03版本和07版本存在兼容性问题,03版本最多只能有65535行,07版本没有限制
2、03版本的文件后缀是xls,07版本的后缀是xlsx
3、pom文件中对应的引用包类型不用
4、java代码中引用的对象不同
5、logo不同

1641282679123

1641282908749

4. Version 03 uses xls, test

String Path="D:\\IDEA 2019.3.3\\IntelliJ IDEA projects\\POI及EasyExcel\\Jin-poi";

@Test
public void testWrite03() throws Exception {
    
    
    //1、创建工作簿 03
    Workbook workbook=new HSSFWorkbook();
    //2、创建一个工作表
    Sheet sheet = workbook.createSheet("Jin的poi的03版本写入测试表");
    //3、创建一个行
    Row row1 = sheet.createRow(0);
    //4、创建一个单元格A1(1,1)
    Cell cell11 = row1.createCell(0);
    cell11.setCellValue("第一个格子的数据:");
    //B1(1,2)
    Cell cell2 = row1.createCell(1);
    cell2.setCellValue("666");

    //第二行(2,1)
    Row row2 = sheet.createRow(1);
    Cell cell21 = row2.createCell(0);
    cell21.setCellValue("统计的时间:");
    //(2,2)
    Cell cell22 = row2.createCell(1);
    String s = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
    cell22.setCellValue(s);


    //生成一张表(IO流) 03版本使用xls
    FileOutputStream fileOutputStream = new FileOutputStream(Path + "Jin的poi的03版本写入测试表.xls");
    workbook.write(fileOutputStream);
    //关闭流
    fileOutputStream.close();
    System.out.println("Jin的poi的03版本写入测试表成完毕!");
}

1641361897492

1641361541262

5. Version 07 uses xlsx, test

@Test
public void testWrite07() throws Exception {
    
    
    //1、创建工作簿 03
    Workbook workbook=new XSSFWorkbook();
    //2、创建一个工作表
    Sheet sheet = workbook.createSheet("Jin的poi的07版本写入测试表");
    //3、创建一个行
    Row row1 = sheet.createRow(0);
    //4、创建一个单元格A1(1,1)
    Cell cell11 = row1.createCell(0);
    cell11.setCellValue("第一个格子的数据:");
    //B1(1,2)
    Cell cell2 = row1.createCell(1);
    cell2.setCellValue("666");

    //第二行(2,1)
    Row row2 = sheet.createRow(1);
    Cell cell21 = row2.createCell(0);
    cell21.setCellValue("统计的时间:");
    //(2,2)
    Cell cell22 = row2.createCell(1);
    String s = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
    cell22.setCellValue(s);

    //生成一张表(IO流) 07版本使用xlsx结尾
    FileOutputStream fileOutputStream = new FileOutputStream(Path + "Jin的poi的07版本写入测试表.xlsx");
    workbook.write(fileOutputStream);
    //关闭流
    fileOutputStream.close();
    System.out.println("Jin的poi的07版本写入测试表生成完毕!");
}

1641361930329

1641361590254

6. Write HSSF , XSSF and SXSSF for large files

6.1. Writing HSSF to large files

Disadvantages: only up to 635536 rows can be processed, otherwise an exception will be thrown

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

Advantages: write to the cache during the process, do not operate the disk, write to the disk at one time at the end, and the speed is fast

@Test
public void testWrite03BigData() throws Exception {
    
    
    //开始时间
    long begin = System.currentTimeMillis();
    //创建一个工作簿
    Workbook workbook = new HSSFWorkbook();
    //创建表
    Sheet sheet = workbook.createSheet();
    //写入数据,行数只能在65536以内,大于报错Invalid row number (65536) outside allowable range (0..65535)
    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);
        }
    }
    FileOutputStream fileOutputStream = new FileOutputStream(Path + "Jin的poi的03版本大文件写HSSF写入测试表.xls");
    workbook.write(fileOutputStream);
    fileOutputStream.close();
    //结束时间
    long end = System.currentTimeMillis();
    System.out.println("Jin的poi的03版本写入测试表生成完毕!");
    System.out.println("Jin的poi的03版本大文件写HSSF写入测试表:"+(end-begin)/1000);
}

1641362010905

1641361671719

6.2, large file write XSSF

Disadvantages: the speed of writing data is very slow, consumes a lot of memory, and memory overflow will also occur, such as 1 million

Advantages: can write a large amount of data, such as 200,000, can write a very large amount of data

@Test
public void testWrite07BigData() throws Exception {
    
    
    //开始时间
    long begin = System.currentTimeMillis();
    //创建一个工作簿
    Workbook workbook = new XSSFWorkbook();
    //创建表
    Sheet sheet = workbook.createSheet();
    //写入数据
    for (int rowNum = 0; rowNum < 100000; rowNum++) {
    
    
        Row row = sheet.createRow(rowNum);
        for (int cellNum = 0; cellNum < 10; cellNum++) {
    
    
            Cell cell = row.createCell(cellNum);
            cell.setCellValue(cellNum);
        }
    }
    FileOutputStream fileOutputStream = new FileOutputStream(Path + "Jin的poi的07版本大文件写XSSF写入测试表.xlsx");
    workbook.write(fileOutputStream);
    fileOutputStream.close();
    //结束时间
    long end = System.currentTimeMillis();
    System.out.println("Jin的poi的07版本写入测试表生成完毕!");
    System.out.println("Jin的poi的07版本大文件写XSSF写入测试表:"+(end-begin)/1000);
}

1641362057999

1641361771084

6.3. Write SXSSF for large files

Advantages: can write a very large amount of data, such as 1 million or more, write data fast, occupy less memory

Notice:

1. Temporary files will be generated during the process, and temporary files need to be cleaned up

2. By default, 100 records are stored in memory. If this number is exceeded, the first data will be written into a temporary file

3. If you want to customize the amount of data in memory, you can use new SXSSFWorkbook (number)

@Test
public void testWrite07BigDataSXSSFWorkbook() throws Exception {
    
    
    //开始时间
    long begin = System.currentTimeMillis();
    //创建一个工作簿
    Workbook workbook = new SXSSFWorkbook();
    //创建表
    Sheet sheet = workbook.createSheet();
    //写入数据
    for (int rowNum = 0; rowNum < 100000; rowNum++) {
    
    
        Row row = sheet.createRow(rowNum);
        for (int cellNum = 0; cellNum < 10; cellNum++) {
    
    
            Cell cell = row.createCell(cellNum);
            cell.setCellValue(cellNum);
        }
    }
    FileOutputStream fileOutputStream = new FileOutputStream(Path + "Jin的poi的07版本大文件写SXSSF写入测试表.xlsx");
    workbook.write(fileOutputStream);
    fileOutputStream.close();
    //清楚SXSSFWorkbook产生的临时文件
    ((SXSSFWorkbook) workbook).dispose();
    //结束时间
    long end = System.currentTimeMillis();
    System.out.println("Jin的poi的07版本写入测试表生成完毕!");
    System.out.println("Jin的poi的07版本大文件写SXSSF写入测试表:"+(end-begin)/1000);
}

1641362095748

1641361822581

Three, POI-Execel reading

1. Version 03 uses xls, test

Note: Modify Path: "D:\IDEA 2019.3.3\IntelliJ IDEA projects\POI and EasyExcel\"

String Path="D:\\IDEA 2019.3.3\\IntelliJ IDEA projects\\POI及EasyExcel\\";

@Test
public void testResd03() throws Exception {
    
    
    //1、获取文件流
    FileInputStream fileInputStream = new FileInputStream(Path + "Jin-poiJin的poi的03版本写入测试表.xls");
    //2、创建工作簿 03
    Workbook workbook=new HSSFWorkbook(fileInputStream);
    //3、得到表
    Sheet sheet = workbook.getSheet("Jin的poi的03版本写入测试表");
    //4、得到行
    Row row = sheet.getRow(0);
    //5、得到列
    Cell cell = row.getCell(1);
    //6、获取不同类型的值
    System.out.println(cell.getStringCellValue());
    //7、关闭流
    fileInputStream.close();
}

1641361391043

2. Version 07 uses xlsx, test

@Test
public void testResd07() throws Exception {
    
    
    //1、获取文件流
    FileInputStream fileInputStream = new FileInputStream(Path + "Jin-poiJin的poi的07版本写入测试表.xlsx");
    //2、创建工作簿 03
    Workbook workbook=new XSSFWorkbook(fileInputStream);
    //3、得到表
    Sheet sheet = workbook.getSheet("Jin的poi的07版本写入测试表");
    //4、得到行
    Row row = sheet.getRow(0);
    //5、得到列
    Cell cell = row.getCell(1);
    //6、获取不同类型的值
    System.out.println(cell.getStringCellValue());
    //7、关闭流
    fileInputStream.close();
}

1641361367462

3. Read different types of data

Native:

@Test
public void testCellType() throws Exception {
    
    
    //1、获取文件流
    FileInputStream fileInputStream = new FileInputStream(Path + "明细表.xls");
    //2、创建工作簿 03
    Workbook workbook = new HSSFWorkbook(fileInputStream);
    //3、获取标题内容
    Sheet sheet = workbook.getSheetAt(0);
    //4、得到行
    Row rowTitle = sheet.getRow(0);
    if(rowTitle!=null){
    
    
        int cellCount=rowTitle.getPhysicalNumberOfCells();
        for (int cellNum = 0; cellNum < cellCount; cellNum++) {
    
    
            //5、得到列
            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 = sheet.getPhysicalNumberOfRows();
    for (int rowNum = 1; rowNum < rowCount; rowNum++) {
    
    
        Row rowData = sheet.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 HSSFCell.CELL_TYPE_STRING://字符
                            System.out.print("【 String】");
                            cellValue = cell.getStringCellValue();
                            break;
                        case HSSFCell.CELL_TYPE_BOOLEAN://布尔
                            System.out.print("【 BOOLEAN】");
                            cellValue = String.valueOf(cell.getBooleanCellValue());
                            break;
                        case HSSFCell.CELL_TYPE_BLANK://System.out.print("【 BLANK】");
                            break;
                        case HSSFCell.CELL_TYPE_NUMERIC://数字(日期、普通数字)
                            System.out.print("【 NUMERIC】");
                            if (HSSFDateUtil.isCellDateFormatted(cell)) {
    
    // 日期
                                System.out.print("--【日期】");
                                Date date = cell.getDateCellValue();
                                cellValue = new DateTime(date).toString("yyyy-MM-dd");
                            } else {
    
    
                                //不是日期格式,防止数字过长!
                                System.out.print("--【转换为字符串输出】");
                                cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                                cellValue = cell.toString();
                            }
                            break;
                        case HSSFCell.CELL_TYPE_ERROR://错误
                            System.out.print("【 数据类型错误】");
                            break;
                    }
                    System.out.println(cellValue);
                }
            }
        }
    }
    //关闭流
    fileInputStream.close();
}

transfer:

public void testCellType(FileInputStream fileInputStream) throws Exception {
    
    
        //1、获取文件流

        //2、创建工作簿 03
        Workbook workbook = new HSSFWorkbook(fileInputStream);
        //3、获取标题内容
        Sheet sheet = workbook.getSheetAt(0);
        //4、得到行
        Row rowTitle = sheet.getRow(0);
        if(rowTitle!=null){
    
    
            int cellCount=rowTitle.getPhysicalNumberOfCells();
            for (int cellNum = 0; cellNum < cellCount; cellNum++) {
    
    
                //5、得到列
                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 = sheet.getPhysicalNumberOfRows();
        for (int rowNum = 1; rowNum < rowCount; rowNum++) {
    
    
            Row rowData = sheet.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 HSSFCell.CELL_TYPE_STRING://字符
                                System.out.print("【 String】");
                                cellValue = cell.getStringCellValue();
                                break;
                            case HSSFCell.CELL_TYPE_BOOLEAN://布尔
                                System.out.print("【 BOOLEAN】");
                                cellValue = String.valueOf(cell.getBooleanCellValue());
                                break;
                            case HSSFCell.CELL_TYPE_BLANK://System.out.print("【 BLANK】");
                                break;
                            case HSSFCell.CELL_TYPE_NUMERIC://数字(日期、普通数字)
                                System.out.print("【 NUMERIC】");
                                if (HSSFDateUtil.isCellDateFormatted(cell)) {
    
    // 日期
                                    System.out.print("--【日期】");
                                    Date date = cell.getDateCellValue();
                                    cellValue = new DateTime(date).toString("yyyy-MM-dd");
                                } else {
    
    
                                    //不是日期格式,防止数字过长!
                                    System.out.print("--【转换为字符串输出】");
                                    cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                                    cellValue = cell.toString();
                                }
                                break;
                            case HSSFCell.CELL_TYPE_ERROR://错误
                                System.out.print("【 数据类型错误】");
                                break;
                        }
                        System.out.println(cellValue);
                    }
                }
            }
        }
        //关闭流
        fileInputStream.close();
    }
    @Test
    public void test() throws Exception {
    
    
        FileInputStream fileInputStream = new FileInputStream(Path + "明细表.xls");
        testCellType(fileInputStream);
    }

1641361342894

4. Calculation formula

@Test
public void testFormula1() throws Exception{
    
    
    FileInputStream fileInputStream = new FileInputStream(Path + "公式表.xls");
    Workbook workbook = new HSSFWorkbook(fileInputStream);
    Sheet sheetAt = workbook.getSheetAt(0);
    //获取计算公式所在的行
    Row row = sheetAt.getRow(3);
    //获取公式的第几个单元格
    Cell cell = row.getCell(0);

    //拿到计算公式
    FormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook) workbook);
    //        FormulaEvaluator formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator();
    //输出单元格的内容
    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;
    }
}
@Test
public void testFormula2() throws Exception {
    
    
    FileInputStream fileInputStream = new FileInputStream(Path+"公式表.xls");
    Workbook workbook = new HSSFWorkbook(fileInputStream);
    //        FormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook) workbook);
    FormulaEvaluator formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator();
    for(int sheetNum = 0; sheetNum < workbook.getNumberOfSheets(); sheetNum++) {
    
    
        Sheet sheetAt = workbook.getSheetAt(sheetNum);
        for(Row row : sheetAt) {
    
    
            for(Cell cell : row) {
    
    
                if(cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
    
    
                    String cellFormula = cell.getCellFormula();
                    System.out.println(cellFormula+":");
                    CellValue evaluate = formulaEvaluator.evaluate(cell);
                    System.out.println(evaluate.formatAsString());
                }
            }
        }
    }
}

1641361256069

Four, EasyExecel write

easyExcel official website address: https://github.com/alibaba/easyexcel

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

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

1. Import maven dependencies

<dependencies>
    <!--&lt;!&ndash;xls(03)&ndash;&gt;-->
    <!--<dependency>-->
    	<!--<groupId>org.apache.poi</groupId>-->
    	<!--<artifactId>poi</artifactId>-->
    	<!--<version>3.9</version>-->
    <!--</dependency>-->
    <!--&lt;!&ndash;xlsx(07)&ndash;&gt;-->
    <!--<dependency>-->
    	<!--<groupId>org.apache.poi</groupId>-->
    	<!--<artifactId>poi-ooxml</artifactId>-->
    	<!--<version>3.9</version>-->
    <!--</dependency>-->

    <!-- easyexcel -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>easyexcel</artifactId>
        <version>2.1.7</version>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.62</version>
    </dependency>
    <!--lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.12</version>
    </dependency>

    <!--日期格式化工具-->
    <dependency>
        <groupId>joda-time</groupId>
        <artifactId>joda-time</artifactId>
        <version>2.10.1</version>
    </dependency>

    <!--test-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>

2. Write entity classes

@Getter
@Setter
@EqualsAndHashCode
public class DemoData {
    
    
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    @ExcelProperty("数字标题")
    private Double doubleData;
    /**
     * 忽略这个字段
     */
    @ExcelIgnore
    private String ignore;
}

3. Write test classes

public class EasyTest {
    
    

    String Path="D:\\IDEA 2019.3.3\\IntelliJ IDEA projects\\POI及EasyExcel\\";

    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;
    }
    @Test
    public void simpleWrite() {
    
    
        // 注意 simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大参照 重复多次写入
        // 写法1 JDK8+
        // since: 3.0.0-beta1
        String fileName = Path+"EasyTest.xlsx";
        //这里需要指定写用哪个 class去写,然后写到第一个 sheet,名字为模板然后文件流会自动关闭
        //write(fileName,格式类)
        //sheet(表名)
        //doWrite(数据)
        EasyExcel.write(fileName, DemoData.class)
            .sheet("模板")
            .doWrite(data());
    }
}

4. Output result

1641361184303

Five, EasyExecel reading

1. Write the listening class DemoDataListener (listener)

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

    /**
     * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 100;
    /**
     * 缓存的数据
     */
    private List<DemoData> cachedDataList = new ArrayList<DemoData>();
    /**
     * 假设这个是一个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));
        System.out.println(JSON.toJSONString(data));
        cachedDataList.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {
    
    
            saveData();
            // 存储完成清理 list
            cachedDataList = new ArrayList<DemoData>();
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
    
    
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成!");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
    
    
        log.info("{}条数据,开始存储数据库!", cachedDataList.size());
        demoDAO.save(cachedDataList);
        log.info("存储数据库成功!");
    }
}

2. Write persistent classes (persistence layer)

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

3. Write test classes

@Test
public void simpleRead() {
    
    
    // 写法1:JDK8+ ,不用额外写一个DemoDataListener
    // since: 3.0.0-beta1
    String fileName = Path+"EasyTest.xlsx";
    // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
    // 这里每次会读取3000条数据 然后返回过来 直接调用使用数据就行
    EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();
}

4. Output result

1641362181734

Guess you like

Origin blog.csdn.net/weixin_45207323/article/details/129791450