POI及EasyExcel学习笔记

前言:学习B站Up主狂神说,视频笔记整理视频链接

POI

常用信息

1、将用户信息导出为excel表格(导出数据…)
2、将Excel表中的信息录入到网站数据库(习题上传…)
开发中经常会设计到excel的处理,如导出Excel,导入Excel到数据库中!操作Excel目前比较流行的就是Apache POI和阿里巴巴的easyExcel !

什么是POI

在这里插入图片描述
在这里插入图片描述

Excel03与Excel07区别

Excel03行数最多只能到65536

Excel03后缀xlx
Excel07后缀xlsx
在这里插入图片描述

快速上手

导入依赖

 <!-- 03版 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>

        <!-- 07版 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>

<!-- 日期格式化工具 -->
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.10.10</version>
        </dependency>

文件写出

测试03版本Excel写出

   private String PATH="D:\\Wordspase\\POI-EasyExcelStudy\\";

    @Test
    public void testWrite03() throws Exception {
    
    
        //创建工作簿
        HSSFWorkbook workbook = new HSSFWorkbook();//03版本工作簿

        //工作表
        HSSFSheet sheet = workbook.createSheet("员工统计表"); //工作表名


        //创建一行
        Row row1 = sheet.createRow(0);//一行

        //单元格
        Cell cell = row1.createCell(0);// 坐标(1,1)
        cell.setCellValue("员工总数");

        //(1,2)
        Cell cell1 = row1.createCell(1);
        cell1.setCellValue(666);

        //第二行
        Row row = sheet.createRow(1);
        Cell ce1ll = row.createCell(0);
        ce1ll.setCellValue("统计时间");
        Cell cell2 = row.createCell(1);
        String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
        cell2.setCellValue(time);

        //生成表(IO流) 03版本就是使用xls结尾
        FileOutputStream outputStream = new FileOutputStream(PATH + "员工统计表03.xls");
        //输出
        workbook.write(outputStream);

        //关闭流
        outputStream.close();

        System.out.println("生成完毕");

测试07版本Excel写出

  private String PATH="D:\\Wordspase\\POI-EasyExcelStudy\\";

    @Test
    public void testWrite03() throws Exception {
    
    
        //创建工作簿
        Workbook workbook = new XSSFWorkbook();//07版本工作簿

        //工作表
        Sheet sheet = workbook.createSheet("员工统计表"); //工作表名


        //创建一行
        Row row1 = sheet.createRow(0);//一行

        //单元格
        Cell cell = row1.createCell(0);// 坐标(1,1)
        cell.setCellValue("员工总数");

        //(1,2)
        Cell cell1 = row1.createCell(1);
        cell1.setCellValue(666);

        //第二行
        Row row = sheet.createRow(1);
        Cell ce1ll = row.createCell(0);
        ce1ll.setCellValue("统计时间");
        Cell cell2 = row.createCell(1);
        String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
        cell2.setCellValue(time);

        //生成表(IO流) xlsx
        FileOutputStream outputStream = new FileOutputStream(PATH + "员工统计表07.xlsx");
        //输出
        workbook.write(outputStream);

        //关闭流
        outputStream.close();

        System.out.println("生成完毕");

    }

大文件写出说明

大文件写HSSF

缺点︰最多只能处理65536行,否则会抛出异常
优点: 内存中 速度较快

大文件写出XSSF

缺点:速度较慢
优点:可以写出比较大的数据

优化XSSF写出慢问题

优点:可以写非常大的数据量,如100万条甚至更多条,写数据速度快,占用更少的内存
注意:
过程中会产生临时文件,需要湾理临时文件
默认由100条记录被保存在内存中,如果超过这数量,则最前面的数据被写入临时文件如果想自定义内存中数据的数量,可以住用new SXSSFWarkbook(数量)

在这里插入图片描述

   private String PATH="D:\\Wordspase\\POI-EasyExcelStudy\\";
    @Test
    public void testWrite07BigDates() throws Exception {
    
    
        //创建工作簿
        Workbook workbook = new SXSSFWorkbook();
        //工作表
        Sheet sheet = workbook.createSheet("员工统计表"); //工作表名
        for (int rowNum =0;rowNum<100000;rowNum++){
    
    
            Row row = sheet.createRow(rowNum);
            for (int cellrow =0;cellrow<10;cellrow++){
    
    
                Cell cell = row.createCell(cellrow);
                cell.setCellValue(cellrow);
            }
        }
        //生成表(IO流) xlsx
        FileOutputStream outputStream = new FileOutputStream(PATH + "员工统计表07dates.xlsx");
        //输出
        workbook.write(outputStream);
        //清除临时文件
        ((SXSSFWorkbook) workbook).dispose();

        //关闭流
        outputStream.close();

        System.out.println("生成完毕");

    }

文件读取

03版本文件读取

  private String PATH="D:\\Wordspase\\POI-EasyExcelStudy\\";
    
    @Test
    public void testRead03() throws Exception {
    
    
        //获取文件流
        FileInputStream inputStream = new FileInputStream(PATH + "员工统计表03.xls");

        //创建表
        HSSFWorkbook sheets = new HSSFWorkbook(inputStream);

        //得到工作簿
        HSSFSheet sheetAt = sheets.getSheetAt(0);//第0
        //得到行
        HSSFRow row = sheetAt.getRow(0);
        //得到列
        HSSFCell cell = row.getCell(1);

        //得到值 字符串类型
       // String value = cell.getStringCellValue();
        
        //cell.getNumericCellValue() 浮点数类型
        System.out.println(cell.getNumericCellValue());

        //关闭流
        inputStream.close();
    }

获取值的时候一定要注意Excel中的数据类型 否则会报类型异常
在这里插入图片描述

07版本文件读取

 @Test
    public void testRead07() throws Exception {
    
    
        //获取文件流
        FileInputStream inputStream = new FileInputStream(PATH + "员工统计表07.xlsx");

        //创建表 07表
        Workbook sheets = new XSSFWorkbook(inputStream);

        //得到工作簿
        Sheet sheetAt = sheets.getSheetAt(0);//第0
        //得到行
        Row row = sheetAt.getRow(0);
        //得到列
        Cell cell = row.getCell(1);

        //得到值 字符串类型
        // String value = cell.getStringCellValue();

        //cell.getNumericCellValue() 浮点数类型
        System.out.println(cell.getNumericCellValue());

        //关闭流
        inputStream.close();
    }

批量文件读取

我们使用这张03表进行测试
在这里插入图片描述

   @Test
    public void testRead03date() throws Exception {
    
    
        //获取文件流
        FileInputStream inputStream = new FileInputStream(PATH + "员工表.xls");

        //创建表
        Workbook sheets = new HSSFWorkbook(inputStream);


        //得到工作簿
        Sheet sheetAt = sheets.getSheetAt(0);//第0

        //得到行
        Row rowTitle = sheetAt.getRow(0);

        if (rowTitle!=null){
    
    
            //获取列数
            int cellCount = rowTitle.getPhysicalNumberOfCells();

            for (int cellNum=0;cellNum<cellCount;cellNum++){
    
    
                Cell cell = rowTitle.getCell(cellNum);
                if (cell!=null){
    
    
                    int type = cell.getCellType();//获取类型
                    String cellValue = cell.getStringCellValue();
                    System.out.print(cellValue+"|");
                }
            }
        }

        //获取表中的内容
        int rowNumber = sheetAt.getPhysicalNumberOfRows();//获取所有行数
        for (int rowNum = 1;rowNum<rowNumber;rowNum++){
    
    
            Row rowDate = sheetAt.getRow(rowNum);
            if (rowDate!=null){
    
    
                int cellCount = rowDate.getPhysicalNumberOfCells(); //获取列数
                for (int cellNum=0;cellNum<cellCount;cellNum++){
    
    
                    Cell cell = rowDate.getCell(cellNum);//取出单元格
                    if (cell!=null){
    
    
                        int type = cell.getCellType();//获取类型

                        String cellValue = "";
                        //匹配数据类型
                        switch (type){
    
    
                            case HSSFCell.CELL_TYPE_STRING: //字符串
                                System.out.println("[String]");
                                cellValue = cell.getStringCellValue();
                                break;
                            case HSSFCell.CELL_TYPE_BOOLEAN: //布尔
                                System.out.println("[BOOLEAN]");
                                cellValue = String.valueOf(cell.getBooleanCellValue());
                                break;
                            case HSSFCell.CELL_TYPE_BLANK: //空
                                System.out.println("[BLANK:]");
                                break;
                            case HSSFCell.CELL_TYPE_NUMERIC: //数字(日期,普通数字)
                                System.out.println("[NUMERIC:]");
                                if (HSSFDateUtil.isCellDateFormatted(cell)){
    
    //日期
                                    Date date = cell.getDateCellValue();
                                    cellValue = new DateTime(date).toString("yyyy-MM-ss");
                                }else {
    
     //如果不是日期格式 防止数字过长
                                    System.out.println("转换成字符串输出");
                                    cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                                    cellValue = cell.toString();
                                }
                                break;
                            case HSSFCell.CELL_TYPE_ERROR: //数据类型错误
                                System.out.println("[ERROR]");
                                break;
                        }
                        System.out.println(cellValue);
                    }
                }
            }
        }

        inputStream.close();
    }

POI实战-Excel模板下载-导入-导出

controller

@Controller
@RequestMapping("/file")
public class FileController {
    
    

    //模板存放位置
    private String PATH = "D:\\Wordspase\\employee-Information\\";

    @Autowired
    private FileService fileService;

    //下载模板
    @ResponseBody
    @RequestMapping("/downloadTemplate")
    public void downloadTemplate(HttpServletResponse response){
    
    
        OutputStream out = null;
        InputStream in = null;
        String fileName= "员工表.xls";
        try {
    
    
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-Disposition","attachment; filename=" + new String(fileName.getBytes("utf-8"), "ISO_8859_1"));
            File file = new File(PATH + fileName);
            in = new FileInputStream(file);
            out = response.getOutputStream();
            byte[] tmp = new byte[1024];
            while (in.read(tmp) != -1) {
    
    
                out.write(tmp);
            }
            out.flush();
            in.close();
            return ;
        } catch (Exception e) {
    
    
            e.printStackTrace();
            throw new RuntimeException("模板下载失败");
        }
    }

    //批量导入员工信息
    @RequestMapping("/upload")
    public String Fileupload(@RequestParam("file") MultipartFile file, Model model){
    
    
       if (file.getSize()>0) {
    
    
           String i = fileService.insertDBByExcel(file);
           if (i.equals("ok")){
    
    
               return "redirect:/employee/allemployee";
           }
           model.addAttribute("filename",i);
           return "addsEmployee";
       }else {
    
    
           model.addAttribute("filename","上传文件为空");
           return "addsEmployee";
       }
    }

    //批量导出
    @ResponseBody
    @RequestMapping("/employeeExcel")
    public void employeeExcel(HttpServletResponse response){
    
    
        fileService.exportToExcel(response);
    }

}

Service

public interface FileService {
    
    

    //批量导入
    public String insertDBByExcel(MultipartFile file);


    //批量导出
    public void exportToExcel(HttpServletResponse response);

}

serviceImpl

@Service
public class FileServiceImpl implements FileService{
    
    

    @Autowired
    private EmployeeService employeeService;

    //批量导入
    @Override
    public String insertDBByExcel(MultipartFile file) {
    
    
        //获取文件名
        String filename = file.getOriginalFilename();
        filename = filename.toLowerCase();
        if("".equals(filename)){
    
    
            return "文件名为空!";
        }
        System.out.println("上传文件名 : "+filename);
        //正则表达式校验
        if(!filename.matches("^.+\\.(xls)$")) {
    
    
            return "请上传后缀为.xls的文件";
        }

        try {
    
    
            InputStream inputStream = file.getInputStream();

            //创建表
            Workbook sheets = new HSSFWorkbook(inputStream);

            //得到工作簿
            Sheet sheetAt = sheets.getSheetAt(0);//第0

            int rowNumber = sheetAt.getPhysicalNumberOfRows();//得到所有行
            
            for (int rowNum = 1;rowNum<rowNumber;rowNum++){
    
    
                //取出每一行
                Row rowDate = sheetAt.getRow(rowNum);
                if (rowDate != null){
    
    //判断是否为空
                    //取出一行中的列数
                    int cellCount = rowDate.getPhysicalNumberOfCells(); //获取列数
                    //员工表实体类
                    Employee employee = new Employee();
                    for (int cellNum=0;cellNum<cellCount;cellNum++){
    
     //便利所有列
                        
                        Cell cell = rowDate.getCell(cellNum);//取出单元格
                        if (cell!=null) {
    
    //判断单元格是否为空
                            
                            String value = typeValue(cell.getCellType(), cell); //单元格数据类型判断
                            //设置值
                            switch (cellNum){
    
    
                                case 1:
                                    employee.setName(value);
                                    break;
                                case 2:
                                    employee.setSex(value);
                                    break;
                                case 3:
                                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");//注意月份是MM
                                    Date date = simpleDateFormat.parse(value);
                                    employee.setBirth(date);
                                    break;
                                case 4:
                                    employee.setAddress(value);
                                    break;
                                case 5:
                                    employee.setPhone(value);
                                    break;
                                case 6:
                                    employee.setCard(value);
                                    break;
                                case 7:
                                    employee.setDegree(value);
                                    break;
                                case 8:
                                    long pid = Long.valueOf(value).longValue();
                                    employee.setPid(pid);
                                    break;
                            }

                        }
                    }
                    //写入数据库
                    employeeService.addEmployee(employee);
                }
            }

        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return "ok";
    }

    //批量导出
    @Override
    public void exportToExcel(HttpServletResponse response) {
    
    
        ServletOutputStream out = null;
        //创建工作簿
        HSSFWorkbook workbook = new HSSFWorkbook();//03版本工作簿
        //工作表
        Sheet sheet = workbook.createSheet("员工统计表"); //工作表名
        //创建一行
        Row row1 = sheet.createRow(0);
        //设置标题
        row1.createCell(0).setCellValue("编号");
        row1.createCell(1).setCellValue("名字");
        row1.createCell(2).setCellValue("性别");
        row1.createCell(3).setCellValue("出生日期");
        row1.createCell(4).setCellValue("地址");
        row1.createCell(5).setCellValue("手机号");
        row1.createCell(6).setCellValue("身份证号");
        row1.createCell(7).setCellValue("学历");
        row1.createCell(8).setCellValue("职位编号");
        
        //查询全部的员工信息
        List<Employee> list = employeeService.queryEmployee(null);
        for (int rowNum =0;rowNum<list.size();rowNum++) {
    
    
            Row row = sheet.createRow(rowNum+1);
            Employee employee = list.get(rowNum);
            row.createCell(0).setCellValue(employee.getId());
            row.createCell(1).setCellValue(employee.getName());
            row.createCell(2).setCellValue(employee.getSex());
            row.createCell(3).setCellValue(employee.getBirth());
            row.createCell(4).setCellValue(employee.getAddress());
            row.createCell(5).setCellValue(employee.getPhone());
            row.createCell(6).setCellValue(employee.getCard());
            row.createCell(7).setCellValue(employee.getDegree());
            row.createCell(8).setCellValue(employee.getPid());
        }

        // 文件名
        String fileName = new String("员工统计表.xls");
        try {
    
    
            out = response.getOutputStream();
            //获取客户端浏览器类型
            response.setHeader("content-disposition", "attachment; filename=\""
                    + new String(fileName.toString().getBytes("utf-8"),
                    "ISO8859_1") + "\"");
            workbook.write(out);//写出
            out.flush();
            out.close();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }

    }


    //单元格匹配类型
    public String typeValue(int type,Cell cell) {
    
    
        String cellValue = "";
        //匹配数据类型
        switch (type) {
    
    
            case HSSFCell.CELL_TYPE_STRING: //字符串
                cellValue = cell.getStringCellValue();
                break;
            case HSSFCell.CELL_TYPE_BOOLEAN: //布尔
                cellValue = String.valueOf(cell.getBooleanCellValue());
                break;
            case HSSFCell.CELL_TYPE_BLANK: //空
                break;
            case HSSFCell.CELL_TYPE_NUMERIC: //数字(日期,普通数字)
                if (HSSFDateUtil.isCellDateFormatted(cell)) {
    
    //日期
                    Date date = cell.getDateCellValue();
                    cellValue = new DateTime(date).toString("yyyy-MM-ss");
                } else {
    
     //如果不是日期格式 防止数字过长
                    cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                    cellValue = cell.toString();
                }
                break;
            case HSSFCell.CELL_TYPE_ERROR: //数据类型错误
                break;
        }
        return cellValue;
    }
}

EasyExcel

什么是EasyExcel

easyexcel 是一个 JAVA 解析 Excel 工具。Java 解析、生成 Excel 比较有名的框架有 Apache poi、jxl 。但他们都存在一个严重的问题就是 非常的耗内存,poi 有一套 SAX 模式的 API 可以一定程度的解决一些内存溢出的问题,但 POI 还是有一些缺陷,比如 07 版 Excel 解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel 重写了 poi 对 07 版 Excel 的解析,能够原本一个 3M 的 excel 用 POI sax 依然需要 100M 左右内存降低到 KB 级别,并且再大的 excel 不会出现内存溢出,03 版依赖 POI 的 sax 模式。在上层做了模型转换的封装,让使用者更加简单方便。

EasyExcel读取文件的方式

在这里插入图片描述
POI读取文件: 100W==>加载到内存中==>全部写入 (可能会引发OOW)
EasyExcel读取文件: 磁盘 一行一行的返回

快速上手

参考文档:https://www.yuque.com/easyexcel/doc/easyexcel文档

猜你喜欢

转载自blog.csdn.net/weixin_46684099/article/details/117873421