Apache-poi操作Excel

文件对比:

从后缀名来看:

03.xls

07.xlsx

 

Excel 中的对象:

1-工作簿 2-工作表  3-行  4-列

按照面向对象的思想:显示成成一个工作簿,由工作簿创建工作表,由工作表创建行,由行指定列,从而定位到具体的某个单元格。

写文件:

03版本写:

/**
 * 操作Microsoft 03版本的excel
 */
@org.junit.Test
public void testWrite03() {
    //创建一个新的excel工作簿
    HSSFWorkbook workbook = new HSSFWorkbook();
    //在excel工作簿中创建一个工作表,其中缺省名字为sheet0
    HSSFSheet sheet = workbook.createSheet("丫丫丫统计表");
    //在这个sheet中创建第一行 row1
    HSSFRow row1 = sheet.createRow(0);//注意:第一行的下标是从0开始的
    //在这个sheet中创建第一个列,也就是第一个单元格 col 1-1
    Cell cell_1_1 = row1.createCell(0);//注意:下标也是从0开始的
    cell_1_1.setCellValue("今日新增关注");

    //创建单元格 col 1-2
    Cell cell_1_2 = row1.createCell(1);
    cell_1_2.setCellValue(999);

    //创建第二行 row 2
    HSSFRow row2 = sheet.createRow(1);
    Cell cell2_1 = row2.createCell(0);
    cell2_1.setCellValue("统计时间");

    Cell cell2_2 = row2.createCell(1);
    String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
    cell2_2.setCellValue(time);

    String path = "D:\ideaOldProject\poi-excel\";

    //新建输出流(注意:要先创建文件夹)
    FileOutputStream fileOutputStream = null;
    try {
        fileOutputStream = new FileOutputStream(path + "丫丫丫统计表03版本.xls");
        //把相应的excel 工作簿存盘
        workbook.write(fileOutputStream);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (fileOutputStream != null) {
                fileOutputStream.close();
            }
            System.out.println("文件生成完毕~~");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

  

07版本写:

  /**
     * 操作Microsoft 07版本
     */
    @org.junit.Test
    public void testWrite07(){
        //创建一个新的excel工作簿 基本上什么都没有改变,只是生成工作簿的对象变了
        XSSFWorkbook workbook = new XSSFWorkbook();
        //在excel工作簿中创建一个工作表,其中缺省名字为sheet0
        XSSFSheet sheet = workbook.createSheet("服装统计表");
        //在这个sheet中创建第一行 row1
        XSSFRow row1 = sheet.createRow(0);//注意:第一行的下标是从0开始的
        //在这个sheet中创建第一个列,也就是第一个单元格 col 1-1
        Cell cell_1_1 = row1.createCell(0);//注意:下标也是从0开始的
        cell_1_1.setCellValue("服装品牌");

        //创建单元格 col 1-2
        Cell cell_1_2 = row1.createCell(1);
        cell_1_2.setCellValue("波司登");

        //创建第二行 row 2
        XSSFRow row2 = sheet.createRow(1);
        Cell cell2_1 = row2.createCell(0);
        cell2_1.setCellValue("销量");

        Cell cell2_2 = row2.createCell(1);
//        String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
        cell2_2.setCellValue(999);

        String path = "D:\ideaOldProject\poi-excel\";

        //新建输出流(注意:要先创建文件夹)
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(path + "服装销售统计.xlsx");
            //把相应的excel 工作簿存盘
            workbook.write(fileOutputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
                System.out.println("文件生成完毕~~");
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

  

数据批量导入!

大文件写HSSF

缺点:最多只能处理65536行,否则会抛出异常

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

 

大文件写XSSF

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

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

 

大文件写SXSSF

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

注意:

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

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

如果想自定义内存中数据的数量,可以使用new SXSSFWorkbook(数量)

 

SXSSFWorkbook-来自官方的解释:实现BigGridDemo策略的流式XSSFWorkbook版本。这允许写入非常大的文件而不会耗尽内存,因为任何时候只有可配置的行部分被保存在内存中。

请注意,仍然可能会消耗大量内存,这些内存基于您正在使用的功能,例如合并区域,注释。。。仍然只能存储在内存中,因此如果广泛使用,可能需要大量内存。

 

03版本批量写

 /**
     * 操作Microsoft 03版本 写如大数据
     */
    @org.junit.Test
    public void testWrite03BigData(){
        //记录开始的时间:
        long start = System.currentTimeMillis();
        //创建一个新的excel工作簿 基本上什么都没有改变,只是生成工作簿的对象变了
        HSSFWorkbook workbook = new HSSFWorkbook();
        //在excel工作簿中创建一个工作表,其中缺省名字为sheet0
        Sheet sheet = workbook.createSheet("服装统计表");
//xls文件最大支持65536行
        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+1);

            }
        }
        String path = "D:\ideaOldProject\poi-excel\";

        //新建输出流(注意:要先创建文件夹)
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(path + "大数据量写入03版本.xls");
            //把相应的excel 工作簿存盘
            workbook.write(fileOutputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
                System.out.println("文件生成完毕~~");
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        //记录结束的时间:
        long end = System.currentTimeMillis();
        System.out.println("============耗时:"+(double)(end-start)/1000);//除以1000,最后得出来的就是秒
        

    }

  

文件生成完毕~~

============耗时:1.179

 

如果我们想生成65537行:

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

 

 

07版本批量写

/**
 * 操作Microsoft 07版本 写如大数据 对写入的数据量没有限制,只和电脑的配置有关系了。
 */
@org.junit.Test
public void testWrite07BigData() {
    //记录开始的时间:
    long start = System.currentTimeMillis();
    //创建一个新的excel工作簿 基本上什么都没有改变,只是生成工作簿的对象变了
    XSSFWorkbook workbook = new XSSFWorkbook();
    //在excel工作簿中创建一个工作表,其中缺省名字为sheet0
    Sheet sheet = workbook.createSheet("服装统计表");
   //xlsx文件,理论上没有限制
    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 + 1);

        }
    }
    String path = "D:\ideaOldProject\poi-excel\";

    //新建输出流(注意:要先创建文件夹)
    FileOutputStream fileOutputStream = null;
    try {
        fileOutputStream = new FileOutputStream(path + "大数据量写入07版本.xlsx");
        //把相应的excel 工作簿存盘
        workbook.write(fileOutputStream);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (fileOutputStream != null) {
                fileOutputStream.close();
            }
            System.out.println("文件生成完毕~~");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    //记录结束的时间:
    long end = System.currentTimeMillis();
    System.out.println("============耗时:" + (double) (end - start) / 1000);//除以1000,最后得出来的就是秒


}

  

文件生成完毕~~

============耗时:9.705

07升级版批量写

/**
 * 操作Microsoft 07版本 写如大数据 对写入的数据量没有限制,只和电脑的配置有关系了。但是速度方面和03版本的相比慢多了
 * 但是我们可以使用它的升级版本,借助临时文件,就比07版本的快多了
 */
@org.junit.Test
public void testWrite07BigDataSuper() {
    //记录开始的时间:
    long start = System.currentTimeMillis();
    //创建一个新的excel工作簿 基本上什么都没有改变,只是生成工作簿的对象变了
    SXSSFWorkbook workbook = new SXSSFWorkbook();
    //在excel工作簿中创建一个工作表,其中缺省名字为sheet0
    Sheet sheet = workbook.createSheet("服装统计表");
    //xlsx文件,理论上没有限制
    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 + 1);

        }
    }
    String path = "D:\ideaOldProject\poi-excel\";

    //新建输出流(注意:要先创建文件夹)
    FileOutputStream fileOutputStream = null;
    try {
        fileOutputStream = new FileOutputStream(path + "大数据量写入07升级版本.xlsx");
        //把相应的excel 工作簿存盘
        workbook.write(fileOutputStream);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (fileOutputStream != null) {
                fileOutputStream.close();
            }
            System.out.println("文件生成完毕~~");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    //文件生成完毕的时候,将产生的临时文件删除掉
    ((SXSSFWorkbook)workbook).dispose();
    //记录结束的时间:
    long end = System.currentTimeMillis();
    System.out.println("============耗时:" + (double) (end - start) / 1000);//除以1000,最后得出来的就是秒


}

  

文件生成完毕~~

============耗时:2.428

读操作:

03版本

/**
 * Microsoft 03版本的数据读操作
 */
@org.junit.Test
public void testRead03() throws IOException {
    String path = "D:\ideaOldProject\poi-excel\";
    InputStream inputStream=null;
    try {
        inputStream=  new FileInputStream(path+ "丫丫丫统计表03版本.xls");
        HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
        HSSFSheet sheet = workbook.getSheetAt(0);//这是一种使用下标的方式,当然也可以通过名字来进行获取
        //读取第一行第一列
        Row row = sheet.getRow(0);
        Cell cell = row.getCell(0);
        String cellValue = cell.getStringCellValue();
        System.out.println("=========单元格的内容:"+cellValue);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }finally {
        if(inputStream!=null){
            inputStream.close();

        }
    }
}

  

=========单元格的内容:今日新增关注

07版本

/**
 * Microsoft 07版本的数据读操作
 */
@org.junit.Test
public void testRead07() throws IOException {
    String path = "D:\ideaOldProject\poi-excel\";
    InputStream inputStream=null;
    try {
        inputStream=  new FileInputStream(path+ "服装销售统计.xlsx");
        XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
        Sheet sheet = workbook.getSheetAt(0);//这是一种使用下标的方式,当然也可以通过名字来进行获取
        //读取第一行第一列
        Row row = sheet.getRow(0);
        Cell cell = row.getCell(0);
        String cellValue = cell.getStringCellValue();
        System.out.println("=========单元格的内容:"+cellValue);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }finally {
        if(inputStream!=null){
            inputStream.close();

        }
    }
}

  

=========单元格的内容:服装品牌

读取excel文件中的不同类型:

这里以03版本的excel为例

 /**
     * 批量的读取excel文件中的数据
     * Microsoft 03版本
     */
    @org.junit.Test
    public void testReadBigData03(){
        String path = "D:\ideaOldProject\poi-excel\";
        InputStream inputStream=null;
        try {
            inputStream=new FileInputStream(path+"会员消费商品明细表.xls");
            HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
            //获取第一个sheet页中的内容
            HSSFSheet sheet = workbook.getSheetAt(0);
            //首先,读取标题的内容
            Row rowTitle = sheet.getRow(0);
            //在实际的项目开发中一定要判断为空
            if(rowTitle!=null){
                //求得这个行中一共有多少个非空的列
                int cellCount = rowTitle.getPhysicalNumberOfCells();
                for (int i = 0; i <cellCount ; i++) {
                    Cell cell = rowTitle.getCell(i);
                    if(cell!=null){
                        int type = cell.getCellType();//获取该单元格的类型
                        String value = cell.getStringCellValue();//获取单元格的值,一般情况下,标题单元格的值都是String类型的,这里是不用进行类型判断的额
                        System.out.print(value+"|");
                    }
                }

            }
            System.out.println("");//加上一个换行
            //读取商品列表中的数据
            int rowCount = sheet.getPhysicalNumberOfRows();//求得这个sheet页中一共有多少个非空的行
            //循环是从1开始的,因为0表示的是标题行
            for (int i = 1; i <rowCount ; i++) {
                Row rowData = sheet.getRow(i);
                if(rowData!=null){
                    //读取cell格子中的内容
                    int cellCount = rowData.getPhysicalNumberOfCells();//得到这个行中一共有多少个格子,也就是列
                     System.out.print("["+(i+1)+"-"+(cellCount)+"]");
                    for (int j = 0; j <cellCount ; j++) {

                        Cell cell = rowData.getCell(j);
                        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]");
//                                    cellValue= cell.getStringCellValue();
                                    break;
                                case HSSFCell.CELL_TYPE_NUMERIC://数值类型
                                    //数值类型,可能是日期类型,当然也可能是正常的数值类型,这里需要进行判断
                                    if (HSSFDateUtil.isCellDateFormatted(cell)){//如果是日期类型
                                        System.out.print("[DATE]");
                                        Date date = cell.getDateCellValue();
                                        cellValue = new DateTime(date).toString("yyyy-MM-dd");
                                        break;

                                    }else{//正常的数值类型
                                        System.out.print("[Number]");
                                        cell.setCellValue(HSSFCell.CELL_TYPE_STRING);
                                        double numericCellValue = cell.getNumericCellValue();
                                        cellValue = String.valueOf(numericCellValue);
                                        break;

                                    }
                                case HSSFCell.CELL_TYPE_ERROR://如果是一个错误
                                    System.out.print("[ERROR]");
//                                    cellValue= cell.getStringCellValue();
                                    break;

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

                    }

                }
                System.out.println();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(inputStream!=null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }

    }

  

运行结果:

序号|卡号|持卡人|手机号|消费日期|小票号|商品编号|商品条码|商品名称|商品单位|原价|销售价|销售数量|销售金额|优惠金额|是否上架|

[2-16][STRING]1 [STRING]100088 [STRING]爱丽丝 [STRING]12333333333 [DATE]2020-04-21 [STRING]0000201510200146 [STRING]PV700012 [STRING]PV700012 [STRING]蒙牛 [STRING]瓶 [Number]1.0 [Number]1.0 [STRING]1.0 [Number]1.0 [Number]1.0 [BOOLEAN]true

[3-16][STRING]2 [Number]1.0 [STRING]丫丫丫 [STRING]12333333333 [DATE]2020-04-21 [STRING]0000201510200146 [STRING]PV700006 [STRING]PV700006 [STRING]老白金 [STRING]盒 [Number]1.0 [Number]1.0 [STRING]1.0 [Number]1.0 [BLANK] [BOOLEAN]false

读取excel中的公式:

@org.junit.Test
public void  testFormula(){
    //首先,读取文件
    String path = "D:\ideaOldProject\poi-excel\";
    InputStream inputStream=null;
    try {
        inputStream=new FileInputStream(path+"计算公式.xls");
        HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
        //获取第一个sheet页中的内容
        HSSFSheet sheet = workbook.getSheetAt(0);
        //首先,读取标题的内容
        Row row = sheet.getRow(4);
        Cell cell = row.getCell(0);
        //公式计算器
        FormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook)workbook);
        //输出单元格内容
        int cellType = cell.getCellType();

        switch (cellType){
            case Cell.CELL_TYPE_FORMULA:
                //得到公式
                String formula = cell.getCellFormula();
                System.out.println("======公式:"+formula);
                CellValue evaluate = formulaEvaluator.evaluate(cell);
                String cellValue = evaluate.formatAsString();
                System.out.println("======单元格的值:"+cellValue);
                break;
        }

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        if(inputStream!=null){
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

}

  

 

运行结果:

======公式:SUM(A2:A4)

======单元格的值:600.0

原文地址:https://www.cnblogs.com/dongyaotou/p/13943727.html