JAVA-POI && easyEXCEL

这篇具有很好参考价值的文章主要介绍了JAVA-POI && easyEXCEL。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

https://easyexcel.opensource.alibaba.com/docs/current/quickstart/write#web%E4%B8%AD%E7%9A%84%E5%86%99

Apache POI [1] 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程序对Microsoft Office格式档案读和写的功能。POI为“Poor Obfuscation Implementation”的首字母缩写,意为“简洁版的模糊实现”。

HSSF [1]  - 提供读写Microsoft Excel XLS格式档案的功能。
XSSF [1]  - 提供读写Microsoft Excel OOXML XLSX格式档案的功能。
HWPF [1]  - 提供读写Microsoft Word DOC格式档案的功能。
HSLF [1]  - 提供读写Microsoft PowerPoint格式档案的功能。
HDGF [1]  - 提供读Microsoft Visio格式档案的功能。
HPBF [1]  - 提供读Microsoft Publisher格式档案的功能。
HSMF [1]  - 提供读Microsoft Outlook格式档案的功能。

Java领域解析、生成Excel比较有名的框架有Apache poi、jxl等。但他们都存在一个严重的问题就是非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或者JVM频繁的full gc。easyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。64M内存1分钟内读取75M(46W行25列)的Excel(当然还有急速模式能更快,但是内存占用会在100M多一点)。

JAVA-POI && easyEXCEL
easyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。下图是easyExcel和POI在解析Excel时的对比图。
JAVA-POI && easyEXCEL
easyExcel采用一行一行的解析模式,并将一行的解析结果以观察者的模式通知处理(AnalysisEventListener)。

1 基础版本

<!-- https://mvnrepository.com/artifact/org.apache.poi/poi 03 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.9</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml 07-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.9</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/joda-time/joda-time -->
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.10.1</version>
        </dependency>

JAVA-POI && easyEXCEL

JAVA-POI && easyEXCEL
HSSFWorkbook 03
XSSFWorkbook 07
SXSSFWorkbook 超级

package com.poi;

import cn.hutool.core.date.DateTime;
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 java.io.FileOutputStream;
import java.io.IOException;

public class POITest {
    public static void main(String[] args) throws IOException {
        test03();
        test07();
    }
    
    public static void test07() throws IOException {
        // 创建一个工作簿
        Workbook workbook = new XSSFWorkbook();
        // 创建一个工作表
        Sheet sheet = workbook.createSheet("sheet-1");
        // 创建一行
        Row row_0 = sheet.createRow(0); // 第一行

        // 创建一个单元格
        Cell cell_00 = row_0.createCell(0);
        cell_00.setCellValue("今日新增观众"); // (0,0)
        Cell cell_01 = row_0.createCell(1);
        cell_01.setCellValue(666); // (0,1)

        Row row_1 = sheet.createRow(1);
        Cell cell_10 = row_1.createCell(0);
        cell_10.setCellValue("统计时间"); // (1,0)
        Cell cell_11 = row_1.createCell(1);
        cell_11.setCellValue(new DateTime().toString("yyyy-MM-dd HH:mm:ss")); // (1,1)

        // 生成一个表 IO
        String Path = "/Users/zhaoshuai11/Desktop/utools/src/main/resources/file/";
        FileOutputStream fileOutputStream = new FileOutputStream(Path + "观众统计表07.xlsx");
        workbook.write(fileOutputStream);
        fileOutputStream.close();
    }

    public static void test03() throws IOException {
        // 创建一个工作簿
        Workbook workbook = new HSSFWorkbook();
        // 创建一个工作表
        Sheet sheet = workbook.createSheet("sheet-1");
        // 创建一行
        Row row_0 = sheet.createRow(0); // 第一行

        // 创建一个单元格
        Cell cell_00 = row_0.createCell(0);
        cell_00.setCellValue("今日新增观众"); // (0,0)
        Cell cell_01 = row_0.createCell(1);
        cell_01.setCellValue(666); // (0,1)

        Row row_1 = sheet.createRow(1);
        Cell cell_10 = row_1.createCell(0);
        cell_10.setCellValue("统计时间"); // (1,0)
        Cell cell_11 = row_1.createCell(1);
        cell_11.setCellValue(new DateTime().toString("yyyy-MM-dd HH:mm:ss")); // (1,1)

        // 生成一个表 IO
        String Path = "/Users/zhaoshuai11/Desktop/utools/src/main/resources/file/";
        FileOutputStream fileOutputStream = new FileOutputStream(Path + "观众统计表03.xls");
        workbook.write(fileOutputStream);
        fileOutputStream.close();
    }
}

2 数据批量导入

大文件写HSSF,缺点:最多只能处理65536行,否则会抛出异常。

java. lang. IlegalArgumentException: Invalid row number (65536) outside al lowable range (0. .65535)

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

大文件写XSSF,缺点:写数据时速度非常慢,非常耗内存,也会发生内存溢出,如100万条。
优点:可以写较大的数据量,如20万条。

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

注意:过程中会产生临时文件,需要清理临时文件。

默认由100条记录被保存在内存中,如果超过这数量,则最前面的数据被写入临时文件。如果想自定义内存中数据的数量,可以使用new SXSSFWorkbook (数量)。

SXSSFWorkbook-来至官方的解释:实现BigGridDemo策略的流式XSSFWorkbook版本。这允许写入非常大的文件而不会耗尽內存,因为任何时候只有可配置的行部分被保存在内存中。请注意,仍然可能会消耗大量內存,这些内存基于您正在使用的功能,例如合并区域,注释……仍然只存储在内存中,因此如果广泛使用,可能需要大量内存。

1 HSSFWorkbook - 2.242s

 public static void testHSSFWorkbookBD() throws IOException {
        // 时间
        long startTime = System.currentTimeMillis();
        Workbook workbook = new HSSFWorkbook();
        Sheet sheet = workbook.createSheet();
        /**
         * Exception in thread "main" java.lang.IllegalArgumentException: Invalid row number (65536) outside allowable range (0..65535)
         */
        for (int i = 0; i < 65536; i++) {
            Row row = sheet.createRow(i);
            for (int j = 0; j < 10; j++) {
                Cell cell = row.createCell(j);
                cell.setCellValue(j);
            }
        }
        System.out.println("over");
        String Path = "/Users/zhaoshuai11/Desktop/utools/src/main/resources/file/";
        FileOutputStream fileOutputStream = new FileOutputStream(Path + "HSSFWorkbook03.xls");
        workbook.write(fileOutputStream);
        fileOutputStream.close();
        long endTime = System.currentTimeMillis();
        System.out.println((double) (endTime - startTime) / 1000); // 时间比较快 数据量有限
    }

2 XSSFWorkbook - 13.682s

 public static void testXSSFWorkbookBD() throws IOException {
        // 时间
        long startTime = System.currentTimeMillis();
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet();
        for (int i = 0; i < 200000; i++) {
            Row row = sheet.createRow(i);
            for (int j = 0; j < 10; j++) {
                Cell cell = row.createCell(j);
                cell.setCellValue(j);
            }
        }
        System.out.println("over");
        String Path = "/Users/zhaoshuai11/Desktop/utools/src/main/resources/file/";
        FileOutputStream fileOutputStream = new FileOutputStream(Path + "HSSFWorkbook07.xlsx");
        workbook.write(fileOutputStream);
        fileOutputStream.close();
        long endTime = System.currentTimeMillis();
        System.out.println((double) (endTime - startTime) / 1000); // 5.064 时间长 但是可以写入更加多的数据
    }

3 SXSSFWorkbook - 5.788s

 public static void testBDSXSSFWorkbook() throws IOException {
        // 时间
        long startTime = System.currentTimeMillis();
        SXSSFWorkbook workbook = new SXSSFWorkbook();
        Sheet sheet = workbook.createSheet();
        for (int i = 0; i < 200000; i++) {
            Row row = sheet.createRow(i);
            for (int j = 0; j < 10; j++) {
                Cell cell = row.createCell(j);
                cell.setCellValue(j);
            }
        }
        System.out.println("over");
        String Path = "/Users/zhaoshuai11/Desktop/utools/src/main/resources/file/";
        FileOutputStream fileOutputStream = new FileOutputStream(Path + "SXSSFWorkbook.xlsx");
        workbook.write(fileOutputStream);
        // 清除临时文件
        workbook.dispose();
        fileOutputStream.close();
        long endTime = System.currentTimeMillis();
        System.out.println((double) (endTime - startTime) / 1000);
    }

3 POI读

1 基础版本- 注意获取值的类型

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

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

public class POIRead {
    public static void main(String[] args) throws IOException {
        test07();
    }

    public static void test03() throws IOException {
        // 获取文件流
        String PATH = "/Users/zhaoshuai11/Desktop/utools/src/main/resources/file/观众统计表03.xls";
        FileInputStream fileInputStream = new FileInputStream(PATH);
        // 创建一个工作簿
        Workbook workbook = new HSSFWorkbook(fileInputStream);
        Sheet sheet = workbook.getSheetAt(0);
        Row row = sheet.getRow(0);
        Cell cell = row.getCell(1);
        /**
         * 获取不同的类型
         * System.out.println(cell.getStringCellValue());
         */
        System.out.println(cell.getNumericCellValue());
        fileInputStream.close();
    }

    public static void test07() throws IOException {
        // 获取文件流
        String PATH = "/Users/zhaoshuai11/Desktop/utools/src/main/resources/file/观众统计表07.xlsx";
        FileInputStream fileInputStream = new FileInputStream(PATH);
        // 创建一个工作簿
        Workbook workbook = new XSSFWorkbook(fileInputStream);
        Sheet sheet = workbook.getSheetAt(0);
        Row row = sheet.getRow(0);
        Cell cell = row.getCell(1);
        /**
         * 获取不同的类型
         * System.out.println(cell.getStringCellValue());
         */
        System.out.println(cell.getNumericCellValue());
        fileInputStream.close();
    }
}

2 读取不同类型的值

package com.poi;
public class POIRead {
    public static void main(String[] args) throws IOException {
        testCellType();
    }

    public static void testCellType() throws IOException {
        // 获取文件流
        String PATH = "/Users/zhaoshuai11/Desktop/utools/src/main/resources/file/住址.xlsx";
        FileInputStream fileInputStream = new FileInputStream(PATH);
        // 创建一个工作簿
        Workbook workbook = new XSSFWorkbook(fileInputStream);
        Sheet sheet = workbook.getSheetAt(0);
        Row rowTitle = sheet.getRow(0);
        if (null != rowTitle) {
            int cells = rowTitle.getPhysicalNumberOfCells();
            for (int i = 0; i < cells; i++) {
                Cell cell = rowTitle.getCell(i);
                if (null != cell) {
                    CellType cellType = cell.getCellType();
                    String cellValue = cell.getStringCellValue();
                    System.out.print(cellValue + " | ");
                }
            }
        }
        System.out.println();
        int rows = sheet.getPhysicalNumberOfRows();
        for (int i = 1; i < rows; i++) {
            Row rowData = sheet.getRow(i);
            if (null != rowData) {
                int cells = rowData.getPhysicalNumberOfCells();
                for (int j = 0; j < cells; j++) {
                    Cell cell = rowData.getCell(j);
                    if (null != cell) {
                        CellType cellType = cell.getCellType();
                        String cellValue = "";
                        // 匹配类型
                        switch (cellType) {
                            case STRING:
                                cellValue = cell.getStringCellValue();
                                break;
                            case BOOLEAN:
                                cellValue = String.valueOf(cell.getBooleanCellValue());
                                break;
                            case BLANK:
                                break;
                            case NUMERIC:
                                if (DateUtil.isCellDateFormatted(cell)) {
                                    cellValue = new DateTime(cell.getDateCellValue()).toString("yyyy-MM-dd");
                                } else {
                                    cellValue = new DecimalFormat("0").format(cell.getNumericCellValue());
                                }
                                break;
                            case ERROR:
                                break;
                        }
                        System.out.print(cellValue + " | ");
                    }
                }
                System.out.println();
            }
        }

        fileInputStream.close();
    }


    public static void test03() throws IOException {
        // 获取文件流
        String PATH = "/Users/zhaoshuai11/Desktop/utools/src/main/resources/file/观众统计表03.xls";
        FileInputStream fileInputStream = new FileInputStream(PATH);
        // 创建一个工作簿
        Workbook workbook = new HSSFWorkbook(fileInputStream);
        Sheet sheet = workbook.getSheetAt(0);
        Row row = sheet.getRow(0);
        Cell cell = row.getCell(1);
        /**
         * 获取不同的类型
         * System.out.println(cell.getStringCellValue());
         */
        System.out.println(cell.getNumericCellValue());
        fileInputStream.close();
    }

    public static void test07() throws IOException {
        // 获取文件流
        String PATH = "/Users/zhaoshuai11/Desktop/utools/src/main/resources/file/观众统计表07.xlsx";
        FileInputStream fileInputStream = new FileInputStream(PATH);
        // 创建一个工作簿
        Workbook workbook = new XSSFWorkbook(fileInputStream);
        Sheet sheet = workbook.getSheetAt(0);
        Row row = sheet.getRow(0);
        Cell cell = row.getCell(1);
        /**
         * 获取不同的类型
         * System.out.println(cell.getStringCellValue());
         */
        System.out.println(cell.getNumericCellValue());
        fileInputStream.close();
    }

}

4 easyEXCEL

<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.0.5</version>
</dependency>

1 通用数据生成

    private static 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;
    }

2 最简单的写

JAVA-POI && easyEXCEL

2.1 最简单的写的对象
package com.easyexcel;
@Data
@EqualsAndHashCode
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    @ExcelProperty("数字标题")
    private Double doubleData;
    /**
     * 忽略这个字段
     */
    @ExcelIgnore
    private String ignore;
}
2.2 代码
/**
     * 最简单的写
     * <p>
     * 1. 创建excel对应的实体对象 参照{@link DemoData}
     * <p>
     * 2. 直接写即可
     */
    @Test
    public void simpleWrite() {
        // 注意 simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大参照 重复多次写入
        String fileName = "/Users/zhaoshuai11/Desktop/utools/src/main/resources/file/easyExcel.xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        // 如果这里想使用03 则 传入excelType参数即可
        // 分页查询数据
        EasyExcel.write(fileName, DemoData.class)
                .sheet("模板")
                .doWrite(TestEasyExcel::data);
    }

3 根据参数只导出指定列

/**
     * 根据参数只导出指定列
     * <p>
     * 1. 创建excel对应的实体对象 参照{@link DemoData}
     * <p>
     * 2. 根据自己或者排除自己需要的列
     * <p>
     * 3. 直接写即可
     *
     * @since 2.1.1
     */
    @Test
    public void excludeOrIncludeWrite() {
        String fileName = "/Users/zhaoshuai11/Desktop/utools/src/main/resources/file/easyExcel-1.xlsx";
        // 这里需要注意 在使用ExcelProperty注解的使用,如果想不空列则需要加入order字段,而不是index,order会忽略空列,然后继续往后,而index,不会忽略空列,在第几列就是第几列。

        // 根据用户传入字段 假设我们要忽略 date
        Set<String> excludeColumnFiledNames = new HashSet<String>();
        excludeColumnFiledNames.add("date");
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(fileName, DemoData.class).excludeColumnFiledNames(excludeColumnFiledNames).sheet("模板")
                .doWrite(data());

        String fileName_2 = "/Users/zhaoshuai11/Desktop/utools/src/main/resources/file/easyExcel-2.xlsx";
        // 根据用户传入字段 假设我们只要导出 date
        Set<String> includeColumnFiledNames = new HashSet<String>();
        includeColumnFiledNames.add("date");
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(fileName_2, DemoData.class).includeColumnFiledNames(includeColumnFiledNames).sheet("模板")
                .doWrite(data());
    }

4 指定写入的列

package com.easyexcel;
@Getter
@Setter
@EqualsAndHashCode
public class IndexData {
    @ExcelProperty(value = "字符串标题", index = 0)
    private String string;
    @ExcelProperty(value = "日期标题", index = 1)
    private Date date;
    /**
     * 这里设置3 会导致第二列空的
     */
    @ExcelProperty(value = "数字标题", index = 3)
    private Double doubleData;
}
    /**
     * 指定写入的列
     * <p>1. 创建excel对应的实体对象 参照{@link IndexData}
     * <p>2. 使用{@link ExcelProperty}注解指定写入的列
     * <p>3. 直接写即可
     */
    @Test
    public void indexWrite() {
        String fileName = "/Users/zhaoshuai11/Desktop/utools/src/main/resources/file/easyExcel-3.xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(fileName, IndexData.class).sheet("模板").doWrite(data());
    }

JAVA-POI && easyEXCEL

5 复杂头写入

JAVA-POI && easyEXCEL

package com.easyexcel;
@Getter
@Setter
@EqualsAndHashCode
public class ComplexHeadData {
    @ExcelProperty({"主标题", "字符串标题"})
    private String string;
    @ExcelProperty({"主标题", "日期标题"})
    private Date date;
    @ExcelProperty({"主标题", "数字标题"})
    private Double doubleData;
}
    /**
     * 复杂头写入
     * <p>1. 创建excel对应的实体对象 参照{@link ComplexHeadData}
     * <p>2. 使用{@link ExcelProperty}注解指定复杂的头
     * <p>3. 直接写即可
     */
    @Test
    public void complexHeadWrite() {
        String fileName = "/Users/zhaoshuai11/Desktop/utools/src/main/resources/file/easyExcel-4.xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(fileName, ComplexHeadData.class).sheet("模板").doWrite(data());
    }

6 重复多次写入(写到单个或者多个Sheet)

/**
     * 重复多次写入
     * 直接调用二次写入即可
     */
    @Test
    public void repeatedWrite() {
        // 方法1: 如果写到同一个sheet
        String fileName = "/Users/zhaoshuai11/Desktop/utools/src/main/resources/file/easyExcel.xlsx";
        // 这里 需要指定写用哪个class去写
        ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build();
        // 这里注意 如果同一个sheet只要创建一次
        WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
        // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来
        for (int i = 0; i < 5; i++) {
            // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
            List<DemoData> data = data();
            excelWriter.write(data, writeSheet);
        }
        excelWriter.finish();
    }
        // 方法2: 如果写到不同的sheet 同一个对象
        ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build();
        // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
        for (int i = 0; i < 5; i++) {
            // 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样
            WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).build();
            // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
            List<DemoData> data = data();
            excelWriter.write(data, writeSheet);
        }
        excelWriter.finish();

7 日期、数字或者自定义格式转换

JAVA-POI && easyEXCEL

package com.easyexcel;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.format.NumberFormat;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;

import java.util.Date;

@Getter
@Setter
@EqualsAndHashCode
public class ConverterData {
    /**
     * 我想所有的 字符串起前面加上"自定义:"三个字
     */
    @ExcelProperty(value = "字符串标题")
    private String string;
    /**
     * 我想写到excel 用年月日的格式
     */
    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    @ExcelProperty("日期标题")
    private Date date;
    /**
     * 我想写到excel 用百分比表示
     */
    @NumberFormat("#.##%")
    @ExcelProperty(value = "数字标题")
    private Double doubleData;
}
    /**
     * 日期、数字或者自定义格式转换
     * <p>1. 创建excel对应的实体对象 参照{@link ConverterData}
     * <p>2. 使用{@link ExcelProperty}配合使用注解{@link DateTimeFormat}、{@link NumberFormat}或者自定义注解
     * <p>3. 直接写即可
     */
    @Test
    public void converterWrite() {
        String fileName = "/Users/zhaoshuai11/Desktop/utools/src/main/resources/file/easyExcel.xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(fileName, ConverterData.class).sheet("模板").doWrite(data());
    }

8 最简单的读

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

    /**
     * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 100;
    /**
     * 缓存的数据
     */
    private List<DemoData> 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(cachedDataList);
        log.info("存储数据库成功!");
    }
}
2 持久层
package com.easyexcel;
/**
 * 假设这个是你的DAO存储。当然还要这个类让spring管理,当然你不用需要存储,也不需要这个类。
 **/
public class DemoDAO {
    public void save(List<DemoData> list) {
        // 持久化操作
        // 如果是mybatis,尽量别直接调用多次insert,自己写一个mapper里面新增一个方法batchInsert,所有数据一次性插入
    }
}
3 代码
 /**
     * 最简单的读
     * <p>
     * 1. 创建excel对应的实体对象 参照{@link DemoData}
     * <p>
     * 2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoDataListener}
     * <p>
     * 3. 直接读即可
     */
    @Test
    public void simpleRead() {
        // 写法1:JDK8+ ,不用额外写一个DemoDataListener
        // since: 3.0.0-beta1
        String fileName = "/Users/zhaoshuai11/Desktop/utools/src/main/resources/file/easyExcel.xlsx";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
        // 这里每次会读取100条数据 然后返回过来 直接调用使用数据就行
        EasyExcel.read(fileName, DemoData.class, new PageReadListener<DemoData>(dataList -> {
            for (DemoData demoData : dataList) {
                log.info("读取到一条数据{}", JSON.toJSONString(demoData));
            }
        })).sheet().doRead();
   }

JAVA-POI && easyEXCEL

// 写法2:
        // 匿名内部类 不用额外写一个DemoDataListener
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
        read(fileName, DemoData.class, new ReadListener<DemoData>() {
            /**
             * 单次缓存的数据量
             */
            public static final int BATCH_COUNT = 100;
            /**
             *临时存储
             */
            private List<DemoData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

            @Override
            public void invoke(DemoData data, AnalysisContext context) {
                cachedDataList.add(data);
                if (cachedDataList.size() >= BATCH_COUNT) {
                    saveData();
                    // 存储完成清理 list
                    cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
                }
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                saveData();
            }

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

JAVA-POI && easyEXCEL

        // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
        // 写法3:
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
        EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();

JAVA-POI && easyEXCEL文章来源地址https://www.toymoban.com/news/detail-451145.html

        // 写法4
        // 一个文件一个reader
        ExcelReader excelReader = EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).build();
        // 构建一个sheet 这里可以指定名字或者no
        ReadSheet readSheet = EasyExcel.readSheet(0).build();
        // 读取一个sheet
        excelReader.read(readSheet);
        excelReader.finish();

到了这里,关于JAVA-POI && easyEXCEL的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • POI和EasyExcel学习

    在Java中,POI是指Apache POI(Poor Obfuscation Implementation),它是一个开源的Java库,用于处理Microsoft Office文档格式文件,如Excel、Word、PowerPoint等。POI提供了一组API,使得开发者可以通过Java代码读取、写入和修改Office文档,可以方便地操作Excel表格、Word文档、PowerPoint演示文稿等。

    2024年01月18日
    浏览(22)
  • POI与EasyExcel--写Excel

     03和07版的简单写入注意事项: 1. 对象不同:03对应HSSFWorkbook,07对应XSSFWorkbook 2. 文件后缀不同:03对应xls,07对应xlsx 大文件写HSSF               缺点: 最多处理65536行,再多会抛出异常              优点: 过程中写入缓存,不操作磁盘,最后一次性写入磁盘,

    2024年02月12日
    浏览(32)
  • 数据导入导出(POI以及easyExcel)

            将一些数据库信息导出为Excel表格         将Excel表格数据导入数据库         大量数据的导入导出操作 常⽤的解决⽅案为: Apache POI 与阿⾥巴巴 easyExcel Apache POI 是基于 Office Open XML 标准( OOXML )和 Microsoft 的 OLE 2 复合⽂档 格式( OLE2 )处理各种⽂件格式的

    2024年02月13日
    浏览(29)
  • easyExcel 与 POI 基础知识

    开发中经常会涉及到Excel的处理,如导出Excel,导入Excel到数据库中 引用场景: ​ 将用户信息导出为Excel表格 ​ 将Excel表中的信息录入到网站数据库(习题上传…),大大减轻网站录入量。(大概意思就是将内容写在表格中,然后通过表格一次性的录入数据库,不用一个一个的

    2024年02月15日
    浏览(19)
  • easyexcel poi根据模板导出Excel

    参考:https://blog.csdn.net/weixin_45742032/article/details/119593288?spm=1001.2101.3001.6650.1utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-1-119593288-blog-86538258.235%5Ev38%5Epc_relevant_anti_t3_basedepth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-1-11959328

    2024年02月10日
    浏览(34)
  • POI及EasyExcel操作xls,xlsx文件

    Apache POI 是基于 Office Open XML 标准(OOXML)和 Microsoft 的 OLE 2 复合文档格式(OLE2)处理各种文件格式的开源项目。 可以使用 Java 读写 MS Excel 文件,可以使用 Java 读写 MS Word 和 MS PowerPoint 文件。 HSSF - 提供读写 Microsoft Excel XLS 格式 (Microsoft Excel 97 (-2003)) 档案的功能。 XSSF - 提

    2024年02月11日
    浏览(27)
  • Apache POI及easyExcel读取及写入excel文件

    目录 1.excel 2.使用场景 3.Apache POI 4.easyExcel 5.总结 1.excel excel分为两版,03版和07版。 03版的后缀为xls,最大有65536行。 07版的后缀为xlsx,最大行数没有限制。 2.使用场景 将用户信息导出到excel表格中。 将excel中的数据读取到数据库中。 3.Apache POI (1)说明 Apache POI是Apache软件基金会

    2024年02月06日
    浏览(35)
  • 使用POI和EasyExcel来实现excel文件的导入导出

    废话不多说咱们直接上干货!!!! 一.读取Excel表格 【1】使用POI读取excel表格中的数据 POI还可以操作我们这个word文档等等,他不仅仅只能弄Excel,而JXI只能操作excel 1.POI的结构,我们可以更具文件的类去选择 相关的对象我当前是使用的XLSX来操作的 HSSF - 提供读写Microsoft

    2024年02月05日
    浏览(37)
  • EasyExcel+POI制作带有有效性校验及下拉联动的Excel模板

    最近在做一个CRM系统的人员销售目标导入的相关需求,需要将销售人员的目标导入到系统中,就要求在Excel导入模板中 填写销售人员Id 和销售人员姓名。在使用的时候,这是一个易错的点,因为这两个字段交给了使用者去自由填写的话,是很容易填错的。除了文字本身填多填

    2024年02月11日
    浏览(24)
  • 使用Apache POI数据导出及EasyExcel进行十万、百万的数据导出

    Apache POI 是基于 Office Open XML 标准( OOXML )和 Microsoft 的 OLE 2 复合⽂档 格式( OLE2 )处理各种⽂件格式的开源项⽬。 简⽽⾔之,您可以使⽤ Java 读写 MS Excel ⽂件,可以使⽤ Java 读写 MS Word 和 MS PowerPoint ⽂件。 1.HSSF - 提供读写 Microsoft Excel XLS 格式 (Microsoft Excel 97 (-2003)) 档案

    2024年02月15日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包