有关后端使用Springboot导出Excel,前端使用vue实现Excel下载的功能实现

简介: 有关后端使用Springboot导出Excel,前端使用vue实现Excel下载的功能实现

有关后端使用Springboot导出Excel,前端使用vue实现Excel下载的功能实现

接到一个需求 ,是有关Excel导出的功能,用户通过页面的数据,进行批量的导出操作。话不多说,直接上代码:

后端

package com.ly.travelaround.cms.common.utils;
import org.apache.poi.hssf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
 * 导出实体到Excel的工具类
 * @Date 2021/9/2 10:17
 */
public class ExportEntityToExcel {
    private static final Logger logger = LoggerFactory.getLogger(ExportEntityToExcel.class);
    public static <T> void export(String excelName, List<T> list, LinkedHashMap<String, String> fieldMap, HttpServletResponse response, HttpServletRequest request) {
        // 设置默认文件名为当前时间:年月日时分秒
        if (excelName == null || excelName == "") {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss");
            String defaultName = sdf.format(new Date());
            excelName = defaultName;
        }
        try {
            String fileName = new String(excelName.getBytes("gb2312"), "ISO8859-1") + ".xls";
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/vnd.ms-excel"); // 改成输出excel文件
            response.setHeader("Pragma", "No-cache");
            response.setHeader("Cache-Control", "No-cache");
            // 设置response头信息
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        } catch (Exception e1) {
            logger.info(e1.getMessage());
        }
        try {
            //创建一个WorkBook,对应一个Excel文件
            HSSFWorkbook workbook = new HSSFWorkbook();
            //在Workbook中,创建一个sheet,对应Excel中的工作薄(sheet)
            HSSFSheet sheet = workbook.createSheet(excelName);
            //创建单元格,并设置值表头 设置表头居中
            HSSFCellStyle style = workbook.createCellStyle();
            //创建一个居中格式
            style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
            // 填充工作表
            fillSheet(sheet, list, fieldMap, style);
            //将文件输出
            OutputStream outputStream = response.getOutputStream();
            workbook.write(outputStream);
            outputStream.flush();
            outputStream.close();
        } catch (Exception e) {
            logger.info("导出Excel失败!");
            logger.error(e.getMessage());
        }
    }
    /**
     * 根据字段名获取字段
     */
    public static Field getFieldByName(String fieldName, Class<?> clazz) {
        // 获取所有字段
        Field[] selfFields = clazz.getDeclaredFields();
        // 如果本类中存在该字段,则返回
        for (Field field : selfFields) {
            //如果本类中存在该字段,则返回
            if (field.getName().equals(fieldName)) {
                return field;
            }
        }
        // 否则,查看父类中是否存在此字段,如果有则返回
        Class<?> superClazz = clazz.getSuperclass();
        if (superClazz != null && superClazz != Object.class) {
            //递归
            return getFieldByName(fieldName, superClazz);
        }
        // 如果本类和父类都没有,则返回空
        return null;
    }
    /**
     * 根据字段名获取字段值
     */
    public static Object getFieldValueByName(String fieldName, Object o) throws Exception {
        Object value = null;
        //根据字段名得到字段
        Field field = getFieldByName(fieldName, o.getClass());
        //如果该字段存在,则取出该字段的值
        if (field != null) {
            field.setAccessible(true);//类中的成员变量为private,在类外边使用属性值,故必须进行此操作
            value = field.get(o);//获取当前对象中当前Field的value
        } else {
            throw new Exception(o.getClass().getSimpleName() + "类不存在字段名: " + fieldName);
        }
        return value;
    }
    /**
     * 根据带路径或不带路径的属性名获取属性值,即接受简单属性名,
     * 如userName等,又接受带路径的属性名,如student.department.name等
     */
    public static Object getFieldValueByNameSequence(String fieldNameSequence, Object o) throws Exception {
        Object value = null;
        // 将fieldNameSequence进行拆分
        String[] attributes = fieldNameSequence.split("\\.");
        if (attributes.length == 1) {
            value = getFieldValueByName(fieldNameSequence, o);
        } else {
            // 根据数组中第一个连接属性名获取连接属性对象,如student.department.name
            Object fieldObj = getFieldValueByName(attributes[0], o);
            //截取除第一个属性名之后的路径
            String subFieldNameSequence = fieldNameSequence.substring(fieldNameSequence.indexOf(".") + 1);
            //递归得到最终的属性对象的值
            value = getFieldValueByNameSequence(subFieldNameSequence, fieldObj);
        }
        return value;
    }
    /**
     * 向工作表中填充数据
     */
    public static <T> void fillSheet(HSSFSheet sheet, List<T> list, LinkedHashMap<String, String> fieldMap, HSSFCellStyle style) throws Exception {
        // 定义存放英文字段名和中文字段名的数组
        String[] enFields = new String[fieldMap.size()];
        String[] cnFields = new String[fieldMap.size()];
        // 填充数组
        int count = 0;
        for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
            enFields[count] = entry.getKey();
            cnFields[count] = entry.getValue();
            count++;
        }
        //在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制short
        HSSFRow row = sheet.createRow((int) 0);
        // 填充表头
        for (int i = 0; i < cnFields.length; i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellValue(cnFields[i]);
            cell.setCellStyle(style);
            sheet.setColumnWidth(i, 3000);//设置表格宽度
        }
        // 填充内容
        for (int index = 0; index < list.size(); index++) {
            row = sheet.createRow(index + 1);
            // 获取单个对象
            T item = list.get(index);
            for (int i = 0; i < enFields.length; i++) {
                Object objValue = getFieldValueByNameSequence(enFields[i], item);
                String fieldValue = objValue == null ? "" : objValue.toString();
                row.setRowStyle(style);
                row.createCell(i).setCellValue(fieldValue);
            }
        }
    }
}
/**
*对应着导出的Excel实体信息 
*/
//略
/**
*控制层
*/
@RestController("excel")
public class ExcelExportController {
    @PostMapping(value = "downLoadExcel")
    public void downLoadExcel(HttpServletResponse response, HttpServletRequest request, @RequestBody() List<ExcelPo> dataList) {
        if (null == dataList || dataList.size() <= 0) {
            return ;
        }
        response.setCharacterEncoding("utf-8");
        String excelName = "酒店列表";
        LinkedHashMap<String, String> fieldMap = new LinkedHashMap<>();
        fieldMap.put("order", "排序值");
        fieldMap.put("cityId", "城市ID");
        fieldMap.put("hotelId", "商品ID");
        fieldMap.put("hotelName", "商品名称");
        fieldMap.put("start", "星级");
        fieldMap.put("score", "评分");
        fieldMap.put("commentTotal", "点评数量");
        fieldMap.put("price", "价格");
        fieldMap.put("filterName", "商圈名称");
        new ExportEntityToExcel().export(excelName, dataList, fieldMap, response, request);
    }
}

其中后端代码是使用的—参考链接—的代码。

前端

<el-button :disabled="isActive" @click="exportChoosed" type="info"
        >导出数据</el-button>
   exportChoosed() {
      // 利用a标签自定义下载文件名
      const link = document.createElement("a");
      //let choosedList = this.multipleSelection.map((item) => {
        //return item;
      //});
      //这里的choosedList是你需要导出的数据集合 我这里是我的具体使用场景 你需要什么就传什么
      console.log("chooosedList", choosedList);
      //请求后端接口 进行excel的导出
      hotelList
        .exportChoosedToExcel(choosedList)
        .then((res) => {
          let blob = new Blob([res], { type: "application/vnd.ms-excel" }); // res就是接口返回的文件流了
          let objectUrl = URL.createObjectURL(blob);
          debugger;
          link.href = objectUrl;
          link.download = "酒店列表"; // 自定义文件名
          link.click(); // 下载文件
          // window.location.href = objectUrl;
          window.URL.revokeObjectURL(objectUrl); // 释放内存
        })
        .catch((err) => {
          console.log("被catch到了", err);
          return {
            code: 500,
            success: false,
            msg: err,
          };
        });
        }
相关文章
|
8月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
764 2
|
11月前
|
缓存 前端开发 Java
SpringBoot 实现动态菜单功能完整指南
本文介绍了一个动态菜单系统的实现方案,涵盖数据库设计、SpringBoot后端实现、Vue前端展示及权限控制等内容,适用于中后台系统的权限管理。
1169 1
|
监控 安全 Java
Java 开发中基于 Spring Boot 3.2 框架集成 MQTT 5.0 协议实现消息推送与订阅功能的技术方案解析
本文介绍基于Spring Boot 3.2集成MQTT 5.0的消息推送与订阅技术方案,涵盖核心技术栈选型(Spring Boot、Eclipse Paho、HiveMQ)、项目搭建与配置、消息发布与订阅服务实现,以及在智能家居控制系统中的应用实例。同时,详细探讨了安全增强(TLS/SSL)、性能优化(异步处理与背压控制)、测试监控及生产环境部署方案,为构建高可用、高性能的消息通信系统提供全面指导。附资源下载链接:[https://pan.quark.cn/s/14fcf913bae6](https://pan.quark.cn/s/14fcf913bae6)。
2574 0
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
1608 14
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
1032 0
|
SpringCloudAlibaba JavaScript 前端开发
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
分布式组件、nacos注册配置中心、openfegin远程调用、网关gateway、ES6脚本语言规范、vue、elementUI
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
|
人工智能 自然语言处理 运维
前端大模型应用笔记(一):两个指令反过来说大模型就理解不了啦?或许该让第三者插足啦 -通过引入中间LLM预处理用户输入以提高多任务处理能力
本文探讨了在多任务处理场景下,自然语言指令解析的困境及解决方案。通过增加一个LLM解析层,将复杂的指令拆解为多个明确的步骤,明确操作类型与对象识别,处理任务依赖关系,并将自然语言转化为具体的工具命令,从而提高指令解析的准确性和执行效率。
816 6
|
机器学习/深度学习 弹性计算 自然语言处理
前端大模型应用笔记(二):最新llama3.2小参数版本1B的古董机测试 - 支持128K上下文,表现优异,和移动端更配
llama3.1支持128K上下文,6万字+输入,适用于多种场景。模型能力超出预期,但处理中文时需加中英翻译。测试显示,其英文支持较好,中文则需改进。llama3.2 1B参数量小,适合移动端和资源受限环境,可在阿里云2vCPU和4G ECS上运行。
1356 1