Apache POI的读写

POI-Excel

常用信息

  1. 将用户信息导出为excel表格(例如是导出数据:数据库信息)
  2. 将excel表中的信息录入网站数据库(例如是导入数据:题库)

开发中经常会用到excel的处理,例如导入、导出excel

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

Apache POI(会比较麻烦一些)

官网:Apache POI - the Java API for Microsoft Documents

百度简介:

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

结构:

在这里插入图片描述


easyExcel(alibaba)

官网:https://github.com/alibaba/easyexce or EasyExcel · 语雀 (yuque.com)

在这里插入图片描述

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

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

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

文件解压文件读取通过文件形式

img

POI-Excel写

创建项目

  1. 创建一个新项目

  2. 引入pom依赖

     <!--导入依赖-->
        <dependencies>
            <!--03-->
             <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi</artifactId>
                <version>4.1.0</version>
            </dependency>
             <!--07-->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>4.1.0</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.13.2</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
  3. 科普:03版本的execl和07版本的execl有什么区别了?

  4. 03与07版本的区别:

    03版本

     @Test
        public void test03() throws IOException {
            //创建一个工作簿
            Workbook workbook = new HSSFWorkbook();
            //创建一个工作表
            Sheet sheet = workbook.createSheet("李凯的工作表");
            //创建行
            Row row = sheet.createRow(0);
            //创建单元格子((0,0)
            Cell cell = row.createCell(0);
            /*添加内容*/
            cell.setCellValue("今天花费");
            //(0,1)
            Cell cell1 = row.createCell(1);
            cell.setCellValue("20");
            /*1,0*/
            final Row row1 = sheet.createRow(1);
            final Cell cell2 = row1.createCell(0);
            cell2.setCellValue("统计时间");
            final String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss:sss");
            final Cell cell3 = row1.createCell(1);
            /*放入时间*/
            cell3.setCellValue(time);
            /*生成一张表 03版本使用xls结尾*/
            FileOutputStream fileOutputStream = new FileOutputStream(PATH + "李凯的日出消费表.xls");
            workbook.write(fileOutputStream);
            //关闭流
            fileOutputStream.close();
            workbook.close();
            System.out.println("生成完毕");
        } 
    

    07版本

    public void test07() throws IOException {
            //创建一个工作簿
            Workbook workbook = new XSSFWorkbook();
            //创建一个工作表
            Sheet sheet = workbook.createSheet("李凯的工作表");
            //创建行
            Row row = sheet.createRow(0);
            //创建单元格子((0,0)
            Cell cell = row.createCell(0);
            /*添加内容*/
            cell.setCellValue("今天花费");
            //(0,1)
            Cell cell1 = row.createCell(1);
            cell1.setCellValue("20");
            /*1,0*/
             Row row1 = sheet.createRow(1);
            Cell cell2 = row1.createCell(0);
            cell2.setCellValue("统计时间");
            final String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss:sss");
            final Cell cell3 = row1.createCell(1);
            /*放入时间*/
            cell3.setCellValue(time);
            /*生成一张表 03版本使用xls结尾*/
            FileOutputStream fileOutputStream = new FileOutputStream(PATH + "李凯的日出消费表.xlsx");
            workbook.write(fileOutputStream);
            //关闭流
            fileOutputStream.close();
            workbook.close();
            System.out.println("生成完毕");
        }
    

    区别:

    1. 对象的区别

      03版本: Workbook workbook = new HSSFWorkbook();

      07版本:Workbook workbook = new XSSFWorkbook();

    2. 后缀名的区别

      0307
      xlsxlsx
  5. 03版本的大文件写入

缺点:最多只可以写入65536行,否则会抛出异常

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

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

时间:
在这里插入图片描述

正确代码:

 public void test03BigData() throws IOException {
        // 时间差:
        final long begin = System.currentTimeMillis();

        //创建一个工作簿
        Workbook workbook = new HSSFWorkbook();
        //创建表
        final Sheet sheet = workbook.createSheet();
        //写入数据
        for (int rowNum = 0;rowNum<65536;rowNum++){
            final Row row = sheet.createRow(rowNum);
            for (int cellNum = 0;cellNum<10;cellNum++){
                final Cell cell = row.createCell(cellNum);
                cell.setCellValue(cellNum);
            }
        }
        System.out.println("over");
        final FileOutputStream fileOutputStream = new FileOutputStream(PATH+"测试.xls");
        workbook.write(fileOutputStream);
        fileOutputStream.close();
        final long end = System.currentTimeMillis();
        System.out.println((double)(end-begin)/1000);
    }

报错代码:

public void test03BigData() throws IOException {
    // 时间差:
    final long begin = System.currentTimeMillis();

    //创建一个工作簿
    Workbook workbook = new HSSFWorkbook();
    //创建表
    final Sheet sheet = workbook.createSheet();
    //写入数据
    for (int rowNum = 0;rowNum<65537;rowNum++){
        final Row row = sheet.createRow(rowNum);
        for (int cellNum = 0;cellNum<10;cellNum++){
            final Cell cell = row.createCell(cellNum);
            cell.setCellValue(cellNum);
        }
    }
    System.out.println("over");
    final FileOutputStream fileOutputStream = new FileOutputStream(PATH+"测试.xls");
    workbook.write(fileOutputStream);
    fileOutputStream.close();
    final long end = System.currentTimeMillis();
    System.out.println((double)(end-begin)/1000);
}
  1. 07版本的大文件写入

    缺点:写数据时数据速度非常慢,非常消耗内存,也会发生溢出,如100w条数据

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

    时间:
    在这里插入图片描述

    可以发现哪怕多了一条数据,时间就多了将进4倍

    代码:

    public void test07BigData() throws IOException {
        // 时间差:
        final long begin = System.currentTimeMillis();
    
        //创建一个工作簿
        Workbook workbook = new XSSFWorkbook();
        //创建表
        final Sheet sheet = workbook.createSheet();
        //写入数据
        for (int rowNum = 0;rowNum<65537;rowNum++){
            final Row row = sheet.createRow(rowNum);
            for (int cellNum = 0;cellNum<10;cellNum++){
                final Cell cell = row.createCell(cellNum);
                cell.setCellValue(cellNum);
            }
        }
        System.out.println("over");
        final FileOutputStream fileOutputStream = new FileOutputStream(PATH+"测试.xlsx");
        workbook.write(fileOutputStream);
        fileOutputStream.close();
        final long end = System.currentTimeMillis();
        System.out.println((double)(end-begin)/1000);
    }
    
  2. 07版本的大数据写SXSSF

    优点:可以写非常大的数据量,例如100w条数据甚至更多条,相对于07版本的XSSF,他的读写数据更快,占用内存更少

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

    默认的时100条记录被保存在内存中,如果超过这个数量,则最前面的数据将会写入到临时文件当中。

    如果要想自定义内存中的数据的数量,则可以通过new SXXSFWorkbook(数量)

    时间:
    在这里插入图片描述

    代码:

     public void test07BigDataS() throws IOException {
            // 时间差:
            final long begin = System.currentTimeMillis();
    
            //创建一个工作簿
            Workbook workbook = new SXSSFWorkbook();
            //创建表
            final Sheet sheet = workbook.createSheet();
            //写入数据
            for (int rowNum = 0;rowNum<65537;rowNum++){
                final Row row = sheet.createRow(rowNum);
                for (int cellNum = 0;cellNum<10;cellNum++){
                    final Cell cell = row.createCell(cellNum);
                    cell.setCellValue(cellNum);
                }
            }
            System.out.println("over");
            final FileOutputStream fileOutputStream = new FileOutputStream(PATH+"测试.xlsx");
            workbook.write(fileOutputStream);
            fileOutputStream.close();
            /*清除临时文件*/
            ((SXSSFWorkbook)workbook).dispose();
            final long end = System.currentTimeMillis();
            System.out.println((double)(end-begin)/1000);
        }
    

POI-Excel读

07/03版本

@Test
public void test03() throws IOException {

    //获取文件流
    FileInputStream fileInputStream = new FileInputStream(PATH+"ABC.xls");
    //创建一个工作簿.使用excel能完成的操作这里都可以完成
    Workbook workbook = new HSSFWorkbook(fileInputStream);
    //获取表
    final Sheet sheetAt = workbook.getSheetAt(0);
    /*获取行*/
    final Row row = sheetAt.getRow(0);
    final int RowNum = sheetAt.getLastRowNum();
    /*获取列*/
    final Cell cell = row.getCell(0);
    final String stringCellValue = cell.getStringCellValue();
    System.out.println(stringCellValue);
    System.out.println(RowNum);
    fileInputStream.close();
}

07版本:

@Test
public void test03() throws IOException {

    //获取文件流
    FileInputStream fileInputStream = new FileInputStream(PATH+"ABC.xlsx");
    //创建一个工作簿.使用excel能完成的操作这里都可以完成
    Workbook workbook = new XSSFWorkbook(fileInputStream);
    //获取表
    final Sheet sheetAt = workbook.getSheetAt(0);
    /*获取行*/
    final Row row = sheetAt.getRow(0);
    final int RowNum = sheetAt.getLastRowNum();
    /*获取列*/
    final Cell cell = row.getCell(0);
    final String stringCellValue = cell.getStringCellValue();
    System.out.println(stringCellValue);
    System.out.println(RowNum);
    fileInputStream.close();
}

读取不同的数据类型

重点:数据转换类型!

  @Test
    public void test07Demo() throws IOException {

        //获取文件流
        FileInputStream fileInputStream = new FileInputStream(PATH+"ABC.xlsx");
        //创建一个工作簿.使用excel能完成的操作这里都可以完成
        Workbook workbook = new XSSFWorkbook(fileInputStream);
        //获取表
        Sheet sheetAt = workbook.getSheetAt(0);
        /*获取行数*/
        Row row = sheetAt.getRow(0);
        if (row!=null){
            /*获取所有的行数*/
            final int physicalNumberOfCells = row.getPhysicalNumberOfCells();
            for (int CellNum = 0; CellNum < physicalNumberOfCells; CellNum++) {
                final Cell cell = row.getCell(CellNum);
                if (cell!=null){
                    /*获取行的类型*/
                    CellType cellType = cell.getCellType();
                    String stringCellValue = cell.getStringCellValue();
                    System.out.print(stringCellValue+" ");
                }
            }
            System.out.println();
        }
        //获取表中的数据(列数)
        int physicalNumberOfRows = sheetAt.getPhysicalNumberOfRows();
        for (int RowNum = 1; RowNum < physicalNumberOfRows; RowNum++) {
            final Row row1 = sheetAt.getRow(RowNum);
            if (row1!=null){
                //读取列
                final int physicalNumberOfCells = row1.getPhysicalNumberOfCells();
                for (int cellNumber = 0; cellNumber < physicalNumberOfCells; cellNumber++) {
                    final Cell cell = row1.getCell(cellNumber);
                    //匹配列的数据类型
                    if (cell!=null){
                        CellType cellType = cell.getCellType();
                        String cellValue = "";
                        /*判断类型*/
                        switch (cellType){
                            case STRING:
                                System.out.println("字符串");
                                cellValue= cell.getStringCellValue();
                                break;
                            case BOOLEAN:
                                System.out.println("布尔类型");
                                cellValue = String.valueOf(cell.getBooleanCellValue());
                                break;
                            case BLANK:
                                System.out.println("为空");
                                break;
                            case NUMERIC: //数字(日期和普通数字)
                                if (HSSFDateUtil.isCellDateFormatted(cell)){ //日期
                                    System.out.println("日期类型");
                                    Date date = cell.getDateCellValue();
                                    cellValue = new DateTime(date).toString("yyyy-MM-dd");
                                }else {
                                    System.out.println("数字");
                                    cellValue = String.valueOf(cell.getNumericCellValue());
                                }
                                break;
                            case ERROR:
                                System.out.println("数组类型错误");
                                break;
                        }
                        System.out.println(cellValue);
                    }
                }
            }
        }
        fileInputStream.close();
    }

计算公式:

 @Test
    public void testFormula() throws IOException {
       FileInputStream fileInputStream = new FileInputStream(PATH + "Documents测试.xlsx");
       Workbook workbook= new XSSFWorkbook(fileInputStream);
       Sheet sheetAt = workbook.getSheetAt(0);
       Row row = sheetAt.getRow(4);
       Cell cell = row.getCell(0);
       //拿到计算公式 eval
        FormulaEvaluator xssfFormulaEvaluator = new XSSFFormulaEvaluator((XSSFWorkbook) workbook);
        //输出单元格的内容
        CellType cellType = cell.getCellType();
        switch (cellType){
            case FORMULA: //公式
               String cellFormula = cell.getCellFormula();
                System.out.println(cellFormula);
               //计算
                CellValue evaluate = xssfFormulaEvaluator.evaluate(cell);
                String CellValue = evaluate.formatAsString();
                System.out.println(CellValue);
                break;
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值