栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

【开发指南】Spring Cloud集成POI完成Excel读写操作

【开发指南】Spring Cloud集成POI完成Excel读写操作

POI简介

Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft office格式档案读和写的功能,其中包括Excel,Word,PowerPoint等。

官方网站:poi.apache.org/

POI前置知识 1. 坐标

Excel中每一个单元格都是有一个坐标的,起始坐标为(0,0),也就是说起始行为第0行,起始列为第0列。

Excel中每一个Sheet也是有下标的,从0开始。

2. 数据类型

POI中定义了6种单元格数据类型,每一个数据类型使用一个数字常量来表示:

  • CELL_TYPE_NUMERIC:值是0,数字类型和日期类型(int,float,Date...)
  • CELL_TYPE_STRING:值是1,字符串类型(String)
  • CELL_TYPE_FORMULA:值是2,计算公式类型
  • CELL_TYPE_BLANK:值是3,空类型,表示单元格里什么都没有(null)
  • CELL_TYPE_BOOLEAN:值是4,布尔类型(boolean)
  • CELL_TYPE_ERROR:值是5,类型错误

存储在Excel中最常见的莫过于字符数据和数值数据了:

  • 字符数据类似于"abc"、"ab123"等,POI默认以CELL_TYPE_STRING类型存储,通过POI转成Java中的类型是String。

  • 数值和日期数据类似于"123"、"2021/12/8"(将日期使用特定算法计算成数字)等,POI默认以CELL_TYPE_NUMERIC类型存储,通过POI转成Java中的类型是double。

    如果Excel需要存储类似于手机号这样的数据,默认是CELL_TYPE_NUMERIC类型,但是可以自行修改类型为CELL_TYPE_STRING。

  • 布尔数据类似于"TRUE"、"true",POI默认以CELL_TYPE_BOOLEAN类型存储,通过POI转成Java中的类型是boolean。

3. 文件类型

Excel经历了两次大变革,就是在Excel 2003和Excel 2007。

在Excel 2003之前,只支持后缀为 .xls 的文件,而Excel 2007之后支持了后缀为 .xls 和 .xlsx 两种后缀的文件。

因此POI针对 .xls 和 .xlsx 两种文件分别提供了两套独立的读写接口,分别是HSSF和XSSF。

4. 前置工作

在xml文件中导入依赖:


    org.apache.poi
    poi
    3.9



    org.apache.poi
    poi-ooxml
    3.9

复制代码
Excel基础读写 1. HSSF

1.1 写操作

@Test
public void testHSSFWrite() throws IOException {
    // 创建文件
    Workbook workbook = new HSSFWorkbook();
    // 创建Sheet
    Sheet sheet = workbook.createSheet("sheet1");
    // 创建第0行
    Row row = sheet.createRow(0);
    // 在第0行上创建第0个单元格
    Cell cell = row.createCell(0);
    // 在(0,0)处写入内容
    cell.setCellValue("Hello POI");

    // 写入
    FileOutputStream outputStream = new FileOutputStream("G:\file\poi\hssf-write.xls");
    workbook.write(outputStream);

    // 关闭输出流
    outputStream.close();
}
复制代码

1.2 读操作

@Test
public void testHSSFRead() throws IOException {
    FileInputStream inputStream = new FileInputStream("G:\file\poi\hssf-read.xls");

    Workbook workbook = new HSSFWorkbook(inputStream);
    Sheet sheet = workbook.getSheetAt(0);
    Row row = sheet.getRow(0);
    Cell cell = row.getCell(0);

    // 读出(0,0)处的字符内容
    String content = cell.getStringCellValue();
    System.out.println(content);

    inputStream.close();
}
复制代码
2. XSSF

2.1 写操作

@Test
public void testXSSFWrite() throws IOException {
    // 创建工作簿
    Workbook workbook = new XSSFWorkbook();
    // 创建Sheet
    Sheet sheet = workbook.createSheet("sheet1");
    // 创建第0行
    Row row = sheet.createRow(0);
    // 在第0行上创建第0个单元格
    Cell cell = row.createCell(0);
    // 在(0,0)处写入内容
    cell.setCellValue("Hello POI");

    // 写入
    FileOutputStream outputStream = new FileOutputStream("G:\file\poi\xssf-write.xlsx");
    workbook.write(outputStream);

    // 关闭输出流
    outputStream.close();
}
复制代码

2.2 读操作

@Test
public void testXSSFRead() throws IOException {
    FileInputStream inputStream = new FileInputStream("G:\file\poi\xssf-read.xlsx");

    Workbook workbook = new XSSFWorkbook(inputStream);
    Sheet sheet = workbook.getSheetAt(0);
    Row row = sheet.getRow(0);
    Cell cell = row.getCell(0);

    // 读出(0,0)处的字符内容
    String content = cell.getStringCellValue();
    System.out.println(content);

    inputStream.close();
}
复制代码
Excel大数据读写

使用HSSF一次最多只能读写65535行记录(列不限),如果超过65535行,则无法读写。

使用XSSF一次最多能读写1048576行和16384列记录,理论上可以读写大数据,但是速度会非常慢,时间不可控,还可能会造成内存溢出。原因是只要没有读写结束,数据就会一直存储在内存中,无论该数据是否已经持久化,这样以来如果是大数据场景,就会造成内存溢出。

因此POI针对大数据提供了一套专门的读写接口,SXSSF,SXSSF只支持后缀为 .xlsx 文件。

1. 读操作
@Test
public void testHSSFWrite() throws IOException {
    // 创建工作簿
    SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook();
    // 创建Sheet
    Sheet sheet = sxssfWorkbook.createSheet("sheet1");
    // 创建第0行
    Row row = sheet.createRow(0);
    // 在第0行上创建第0个单元格
    Cell cell = row.createCell(0);
    // 在(0,0)处写入内容
    cell.setCellValue("Hello POI");

    // 写入
    FileOutputStream outputStream = new FileOutputStream("G:\file\poi\sxssf-write.xlsx");
    sxssfWorkbook.write(outputStream);

    // 清除内存中临时文件
    sxssfWorkbook.dispose();

    // 关闭输出流
    outputStream.close();
}
复制代码
2. 写操作
@Test
public void testSXSSFRead() throws IOException {
    FileInputStream inputStream = new FileInputStream("G:\file\poi\sxssf-read.xlsx");

    XSSFWorkbook xssfWorkbook = new XSSFWorkbook(inputStream);
    // 内存窗口大小为1000,表示能从Sheet窗口最多看到1000跳新创建的数据
    SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(xssfWorkbook, 1000);

    Sheet sheet = xssfWorkbook.getSheetAt(0);
    Row row = sheet.getRow(0);
    Cell cell = row.getCell(0);

    // 读出(0,0)处的字符内容
    String content = cell.getStringCellValue();
    System.out.println(content);

    inputStream.close();
}
复制代码
POI实战

将文件名为student-grade.xlsx的Excel表中的数据全部读入到程序中。

  1. xml文件中引入POI依赖

    
        org.apache.poi
        poi
        3.14
    
    
        org.apache.poi
        poi-ooxml
        3.14
    
    复制代码
  2. 自定义单元类型异常CellTypeException

  3. 在ResultCode中建立单元类型异常枚举对象

  4. 将单元类型异常配置进全局异常

  5. 创建存储读入数据的对象

    @Data
    public class Student {
    
        private String university;
    
        private String studentId;
    
        private String name;
    
        private Integer score;
    
        private Integer credit;
    
        private Date gmtCreate;
    
    }
    复制代码
  6. 创建POIUtils

    public class POIUtils {
    
        
        public static Object getCellValue(XSSFCell cell) {
            Object value = null;
    
            if (cell != null) {
                // 获取cell类型
                int type = cell.getCellType();
                // Numeric类型
                if (type == XSSFCell.CELL_TYPE_NUMERIC) {
                    // 判断是日期类型还是数值类型
                    if (HSSFDateUtil.isCellDateFormatted(cell)) {
                        value = cell.getDateCellValue();
                    } else {
                        value = cell.getNumericCellValue();
                    }
                }
                // String类型
                else if (type == XSSFCell.CELL_TYPE_STRING) {
                    value = cell.getStringCellValue();
                }
                // Boolean类型
                else if (type == XSSFCell.CELL_TYPE_BOOLEAN) {
                    value = cell.getBooleanCellValue();
                }
                // Error类型
                else if (type == XSSFCell.CELL_TYPE_ERROR) {
                    throw new CellTypeException(ResultCode.CELL_TYPE_ERROR);
                }
            }
    
            return value;
        }
    
        
        public static String getStringValue(XSSFCell cell) {
            return (String) getCellValue(cell);
        }
    
        
        public static String getDouble2StringValue(XSSFCell cell) {
            // 将科学计数法表示的double数据四舍五入成整形数据
            BigDecimal bigDecimal = BigDecimal.valueOf((Double) getCellValue(cell)).setScale(0, BigDecimal.ROUND_DOWN);
    
            return bigDecimal.toString();
        }
    
        
        public static Integer getDouble2IntegerValue(XSSFCell cell) {
            // 将double数据四舍五入成整形数据
            return (int) Math.round((double) getCellValue(cell));
        }
    
        
        public static Date getDatevalue(XSSFCell cell) {
            return (Date) getCellValue(cell);
        }
    
        
        public static void setStudentProperty(int columnIndex, XSSFCell cell, Student student) {
            if (columnIndex == 0) {
                student.setUniversity(getStringValue(cell));
            } else if (columnIndex == 1) {
                student.setStudentId(getDouble2StringValue(cell));
            } else if (columnIndex == 2) {
                student.setName(getStringValue(cell));
            } else if (columnIndex == 3) {
                student.setScore(getDouble2IntegerValue(cell));
            } else if (columnIndex == 4) {
                student.setCredit(getDouble2IntegerValue(cell));
            } else {
                student.setGmtCreate(getDatevalue(cell));
            }
        }
    
    }
    复制代码

    工具类中除了第一个方法固定不变外,其他方法都需要视具体要导入的数据而定。

    比如现在需要导入student-grade.xlsx中的数据,在其每一行数据中,学校、姓名字段数据使用getStringValue方法接收,学号字段数据使用getDouble2StringValue方法接收,成绩、学分字段数据使用getDouble2IntegerValue方法接收,上传日期使用getDatevalue方法接收,接收到数据之后需要使用setStudentProperty方法装配到PO中来持久化到数据库。

  7. 创建读操作方法

    @Test
    public void read() throws IOException {
        FileInputStream inputStream = new FileInputStream("G:\file\student-grade.xlsx");
    
        XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
        XSSFSheet sheet = workbook.getSheetAt(0);
    
        // 获取行数
        int rowCount = sheet.getPhysicalNumberOfRows();
        for (int i = 1; i < rowCount; i ++) {
            XSSFRow row = sheet.getRow(i);
    
            Student student = new Student();
            // 获取列数
            int cellCount = row.getPhysicalNumberOfCells();
            for (int j = 0; j < cellCount; j ++) {
                XSSFCell cell = row.getCell(j);
                // 装载数据
                POIUtils.setStudentProperty(j, cell, student);
            }
    
       		// 将student持久化到数据库
        }
    
        inputStream.close();
    }

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/653925.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号