Java操作Excel——Apache POI

POI是什么

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

版本差异

poi 有两个版本:03版本和07版本,引入的依赖各不相同,也有细微的差距

03年创建的表格是 .xls 后缀、07年版本是.xlsx版本。两个版本的差异体现在内容大小上。

以下是两个两个版本的依赖:








    org.apache.poi

    poi

    3.17









    org.apache.poi

    poi-ooxml

    3.17



使用流程

该工具很好的体现了面向对象的思想。把 Excel 里的内容对象化。

里面的对象大致分四个:

  1. Excel的对象

  2. Sheet 对象

  3. 行对象

  4. 单元格对象

03版本

按照上面的对象流程来书写代码。因为是写操作,所以需要手动创建该对象


public void writeExcel(){

    String path = "E:\\";

    // 创建一个Excel对象

    Workbook workbook = new HSSFWorkbook();

    // 创建一个工作薄

    Sheet sheet = workbook.createSheet();

    // 创建一行 0代表Excel的第一行

    Row row = sheet.createRow(0);

    // 创建单元格

    Cell cell = row.createCell(0);

    // 给单元格书写内容

    cell.setCellValue("张三");

    // 内容写完后输出到硬盘上

    // 这里要自己指定后缀 务必遵循 03 使用xls 否则无法打开

    try (FileOutputStream fos = new FileOutputStream(path+"excel03.xls")) {

        //  注意! 这里是用excel对象来进行写入。

        workbook.write(fos);

        System.out.println("输出完毕");

        workbook.close();

    }catch (Exception e){

        e.printStackTrace();

    }

}

读操作,所以先从本地读取Excel


public void readExcel() throw Exception{

    // 读取excel

    FileInputStream fis = new FileInputStream("E:\\excel03.xls");

    // 将流读入 WorkBook 中

    Workbook workbook = new HSSFWorkbook(fis);

    // 获取第一页 sheet || 通过 getSheet 读取,参数是 sheet 的名字

    Sheet sheet0 = workbook.getSheetAt(0);

    // 获取第一行

    Row row = sheet0.getRow(0);

    // 获取第一个单元格

    Cell cell = row.getCell(0);

    // 读取不比写入,这里有一点问题,因为读取出来的数据可能是 数字、字符串、时间格式 所以需要额外判断  稍后在07版本写判断该数据什么格式

    System.out.println(cell.getStringCellValue());

    // 别忘记关流了

    workbook.close();

    fis.close();

}

07版本

03和07的书写差异并不大。实现类、后缀名不同。

流程基本一样,注意 实现类,文件后缀名即可


public void writeExcel07(){

    String path = "E:\\";

    Workbook workbook = new XSSFWorkbook();

    Sheet sheet = workbook.createSheet();

    Row row = sheet.createRow(0);

    Cell cell = row.createCell(0);

    cell.setCellValue("李四");

    // 后缀名 xlsx

    try (FileOutputStream fos = new FileOutputStream(path+"excel07.xlsx")) {

        workbook.write(fos);

        System.out.println("输出完毕");

        workbook.close();

    }catch (Exception e){

        e.printStackTrace();

    }

}

读取流程一样


public void readExcel() throws Exception(){

    FileInputStream fis = new FileInputStream("E:\\excel07.xlsx");

    Workbook workbook = new XSSFWorkbook(fis);

    Sheet sheet = workbook.getSheetAt(0);

    Row row = sheet.getRow(0);

    Cell cell = row.getCell(0);

    System.out.println(cell.getStringCellValue());

    workbook.close();

    fis.close();

}

超级写

超级写和普通写的区别:速度!速度!

实现方式变为new SXSSFWorkbook(),且需要显示的清除文件缓存。


public void superWriteExcel(){

    String path = "E:\\";

    // 接口无清除方法,所以不采用接口申明

    SXSSFWorkbook workbook = new SXSSFWorkbook();

    Sheet sheet = workbook.createSheet();

    Row row = sheet.createRow(0);

    Cell cell = row.createCell(0);

    cell.setCellValue("李四");

    try (FileOutputStream fos = new FileOutputStream(path+"excel07.xlsx")) {

        workbook.write(fos);

        System.out.println("输出完毕");

        workbook.close();

        // 清除临时文件  这里清除

        workbook.dispose(); 

    }catch (Exception e){

        e.printStackTrace();

    }

}

读取时候数据类型的判断

以下代码是正常读取一个excel所做的操作


public void read()throws Exception{

    FileInputStream fis = new FileInputStream("E:\\excel07.xlsx");

    Workbook workbook = new XSSFWorkbook(fis);

    Sheet sheet = workbook.getSheetAt(0);

    // 获取第一行 一般是表头

    Row rowTitle = sheet.getRow(0);

    // 单元格是否为空

    if (rowTitle != null) {

        // 一行中单元格数量

        int titleCellCount = rowTitle.getPhysicalNumberOfCells();

        for (int cellNum = 0; cellNum < titleCellCount; cellNum++) {

            Cell cell = rowTitle.getCell(cellNum);

            String cellValue = cell.getStringCellValue();

            System.out.print(cellValue + " |");

        }

        System.out.println();

        // 获取一共有多少行

        int rowCount = sheet.getPhysicalNumberOfRows();

        // 这里从第二行开始读取 因为第一行是表头

        for (int i = 1; i < rowCount; i++) {

            Row rowDate = sheet.getRow(i);

            if (rowDate != null) {

                int cellCount = rowDate.getPhysicalNumberOfCells();

                for (int cellNum = 0; cellNum < cellCount; cellNum++) {

                    Cell cellDate = rowDate.getCell(cellNum);

                    String cellValue = "";

                    if (cellDate != null) {

                        switch (cellDate.getCellTypeEnum()) {

                            case STRING:

                                cellValue = cellDate.getStringCellValue();

                                break;

                            case BOOLEAN:

                                cellValue = String.valueOf(cellDate.getBooleanCellValue());

                                break;

                            case NUMERIC:

                                if ("General".equals(cellDate.getCellStyle().getDataFormatString())) {

                                    cellValue = cellDate.toString();

                                } else if ("m/d/yy".equals(cellDate.getCellStyle().getDataFormatString())) {

                                    // 用的时间格式化工具,无视之

                                    cellValue = new DateTime(cellDate.getDateCellValue()).toString("yyyy-MM-dd");

                                } else {

                                    cellValue = cellDate.toString();

                                }

                                break;

                            case BLANK:

                                break;

                        }

                    }

                    System.out.print(cellValue + "|");

                }

            }

        }

    }

    fis.close();

}

以上就是POI的基本读写了。

一些其他问题

读取多少行有两个方法:

假设现在在excel 第1行有数据 第10行有数据 2-9无数据

sheet.getLastRowNum():读取的是最后一行有数据的行数,n-1 10-1 九行

sheet.getPhysicalNumberOfRows():读取有数据的行数, n-m 10-8 两行

读取一行有多少列的两个方法:

假设现在excel第一行 第1列有数据 第10列有数据

row.getLastCellNum():读取是最后一列有数据的数字,n(非n-1)

row.getPhysicalNumberOfCells():读取有数据的行数,n-m 10-8 两列

PS:注意虽然方法名都是Last 但是行读取的不是n-1模式而是直接取n

读取问题

上面的读有03版本和07版本,写的时候也是分开写的,那么有一个通用读取方法吗?

必然是有的采用工厂读取。

2003/2007/2010 都是可以处理的

Workbook workbook = WorkbookFactory.create(fis);

写入问题

当excel 执行write 后,创建的 workbook对象则被清空,此时读取设置好的数据会出现空指向异常。

使用注意

poi使用采用的一口气读取进内存,所以读取过大的excel非常容易出现OOM

所以还有另外一个软件阿里出的:EasyExcel

你可能感兴趣的:(Java操作Excel——Apache POI)