有关后端使用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,
          };
        });
        }
相关文章
|
3月前
|
安全 Java Ruby
我尝试了所有后端框架 — — 这就是为什么只有 Spring Boot 幸存下来
作者回顾后端开发历程,指出多数框架在生产环境中难堪重负。相比之下,Spring Boot凭借内置安全、稳定扩展、完善生态和企业级支持,成为构建高可用系统的首选,真正经受住了时间与规模的考验。
319 2
|
7月前
|
JavaScript 前端开发 Java
制造业ERP源码,工厂ERP管理系统,前端框架:Vue,后端框架:SpringBoot
这是一套基于SpringBoot+Vue技术栈开发的ERP企业管理系统,采用Java语言与vscode工具。系统涵盖采购/销售、出入库、生产、品质管理等功能,整合客户与供应商数据,支持在线协同和业务全流程管控。同时提供主数据管理、权限控制、工作流审批、报表自定义及打印、在线报表开发和自定义表单功能,助力企业实现高效自动化管理,并通过UniAPP实现移动端支持,满足多场景应用需求。
729 1
|
8月前
|
移动开发 前端开发 JavaScript
Vue与React两大前端框架的主要差异点
以上就是Vue和React的主要差异点,希望对你有所帮助。在选择使用哪一个框架时,需要根据项目的具体需求和团队的技术栈来决定。
507 83
|
8月前
|
前端开发 Java 物联网
智慧班牌源码,采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署
智慧班牌系统是一款基于信息化与物联网技术的校园管理工具,集成电子屏显示、人脸识别及数据交互功能,实现班级信息展示、智能考勤与家校互通。系统采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署与私有化定制。核心功能涵盖信息发布、考勤管理、教务处理及数据分析,助力校园文化建设与教学优化。其综合性和可扩展性有效打破数据孤岛,提升交互体验并降低管理成本,适用于日常教学、考试管理和应急场景,为智慧校园建设提供全面解决方案。
546 70
|
7月前
|
JavaScript 前端开发 编译器
Vue与TypeScript:如何实现更强大的前端开发
Vue.js 以其简洁的语法和灵活的架构在前端开发中广受欢迎,而 TypeScript 作为一种静态类型语言,为 JavaScript 提供了强大的类型系统和编译时检查。将 Vue.js 与 TypeScript 结合使用,不仅可以提升代码的可维护性和可扩展性,还能减少运行时错误,提高开发效率。本文将介绍如何在 Vue.js 项目中使用 TypeScript,并通过一些代码示例展示其强大功能。
346 22
|
存储 JavaScript 网络架构
Vue3新增功能特性
Vue3相比Vue2更新技术点
|
3月前
|
JavaScript
Vue中如何实现兄弟组件之间的通信
在Vue中,兄弟组件可通过父组件中转、事件总线、Vuex/Pinia或provide/inject实现通信。小型项目推荐父组件中转或事件总线,大型项目建议使用Pinia等状态管理工具,确保数据流清晰可控,避免内存泄漏。
370 2
|
2月前
|
缓存 JavaScript
vue中的keep-alive问题(2)
vue中的keep-alive问题(2)
338 137
|
6月前
|
人工智能 JavaScript 算法
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
853 0
|
6月前
|
JavaScript UED
用组件懒加载优化Vue应用性能
用组件懒加载优化Vue应用性能