POI与easyExcel操作Excel随笔

一、POI与easyExcel的介绍

1.1、POI

POI是Apache下开源、目前比较流行的java操作office的api,对于操作excel,提供了操作03版本及其以前版本(.xls)和07版本及以后版本(.xlsx)的两个接口,其中处理03版的速度会快于07版。

excel 03版与07版的区别在于,03版最多只有65535行数据,07版则没有上限

1.2、easyExcel

easyExcel是阿里巴巴下在POI的基础上二次开发的开源api,以使用简单、节省内存著称。(官方文档写的已经非常详细了,就不再这做过多代码的演示)

POI与easyExcel操作Excel随笔_第1张图片
1.3、区别

POI与easyExcel的区别主要在内存消耗上。

  • POI由于在操作excel时是先将所有数据都读入内存后,再写入文件,比较消耗内存,特别是大数据量时,容易出现OOM

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

二、POI实战入门

2.1、案例准备
2.1.1、导入依赖

    
    
        org.apache.poi
        poi
        3.9
    
    
    
        org.apache.poi
        poi-ooxml
        3.9
    

    
    
        junit
        junit
        4.12
    
    
        org.projectlombok
        lombok
        1.18.20
    
2.1.2、构建实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    //学号
    private Integer stuNo;
    //姓名
    private String name;
    //生日
    private Date birthday;
    //体重
    private Double weight;
    //模拟通过数据库获取数据
    public static List getStudentList() throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        List students = new LinkedList<>();
        students.add(new Student(1,"张三",sdf.parse("1999/8/5"),65.5));
        students.add(new Student(2,"李四",sdf.parse("2000/2/8"),60.3));
        return students;
    }
}
2.2、编写代码
2.2.1、导出excel

流程:创建工作簿>创建工作表sheet>创建行>创建列>设值>写出文件

注意:03版与07版代码区别在

(1) 创建工作簿实例化对象不同
(2) 文件名后缀不同
(3) 大数据情况下,03版数据量超出65535行会报错,07版可能会出现内存溢出、速度较03版慢
(4) 使用SXSSFWorkbook可提升07版的速度,但要注意清除生成的临时文件
//全局静态变量之后代码不在注明
private static String PATH = "F:\\mavenProject\\excel_POI\\";
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");

@Test
public void testWrite() throws Exception{
    List students = Student.getStudentList();
    //1、创建一个工作簿
    //03版
    //Workbook workbook = new HSSFWorkbook(); 
    //07版 
    Workbook workbook = new XSSFWorkbook();
    //07加速版,可加速07的操作,但要注意清除临时文件
    //Workbook workbook = new SXSSFWorkbook();
    //2、创建一个工作表sheet,命名为"模板表"
    Sheet sheet = workbook.createSheet("模板表");
    //3、创建表头
    //3.1、创建第一行
    Row row1 = sheet.createRow(0);
    //3.2、在第一行中创建第1~4列并设值
    row1.createCell(0).setCellValue("序号");
    row1.createCell(1).setCellValue("姓名");
    row1.createCell(2).setCellValue("生日");
    row1.createCell(3).setCellValue("体重");
    //4、创建表格内容
    for (int i = 0; i < students.size(); i++) {
        Student student = students.get(i);
        Row row = sheet.createRow(i + 1);
        row.createCell(0).setCellValue(student.getStuNo());
        row.createCell(1).setCellValue(student.getName());
        row.createCell(2).setCellValue(sdf.format(student.getBirthday()));
        row.createCell(3).setCellValue(student.getWeight());
    }
    //03版
    //FileOutputStream fileOutputStream = new FileOutputStream(PATH + "模板表.xls");
    //07版
    FileOutputStream fileOutputStream = new FileOutputStream(PATH + "模板表.xlsx");
    //5、写出excel
    workbook.write(fileOutputStream);
    //关闭流
    fileOutputStream.close();
    //使用SXSSFWorkbook时, 需要清除临时文件
    //((SXSSFWorkbook) workbook).dispose();
    System.out.println("excel导出完毕");
}

HSSFWorkbook补充:

优点:可以写非常大的数据量,如 100 万条甚至更多条,写数据速度更快,占用更少内存
注意:
1、过程中会产生临时文件,需要清理临时文件
2、默认由 100 条记录被保存在内存中,如果超过这数量,则最前面的数据被写入临时文件
3、可以使用 new SXSSFWorkbook(数量)自定义内存中的数量
4、仍然可能会消耗较大的内存

2.2.2、导入excel
@Test
public void testRead() throws Exception {
    FileInputStream fileInputStream = new FileInputStream(PATH + "模板表.xlsx");
    //1、创建一个工作簿,将流放入其中
    Workbook workbook = new XSSFWorkbook(fileInputStream);
    //2、获取第一个表sheet
    Sheet sheet = workbook.cloneSheet(0);
    //3、获取表头
    Row rowTitle = sheet.getRow(0);
    if (rowTitle != null) {
        //获取行的总列数
        int cellCount = rowTitle.getPhysicalNumberOfCells();
        for (int cellIndex = 0; cellIndex < cellCount; cellIndex++) {
            //获取行的每个列
            Cell cell = rowTitle.getCell(cellIndex);
            if (cell != null) {
                //获取值,由于表头都是字符串,就不用进行类型判断
                String cellValue = cell.getStringCellValue();
                System.out.print(cellValue + "、");
            }
        }
        System.out.println();
    }
    //获取表格内容
    //获取表格的行总数
    int totalRows = sheet.getPhysicalNumberOfRows();
    //从第二行开始遍历
    for (int rowIndex = 1; rowIndex < totalRows; rowIndex++) {
        //获取每一行
        Row row = sheet.getRow(rowIndex);
        if (row != null) {
            int totalCells = row.getPhysicalNumberOfCells();
            for (int cellIndex = 0; cellIndex < totalCells; cellIndex++) {
                //获取每一列
                Cell cell = row.getCell(cellIndex);
                if (cell != null) {
                    //获取值的数据类型
                    int cellType = cell.getCellType();
                    String cellValue = "";
                    switch (cellType) {
                        case Cell.CELL_TYPE_STRING:    // 字符串
                            System.out.print("【String】");
                            cellValue = cell.getStringCellValue();
                            break;
                        case Cell.CELL_TYPE_BOOLEAN:    // 布尔类型
                            System.out.print("【Boolean】");
                            cellValue = String.valueOf(cell.getBooleanCellValue());
                            break;
                        case Cell.CELL_TYPE_BLANK:    // 为空
                            System.out.print("【Blank】");
                            break;
                        case Cell.CELL_TYPE_NUMERIC:    // 数字(日期、普通数字)类型
                            System.out.print("【Numeric】");
                            // 判断当前列是不是时间日期
                            if (HSSFDateUtil.isCellDateFormatted(cell)) {
                                System.out.print("【日期】");
                                Date date = cell.getDateCellValue();
                                cellValue = new DateTime(date).toString("yyyy-MM-dd");
                            } else {
                                // 不是日期格式,防止数字过长
                                System.out.print("【转换为字符串输出】");
                                cell.setCellType(Cell.CELL_TYPE_STRING);
                                cellValue = cell.toString();
                            }
                            break;
                        case Cell.CELL_TYPE_ERROR:    // 布尔类型
                            System.out.print("【数据类型错误】");
                            cellValue = String.valueOf(cell.getErrorCellValue());
                            break;
                        case Cell.CELL_TYPE_FORMULA:  // 公式类型,代表这个cell存的是一个公式
                            System.out.print("【公式】");
                            // 6、获取计算公式
                            FormulaEvaluator formulaEvaluator = new XSSFFormulaEvaluator((XSSFWorkbook) workbook);
                            // 8、得到第 5 行第 1 列       计算公式的内容
                            String formula = cell.getCellFormula();
                            // formula = SUM(A2:A4)
                            System.out.println("formula = " + formula);
                            // 9、计算得到值  把获取到第 5 行,第 1 列的内容放入到
                            CellValue evaluate = formulaEvaluator.evaluate(cell);
                            // 10、将的到的内容转化为字符串
                            cellValue = evaluate.formatAsString();
                            break;
                    }
                    System.out.println(cellValue);
                }
            }
        }
        fileInputStream.close();
    }
}

你可能感兴趣的:(java,excel,java,开发语言)