前言:前段时间,写了一个导出Excel的业务需求,在网上找了一些资料,发现坑挺多的。记录一下自己遇到的问题,以及目前(2021年)市面上的api,快速完成这个业务需求。

本文你可以学到:

  1. Spring Boot 使用 Apache POI 导出Excel文件
  2. 理解Excel业务的相关表格对象

理解导出的业务

首先我们应该理解导出的业务:导出,就是把数据库中的一张表的信息(像下面CSDN的博客数据一样),导出到Excel。如果你的数据库中没有全部的这张表格信息,可能你会在业务层进行一些复杂的计算处理。或者像你可以自由勾选阅读量,评论量,份数量,收藏量,前端传给后端之后,根据参数的需要,生成对应的List

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

总结导出:从数据库中查询出对应的List,然后在Excel中显示出来。

如何显示在Excel中

那么就有一个问题:如何把数据打印或显示在对应的表格中?

首先我们应该理解4个对象
工作簿,一个Excel文件就是一个工作簿。
表Sheet,一个表格页就是一个Sheet,一个Excel可以有多个表格Sheet页。
行Row,一张表中有多行。
单元格Cell,一行里面有多个单元格。

在这里插入图片描述
然后根据上面理解的4个对象,导出需求则是:创建一张工作簿,然后再工作簿中创建一张表,然后再对于的行与列中填写对应的List数据,你就可以得到Excel文件。一个一个的定位数据。

使用Apache POI解决导出需求

我打算使用一种简便一些的方法,完成这个需求,可能有种面向过程的感觉,但是理解业务有好处,没有繁琐的封装调用,各位读者可以使用一些封装改成对于的业务。

  1. 引入对应的依赖,这里只导入2007版本的Excel
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.9</version>
</dependency>
  1. 编写后端controller代码,这里我就用list表示,你们自行修改
    @RequestMapping("list")
    public void list(HttpServletResponse response) throws Exception{
        //需要通过response给前端数据流,设置对应的response
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition","attachment;filename="+"text.xlsx");
        
		//创建一张工作簿workbook
        Workbook workbook = new XSSFWorkbook();
        //在工作簿中创建一张表sheet
        Sheet sheet = workbook.createSheet("sheet1");
        //在表中创建一行row1,对应是sheet.createRow(0);
        Row row1 = sheet.createRow(0);
        //第一个单元格是姓名,第二个单元格是学好,相当于表头
        Cell cell1 = row1.createCell(0);
        cell1.setCellValue("姓名");
        Cell cell2 = row1.createCell(1);
        cell2.setCellValue("学号");
		//在表中创建第二行row2,对应是sheet.createRow(1);
        Row row2 = sheet.createRow(1);
        //第二行第一个单元格是张三,学好是123456
        Cell cell3 = row2.createCell(0);
        cell3.setCellValue("张三");
        Cell cell4 = row2.createCell(1);
        cell4.setCellValue("123456");
		
		//使用数据流返回给前端
        OutputStream out = response.getOutputStream();
        workbook.write(out);
        out.close();
        System.out.println("创建Excel完毕");

        //也直接使用文件流
        //FileOutputStream fileOutputStream = new FileOutputStream("E:\\workspace_2021(IDEA)\\export_excel\\test.xlsx");
        //workbook.write(fileOutputStream);
        //fileOutputStream.close();
    }

代码理解的内容我在注释中都已经写完全了,可以仔细的理解。就是创建一个工作簿,然后再工作簿中创建一张表,在表里面的第一行创建一行,然后依次的定位单元格。最后给前端数据流

问题一:为什么使用数据流不使用文件流?

现在的前后端分离项目,应该都是使用的数据流。前端人员根据数据流生成对应的文件,可以问一问前端业务的需求。我是一开始找一些网上的资料,大部分后端的资料还是会使用文件流,直接生成一个文件,后端测试好像一直是这样测试的,这样也直观一些。可能是因为时代的原因吧。。。。我们的Vue的前端说要的数据流。

在这里插入图片描述
使用postman测试后,数据流是这样的,并且本地不会创建文件。


下面是使用的文件流
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
使用文件流的话,就是上面的结果,本地会有一个生成的文件。

问题二:2003版本Excel和2007版本的Excel?

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.9</version>
</dependency>
<dependency>
   	<groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.9</version>
</dependency>

可能需要首先理解一下,为什么有这个问题,我是从导入依赖的时候发现的这个问题,poi是操作2003版的Excel,poi-ooxml是操作2007版的Excel。现在很多的代码直接两个依赖都加上,但是缺少解释,我觉得还是需要解释一下。

在这里插入图片描述

POI中有HSSF和XSSF,其中HSSF是2003版本的Excel,XSSF是2007版本的Excel

问题三:如果需要生成的是03版本的Excel,需要在上面的controller修改什么呢?

第一个就是new HSSF,第二个就是生成的文件需要是以xls结尾的,否则就算生成了文件,你的Excel文件也打不开。

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

 Workbook workbook = new XSSFWorkbook();
 //文件流只用于测试
 //FileOutputStream fileOutputStream = new FileOutputStream("E:\\workspace_2021(IDEA)\\export_excel\\test1.xls");

需要注意的是:使用的是数据流的话,需要和前端协商好对应的文件扩展名。2003版用xls,2007版用xlsx。

在这里插入图片描述
下面一段视频帮助大家理解一下Excel版本的区别:视频原地址

bug 无 处 不 在

点赞的朋友都能升职加薪

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐