Bootstrap

【Apache POI】Excel操作(三):Excel在浏览器端即Web端写入操作的实现

卑鄙是卑鄙者的通行证,高尚是高尚者的墓志铭。

前言

之前给大家介绍了Excel在本地导入的基本操作(本期博客需要有前两期博客的基础才比较好理解,大家最好看一看哦),详情可见博客:

【Apache POI】Excel操作(一):Excel本地写入基本操作的实现

以及

【Apache POI】Excel操作(二):Excel本地写入基本操作的实现(进阶版)

但很多小伙伴,或者说看过我这篇博客:那些年Java走过的路 的小伙伴可能就会问了:Java大多是运用于B/S架构的项目,也就是浏览器/服务器模式的项目,所以我往往需要的是在浏览器端导出Excel,那么我到底该怎么写呢???

别担心,本期博客将解决这个问题!!!

编码开始

依赖

既然要在web端操作,肯定需要Web的依赖:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

完整依赖如下:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- xls(03) -->
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>3.9</version>
</dependency>

<!-- xlsx(07) -->
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml</artifactId>
	<version>3.9</version>
</dependency>

<!-- 日期格式化工具 -->
<dependency>
	<groupId>joda-time</groupId>
	<artifactId>joda-time</artifactId>
	<version>2.10.1</version>
</dependency>
        
<!-- lombok的依赖,idea需按照lombok的插件-->
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<version>1.18.12</version>
	<scope>provided</scope>
</dependency>

实体类

再需要一个实体类来装数据:

package com.guqueyue.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;


//lombok插件的注解
@Data // 若未使用lombok插件,请自行生成getter、setter以及toString方法
@AllArgsConstructor // 若未使用lombok插件,请自行生成有参构造方法
@NoArgsConstructor // 若未使用lombok插件,请自行生成无参构造方法
@Accessors(chain = true) // 开启链式编程
public class DemoData {

    /**
     * 书名
     */
    private String bookName;

    /**
     * 作者
     */
    private String author;

    /**
     * 时间
     */
    private String dateTime;

}

控制层

接下来,我们在控制层编写代码就好了:

package com.guqueyue.controller;

import com.guqueyue.entity.DemoData;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.joda.time.DateTime;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import javax.swing.*;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @ClassName ExportExcelController
 * @Description excel导出相关的控制层
 * @Author 古阙月
 * @Date 2020/11/4 0:31
 * @Version 1.0
 **/
@RequestMapping("/exportExcel")
@RestController
public class ExportExcelController {

    /**
     * 列名数组
     */
    static String[] rowNameArray = {"书名", "作者", "写作时间"};

    /**
     * 生成数据的方法
     * @return
     */
    private List<DemoData> getData() {
        List<DemoData> dataList = new ArrayList<DemoData>();
        for (int i = 0; i < 10; i++) {
            DemoData data = new DemoData();
            data.setBookName("平凡的世界" + i);
            data.setDateTime(new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
            data.setAuthor("路遥" + i);
            dataList.add(data);
        }
        return dataList;
    }

    /**
     * 导出excel
     * @param response
     * @throws Exception
     */
    @RequestMapping("/export")
    public void testWrite03Web(HttpServletResponse response) throws Exception {
        // 1.创建一个工作簿
        Workbook workbook = new HSSFWorkbook();
        // 2.创建一个工作表
        Sheet sheet = workbook.createSheet("古阙月的书单");
        // 3.创建第一行
        Row row1 = sheet.createRow(0);
        // 创建列名
        for (int i = 0; i < rowNameArray.length; i++) {
            Cell cell = row1.createCell(i);
            cell.setCellValue(rowNameArray[i]);
        }

        // 遍历创建接下来的行
        List<DemoData> dataList = getData();
        for (int i = 0; i < dataList.size(); i++) {
            Row row = sheet.createRow(i + 1);

            int j = 0;
            DemoData demoData = dataList.get(i);
            // 获取反射对象
            Class<?> clazz = demoData.getClass();

            // 获取反射对象的所有属性,包括公有属性和私有属性
            Field[] fields = clazz.getDeclaredFields();

            // 遍历所有属性
            for (Field field : fields) {

                // 私有属性授权,方便访问
                field.setAccessible(true);

                // 赋值
                String value = (String) field.get(demoData);
                Cell cell = row.createCell(j);
                cell.setCellValue(value);
                j++;
            }
        }

        /**
         * 格式化当前日期,以便拼接文件名
         */
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String date = sdf.format(new Date());
        // 生成文件名
        String fileName = "古阙月书籍表03" + date + ".xls";

        /**
         * 将生成的excel写入到浏览器端
         */
        response.reset();
        response.setContentType("application/ms-excel;charset=UTF-8");
        try {
            response.addHeader("Content-Disposition", "attachment;filename=\""
                    + new String((fileName).getBytes("GBK"),
                    "ISO8859_1") + "\"");
            OutputStream out = response.getOutputStream();
            // 写入
            workbook.write(out);
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

看见代码不要慌,其实跟上期博客相比,主要多了这么些代码而已:

/**
 * 将生成的excel写入到浏览器端
 */
response.reset();
response.setContentType("application/ms-excel;charset=UTF-8");
try {
    response.addHeader("Content-Disposition", "attachment;filename=\""
            + new String((fileName).getBytes("GBK"),
            "ISO8859_1") + "\"");
    OutputStream out = response.getOutputStream();
    // 写入
    workbook.write(out);
    out.flush();
    out.close();
} catch (Exception e) {
    e.printStackTrace();
}

运行

运行SpringBoot程序,在浏览器端输入:http://localhost:8080/exportExcel/export (因为我这里没有配置端口,所以默认为8080)
在这里插入图片描述
可以看到在浏览器下方成功导出了一个excel文件,点开一看:
在这里插入图片描述
完美!!!

小提醒

当然,我们在实际开发过程中是不可能让用户直接在浏览器端输入url来导出excel的,我们可能需要编写前端代码来发送请求。

切记,千万不要用ajax来发送请求,毕竟ajax发送请求都是由ajax引擎来发送和接收请求的,而不是浏览器!!!

本博主就因为这个发送的问题困扰了几个小时!用location.href即可:

location.href = "url";

比如没有拦截器等配置的情况之下,本篇博客中的url就是:http://localhost:8080/exportExcel/export

好了,本期博客到此结束,敬请期待下期博客,我们不见不散

;