JAVA第三方(Excel处理):POI和easyExcel

一、POI和easyExcel介绍

1、POI介绍

Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。

  1. 基本功能

    HSSF - 提供读写Microsoft Excel格式档案的功能。

    XSSF - 提供读写Microsoft Excel OOXML格式档案的功能。

    HWPF - 提供读写Microsoft Word格式档案的功能。

    HSLF - 提供读写Microsoft PowerPoint格式档案的功能。

    HDGF - 提供读写Microsoft Visio格式档案的功能。

  2. 资料来源 :http://poi.apache.org/

2、easyExcel介绍

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

  1. 特点

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

    下图是easyExcel和POI在解析Excel时的对比图。

    JAVA第三方(Excel处理):POI和easyExcel

  2. 资料来源:https://github.com/alibaba/easyexcel

二、POI操作Excel

前期准备

导入依赖

<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>
   <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
   </dependency>
</dependencies> 

1、POI写入Excel

使用HSSFWorkbook生成的Excel文件格式是xls ,使用XSSFWorkbook生成的Excel文件格式是xlsx,使用SXSSFWorkbook使用更省时的方法生成xlsx

  1. 使用SXSSFWorkbook简单生成Excel代码样例
@Test
public void testPoiWrite() throws IOException {
    String PATH = "D:\\subject\\poi\\";
    String FILE_NAME = "POI测试表.xlsx";
    //1、创建工作薄
    Workbook workBookTest = new SXSSFWorkbook();
    //2、创建工作表
    Sheet sheet = workBookTest.createSheet("POI测试");
    //3、创建一个行(1,1)
    Row row1 = sheet.createRow(0);
    //4、创建一个单元格
    Cell cell11 = row1.createCell(0);
    cell11.setCellValue("工号");
    //5、创建第二列
    Cell cell12 = row1.createCell(1);
    cell12.setCellValue("创建时间");
    //6、插入数据到第二行
    Row row2 = sheet.createRow(1);
    Cell cell21 = row2.createCell(0);
    cell21.setCellValue("Z20210428");
    Cell cell22 = row2.createCell(1);
    String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
    cell22.setCellValue(time);
    //7、写入到文件(IO流)
    FileOutputStream fileOutputStream = new FileOutputStream(PATH+FILE_NAME);
    workBookTest.write(fileOutputStream);
    fileOutputStream.close();//关闭IO流
    ((SXSSFWorkbook)workBookTest).dispose();//清除临时文件
    System.out.println("文件生成完毕");
}
  1. 注意事项
  • 大数据批量写入Excel

大文件写HSSF

缺点:每次最多处理65536行,否则会发生异常。

有点:过程中使用缓存,不操作硬盘,最后一次性写入磁盘,所以速度快。

大文件写XSSF

缺点:写数据时速度非常慢,非常耗内存,数据量过大也会发生内存溢出,比如100万条以上。

优点:可以写较大批的数据,比如20万条左右。

大文件写SXSSF

优点:写入大批量数据(超100万条)速度较快,占用内存较少。

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

((SXSSFWorkbook)workBookTest).dispose();//清除临时文件

2、POI读取Excel

  1. HSSF读取代码样例

        @Test
        public void testPoiRead() throws IOException {
            String PATH = "D:\\subject\\poi\\";
        	String FILE_NAME = "POI测试表.xls";
            //获取文件流
            FileInputStream fileInputStream = new FileInputStream(PATH+FILE_NAME);
            //1、创建工作薄
            Workbook workBookTest = new HSSFWorkbook(fileInputStream);
            FormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook) workBookTest);//获取公式
            //2、读取第一张表
            Sheet sheet = workBookTest.getSheetAt(0);
            if(sheet!=null){
                //3、读取行
                int rowCount = sheet.getPhysicalNumberOfRows();
                for (int rowNum = 0; rowNum < rowCount; rowNum++) {
                    Row row = sheet.getRow(rowNum);
                    if(row!=null){
                        //4、读取所有列
                        int cellCount = row.getPhysicalNumberOfCells();
                        for (int cellNum = 0; cellNum < cellCount; cellNum++) {
                            //5、读取单元格
                            Cell cell = row.getCell(cellNum);
                            if(cell!=null){
                                String cellValue = "";
                                int cellType = cell.getCellType();
                                switch (cellType){
                                    case Cell.CELL_TYPE_NUMERIC:
                                        if(HSSFDateUtil.isCellDateFormatted(cell)){
                                            Date date = cell.getDateCellValue();
                                            cellValue = new DateTime(date).toString("yyyy-MM-dd");
                                        }else{
                                            //不是日期格式,防止数字过长,转换为字符串显示
                                            //注意转换为字符串后影响公式计算
                                            //cell.setCellType(Cell.CELL_TYPE_STRING);
                                            //cellValue = cell.toString();
                                            cellValue = String.valueOf(cell.getNumericCellValue());
                                        }
                                        break;
                                    case Cell.CELL_TYPE_STRING:
                                        cellValue = cell.getStringCellValue();
                                        break;
                                    case Cell.CELL_TYPE_BOOLEAN:
                                        cellValue = String.valueOf(cell.getBooleanCellValue());
                                        break;
                                    case Cell.CELL_TYPE_FORMULA:
                                        //String formula = cell.getCellFormula();
                                        //System.out.println(formula);
                                        //直接计算
                                        cellValue = (formulaEvaluator.evaluate(cell)).formatAsString();
                                        break;
                                    case Cell.CELL_TYPE_ERROR:
                                        System.out.println("【数据类型错误】");
                                        break;
                                    default:
                                        break;
                                }
                                System.out.println(cellValue);
                            }else{
                                System.out.println("【空白格】");
                                cellCount++;
                            }
                        }
                    }else{
                        System.out.println("【空白行】");
                        rowCount++;
                    }
    
                }
            }
            //关闭IO流
            fileInputStream.close();
        }
    
    1. 注意事项

      公式计算

      计算公式前栏位格式不能变化,以SUM公式为例,如果在公式计算前将数字字符转换为字符串,则计算值为0。

      //注意转换为字符串后影响公式计算
      //cell.setCellType(Cell.CELL_TYPE_STRING);
      //cellValue = cell.toString();
      FormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook) workBookTest);//获取公式
      String cellValue = (formulaEvaluator.evaluate(cell)).formatAsString(); 
      

三、easyExcel操作

前期准备

导入依赖

<!--导入easyExcel-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.7</version>
</dependency>

1、easyExcel写入

@Test
public void simpleWrite() {
    EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
}

2、easyExcel读取

@Test
public void simpleRead() {
    EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();
}
上一篇:【工具篇】EasyExcel的应用


下一篇:easyExcel实现Excel导出功能