有关后端使用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,
          };
        });
        }
相关文章
|
7月前
|
JavaScript 前端开发 Java
制造业ERP源码,工厂ERP管理系统,前端框架:Vue,后端框架:SpringBoot
这是一套基于SpringBoot+Vue技术栈开发的ERP企业管理系统,采用Java语言与vscode工具。系统涵盖采购/销售、出入库、生产、品质管理等功能,整合客户与供应商数据,支持在线协同和业务全流程管控。同时提供主数据管理、权限控制、工作流审批、报表自定义及打印、在线报表开发和自定义表单功能,助力企业实现高效自动化管理,并通过UniAPP实现移动端支持,满足多场景应用需求。
725 1
|
8月前
|
移动开发 前端开发 JavaScript
Vue与React两大前端框架的主要差异点
以上就是Vue和React的主要差异点,希望对你有所帮助。在选择使用哪一个框架时,需要根据项目的具体需求和团队的技术栈来决定。
507 83
|
7月前
|
JavaScript 前端开发 编译器
Vue与TypeScript:如何实现更强大的前端开发
Vue.js 以其简洁的语法和灵活的架构在前端开发中广受欢迎,而 TypeScript 作为一种静态类型语言,为 JavaScript 提供了强大的类型系统和编译时检查。将 Vue.js 与 TypeScript 结合使用,不仅可以提升代码的可维护性和可扩展性,还能减少运行时错误,提高开发效率。本文将介绍如何在 Vue.js 项目中使用 TypeScript,并通过一些代码示例展示其强大功能。
346 22
|
9月前
|
人工智能 JavaScript 前端开发
Vue 性能革命:揭秘前端优化的终极技巧;Vue优化技巧,解决Vue项目卡顿问题
Vue在处理少量数据和有限dom的情况下技术已经非常成熟了,但现在随着AI时代的到来,海量数据场景会越来越多,Vue优化技巧也是必备技能。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
3月前
|
JavaScript
Vue中如何实现兄弟组件之间的通信
在Vue中,兄弟组件可通过父组件中转、事件总线、Vuex/Pinia或provide/inject实现通信。小型项目推荐父组件中转或事件总线,大型项目建议使用Pinia等状态管理工具,确保数据流清晰可控,避免内存泄漏。
364 2
|
2月前
|
缓存 JavaScript
vue中的keep-alive问题(2)
vue中的keep-alive问题(2)
334 137
|
6月前
|
人工智能 JavaScript 算法
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
850 0
|
6月前
|
JavaScript UED
用组件懒加载优化Vue应用性能
用组件懒加载优化Vue应用性能
|
7月前
|
JavaScript 数据可视化 前端开发
基于 Vue 与 D3 的可拖拽拓扑图技术方案及应用案例解析
本文介绍了基于Vue和D3实现可拖拽拓扑图的技术方案与应用实例。通过Vue构建用户界面和交互逻辑,结合D3强大的数据可视化能力,实现了力导向布局、节点拖拽、交互事件等功能。文章详细讲解了数据模型设计、拖拽功能实现、组件封装及高级扩展(如节点类型定制、连接样式优化等),并提供了性能优化方案以应对大数据量场景。最终,展示了基础网络拓扑、实时更新拓扑等应用实例,为开发者提供了一套完整的实现思路和实践经验。
983 77
|
5月前
|
人工智能 JSON JavaScript
VTJ.PRO 首发 MasterGo 设计智能识别引擎,秒级生成 Vue 代码
VTJ.PRO发布「AI MasterGo设计稿识别引擎」,成为全球首个支持解析MasterGo原生JSON文件并自动生成Vue组件的AI工具。通过双引擎架构,实现设计到代码全流程自动化,效率提升300%,助力企业降本增效,引领“设计即生产”新时代。
494 1

热门文章

最新文章