springboot+vue+mysql+easyexcel实现文件导出+导出的excel单元格添加下拉列表

Excel导出

EasyExcel官方文档
官方文档本身写的非常详细,我就是根据官方文档内的写Excel里web中的写实现的导出

后端

对象

需要写一个实体类
其中涉及到一些用到的EasyExcel的注解

  • @ColumnWidth(20) 列宽设为20,自定义的,放在实体类上面是整个实体类的每个字段的列宽都为20,放在单个字段上则是改字段为20
  • @ContentRowHeight(10) 设置数据行的行高为10个单位
  • @HeadRowHeight(20) 设置Excel表格的表头行高度为20
  • @ExcelIgnore 在导出文件的时候忽略该字段列
  • @ExcelProperty("xxx") 导出文件原本标题行字段是数据库内写的字段,加上这个注解就会变为括号内写入的文字
  • @DateTimeFormat("yyyy-MM-dd") 设置日期格式,自定义
@Data
@ColumnWidth(20)
public class WarnVo {//传输给前端展示//id@ExcelIgnoreprivate Long id;//车间@ExcelProperty("车间")private String workshops;//设备编号@ExcelProperty("设备编号")private String deviceNumber;//设备名称@ExcelProperty("设备名称")private String deviceName;//设备型号@ExcelProperty("设备型号")private String deviceModel;//维保到期时间@ExcelProperty("维保到期时间")@DateTimeFormat("yyyy-MM-dd")private Date tainEndTime;//预警时间@ExcelProperty("预警时间")@DateTimeFormat("yyyy-MM-dd")private Date warnTime;//状态(是否生成预警信息 是否被保养)@ExcelIgnoreprivate Integer status;
}

controller层

  • copy了官网的导出代码,做了一些改变,比如导出的一个字段workshops是字典(不了解的可以点击vue实现查询搜索框下拉字典了解一下,如果没有做字典的可以忽略这一段),只能选择字典项进行输入,在controller层获取到要导出的数据以及字典集合,进行一个匹配判断然后置换
    //文件导出/*** 文件下载并且失败的时候返回json(默认失败了会返回一个有部分数据的Excel)* 这种方法是将Excel文件的生成过程放在后端进行。前端发起一个请求到后端,后端处理数据并生成Excel文件,然后将文件返回给前端进行下载。* 这种方法的优点是可以将数据处理的压力放在后端,前端只需要处理请求和下载文件的逻辑。* @since 2.1.1*/@GetMapping("/download")public void download(HttpServletResponse response) throws IOException {// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postmantry {response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");this.setExcelResponseProp(response,"保养预警");List<WarnVo> warnVos = iTainWarnService.listAllWarn();List<SysDictEntity> workList = sysDictService.maintenanceList("chejian");for (WarnVo warnVo : warnVos) {for (SysDictEntity sysDictEntity : workList) {if (sysDictEntity.getValue().compareTo(warnVo.getWorkshops())==0){warnVo.setWorkshops(sysDictEntity.getName());}}}// 这里需要设置不关闭流EasyExcel.write(response.getOutputStream(), WarnVo.class)// 导出Excel时在此处注册handler.registerWriteHandler(new CustomSheetWriteHandler(sysDictService)).autoCloseStream(Boolean.FALSE).sheet("保养预警").doWrite(warnVos);} catch (Exception e) {// 重置responseresponse.reset();response.setContentType("application/json");response.setCharacterEncoding("utf-8");Map<String, String> map = new HashMap<>();map.put("status", "failure");map.put("message", "下载文件失败" + e.getMessage());response.getWriter().println(JSON.toJSONString(map));}}
  • 字典项做了下拉框,需要在导出Excel的时候注册handler,是一个监听器,这个监听器需要自己手动装配构造器,因为这个监听器没被扫描到,不属于可自动装配范围
    • 重写afterSheetCreate方法,先写一个空的集合,再获取字典集合
    • 遍历字典集合,根据数据库的字典特性,拿到字典项的某个我们需要展示出来的字段,比如这里就要展示字典项的name,所以把字典项的name全放入上面写的空集合中
    • 再设置下拉选项单元格列的位置,key:下拉选项要放到哪个单元格,比如A列的单元格那就是0,C列的单元格,那就是2,value:key对应的那个单元格下拉列表里的数据项,比如这里就是下拉选项放入字典项name的集合,其余内容不变,copy即可
package com.wedu.modules.tain.listener;import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import com.wedu.modules.sys.entity.SysDictEntity;
import com.wedu.modules.sys.service.SysDictService;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class CustomSheetWriteHandler implements SheetWriteHandler {private SysDictService sysDictService;public CustomSheetWriteHandler(SysDictService sysDictService) {this.sysDictService = sysDictService;}@Overridepublic void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {}/*** 想实现Excel引用其他sheet页数据作为单元格下拉选项值,* 需要重写该方法** @param writeWorkbookHolder* @param writeSheetHolder*/@Overridepublic void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {// 构造样例数据,该数据可根据实际需要,换成业务数据// 实际数据可通过构造方法,get、set方法等由外界传入List<String> selectDataList = new ArrayList<>();List<SysDictEntity> list = sysDictService.maintenanceList("chejian");for (SysDictEntity sysDictEntity : list) {if (sysDictEntity.getSort()!=null){selectDataList.add(sysDictEntity.getName());}}// 构造下拉选项单元格列的位置,以及下拉选项可选参数值的map集合// key:下拉选项要放到哪个单元格,比如A列的单元格那就是0,C列的单元格,那就是2// value:key对应的那个单元格下拉列表里的数据项,比如这里就是下拉选项1..100Map<Integer, List<String>> selectParamMap = new HashMap<>();selectParamMap.put(0, selectDataList);// 获取第一个sheet页Sheet sheet = writeSheetHolder.getCachedSheet();// 获取sheet页的数据校验对象DataValidationHelper helper = sheet.getDataValidationHelper();// 获取工作簿对象,用于创建存放下拉数据的字典sheet数据页Workbook workbook = writeWorkbookHolder.getWorkbook();// 迭代索引,用于存放下拉数据的字典sheet数据页命名int index = 1;for (Map.Entry<Integer, List<String>> entry : selectParamMap.entrySet()) {// 设置存放下拉数据的字典sheet,并把这些sheet隐藏掉,这样用户交互更友好String dictSheetName = "dict_hide_sheet" + index;Sheet dictSheet = workbook.createSheet(dictSheetName);// 隐藏字典sheet页workbook.setSheetHidden(index++, true);// 设置下拉列表覆盖的行数,从第一行开始到最后一行,这里注意,Excel行的// 索引是从0开始的,我这边第0行是标题行,第1行开始时数据化,可根据实// 际业务设置真正的数据开始行,如果要设置到最后一行,那么一定注意,// 最后一行的行索引是1048575,千万别写成1048576,不然会导致下拉列表// 失效,出不来CellRangeAddressList infoList = new CellRangeAddressList(1, 1048575, entry.getKey(), entry.getKey());int rowLen = entry.getValue().size();for (int i = 0; i < rowLen; i++) {// 向字典sheet写数据,从第一行开始写,此处可根据自己业务需要,自定// 义从第几行还是写,写的时候注意一下行索引是从0开始的即可dictSheet.createRow(i).createCell(0).setCellValue(entry.getValue().get(i));}// 设置关联数据公式,这个格式跟Excel设置有效性数据的表达式是一样的String refers = dictSheetName + "!$A$1:$A$" + entry.getValue().size();Name name = workbook.createName();name.setNameName(dictSheetName);// 将关联公式和sheet页做关联name.setRefersToFormula(refers);// 将上面设置好的下拉列表字典sheet页和目标sheet关联起来DataValidationConstraint constraint = helper.createFormulaListConstraint(dictSheetName);DataValidation dataValidation = helper.createValidation(constraint, infoList);sheet.addValidationData(dataValidation);}}
}

测试

后端写好了可以使用postman进行测试
在这里插入图片描述
token失效可以去网页上f12找一个有效的token复制一下
在这里插入图片描述
发送请求并且下载,就可以导出文件进行查看了
在这里插入图片描述

前端

template

<el-button type="primary" icon="el-icon-share" @click="download()">一键导出</el-button>

methods

设置相应类型非常重要,不设置导出的文件也不能用
link.setAttribute("download", "保养预警.xlsx") 这句为导出文件命名

//文件导出download() {this.$http({url: this.$http.adornUrl("/tain/warn/download"),method: "get",//设置响应类型(重要responseType: "blob",}).then((response) => {const url = window.URL.createObjectURL(new Blob([response.data]));const link = document.createElement("a");link.href = url;link.setAttribute("download", "保养预警.xlsx");document.body.appendChild(link);link.click();});},

前后端都写完后,就可以启动项目,在前端页面点击下载按钮,发送请求成功就可以成功下载文件

前端发起一个请求到后端,后端处理数据并生成Excel文件,然后将文件返回给前端进行下载。这种方法的优点是可以将数据处理的压力放在后端,前端只需要处理请求和下载文件的逻辑。缺点是需要前后端的配合,增加了后端的工作量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/707250.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Postgresql中触发器的使用

在PostgreSQL中&#xff0c;触发器是一种特殊类型的函数&#xff0c;它会自动在数据库上执行特定操作之前或之后触发。这些操作通常是INSERT、UPDATE或DELETE语句。触发器可以用来执行数据校验、自动更新或维护表之间的关联。 触发器组件 触发器函数&#xff1a;这是实际执行…

binwalk安装记录和burpsuite安装记录

我的虚拟机环境是Ubuntu20.04 python有2.7的和3.8的 [[#binwalk|binwalk]] [[#binwalk#pip|pip]][[#binwalk#安装 sasquatch|安装 sasquatch]][[#binwalk#安装 jefferson|安装 jefferson]][[#binwalk#安装 ubi_reader|安装 ubi_reader]][[#binwalk#安装 yaffshiv|安装 yaffshi…

JavaWeb——005 -- 请求响应 分层解耦(Postman、三层架构、IOC、DI、注解)

目录 一、请求 1、Postman&#xff08;接口测试工具&#xff09; 1.1、介绍 ②、安装 2、简单参数 1.1、原始方式 1.2、SpringBoot方法 ③、小结 3、实体参数 3.1、简单实体对象 3.2、复杂实体对象 3.3、小结 4、数组集合参数 ①、数组​编辑 ②、集合 ③、小结…

Alist访问主页显示空白解决方法

文章目录 问题记录问题探索和解决网络方案问题探究脚本内容查看 最终解决教程 问题记录 访问Alist主页显示空白&#xff0c;按F12打开开发人员工具 ,选择控制台&#xff0c;报错如下 index.75e31196.js:20 Uncaught TypeError: Cannot assign to read only property __symbo…

python|闲谈2048小游戏和数组的旋转及翻转和转置

目录 2048 生成数组 n阶方阵 方阵旋转 顺时针旋转 逆时针旋转 mxn矩阵 矩阵旋转 测试代码 测试结果 翻转和转置 2048 《2048》是一款比较流行​的数字游戏​&#xff0c;最早于2014年3月20日发行。原版2048由Gabriele Cirulli首先在GitHub上发布&#xff0c;后被移…

【Day59】代码随想录之动态规划_583两个字符串的删除操作_72编辑距离

文章目录 动态规划理论基础动规五部曲&#xff1a;出现结果不正确&#xff1a; 1. 583两个字符串的删除操作2. 72编辑距离 动态规划理论基础 动规五部曲&#xff1a; 确定dp数组 下标及dp[i] 的含义。递推公式&#xff1a;比如斐波那契数列 dp[i] dp[i-1] dp[i-2]。初始化d…

选择排序的简单介绍

选择排序是一种简单直观的排序算法&#xff0c;其原理如下&#xff1a; 1. 遍历数组&#xff0c;找到最小&#xff08;或最大&#xff09;的元素&#xff0c;并将其与数组的第一个元素交换位置。 2. 接着在剩下的元素中找到最小&#xff08;或最大&#xff09;的元素&#xff…

Uniapp在IOS系统打包测试流程

大家好我是咕噜美乐蒂&#xff0c;很高兴又和大家见面了&#xff01;UniApp 是一种基于 Vue.js 的跨平台应用开发框架&#xff0c;可以用于快速构建同时支持多个平台&#xff08;包括iOS、Android、Web 等&#xff09;的应用程序。在 iOS 系统上打包和测试 UniApp 应用的流程可…

园区水费收费管理系统

园区水费收费管理系统是专为园区或小区的水费管理而设计的系统&#xff0c;旨在提高水费收费效率、精准监测水费使用情况&#xff0c;简化管理流程&#xff0c;为园区管理方和居民提供便捷、高效的水费管理解决方案。该系统结合了数字化技术和智能化管理手段&#xff0c;通过线…

『NLP学习笔记』图解 GPT-2(可视化 Transformer 语言模型)

图解 GPT-2(可视化 Transformer 语言模型) 文章目录 一. GPT-2和语言模型1.1. 什么是语言模型1.2 Transformer的语言模型1.3 和BERT的不同1.4 Transformer 组件的演变1.4.1 encoder组件1.4.2 decoder组件1.4.3 只有decoder组件的decoder模块1.5 GPT-2内部结构1.6 GPT-2内部结构…

P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G python解法

P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) nint(input()) arrlist(map(int,input().split())) arr.sort() sumarr[0] total_sum0 #一开始以为单纯排列就行了&#xff0c;然后将之前累计的时间求和 for i…

非同质化权益(NFR):重塑当代商业市场的新范式

每天五分钟讲解一个互联网知识&#xff0c;大家好我是啊浩说互联网 随着区块链技术的日益成熟和数字资产的普及&#xff0c;非同质化权益&#xff08;Non-Fungible Rights&#xff0c;简称NFR&#xff09;开始崭露头角&#xff0c;并在当代商业市场中引发了一场深刻的变革。NFR…

pg_rman部署及使用

PG_RMAN部署及使用 PGSQL推出开源备份工具pg_rman&#xff0c;类似于oracle的rman备份策略&#xff0c;实现了全量、增量和归档等多重备份方式&#xff0c;可以很灵活的管理PGSQL数据库的备份&#xff0c;支持在线和基于PITR的备份恢复方式。 1、使用postgres用户部署 [post…

动态规划-状态转移(O(n))

获取生成数组中的最大值 1.题目 2.思路 其实只要看透该题的本质 并不难&#xff0c;应用动态规划&#xff0c;题目就已经给出了状态方程的式子。 首先规定好maxn的大小&#xff0c;防止溢出。定义nums数组。定义一个函数&#xff0c;写入状态方程式子。最后定义一个变量与数…

【数据结构】数组

第一章、为什么数组的下标一般从0开始编号 提到数组&#xff0c;读者肯定不陌生&#xff0c;甚至还会很自信地说&#xff0c;数组很简单。编程语言中一般会有数组这种数据类型。不过&#xff0c;它不仅是编程语言中的一种数据类型&#xff0c;还是基础的数据结构。尽管数组看起…

Openstack云计算架构及前期服务搭建

openstack介绍 Openstack是一个开源的云计算管理平台项目&#xff0c;由几个主要的组件组合起来完成具体工作&#xff0c;支持几乎所有的云环境&#xff0c;项目目标是提供实施简单、可大规模扩展、丰富、标准统一的云计算管理平台 ----百度百科 Openstack是一个云操作系统&a…

STM32开发(屏幕驱动ST7735S-SPI方式)用RT-Thread驱动测试

前言 使用ST7735S屏幕驱动&#xff0c;方便学习LVGL通过结构体的方式来管理相关函数和变量通讯协议和硬件驱动层进行解耦 驱动 配置&#xff08;用于对接硬件&#xff09; st7735s_conf.h // // Created by shchl on 2024/2/28. //#ifndef STM32F407V4T6_RTOS_ST7735S_CON…

css常用的选择器介绍

CSS&#xff08;层叠样式表&#xff09;选择器是CSS规则的一部分&#xff0c;它用于选择和定位网页上的元素&#xff0c;以便将样式应用到这些元素上。CSS选择器的种类繁多&#xff0c;每种选择器都有其特定的用途、特点和效率。在这篇文章中&#xff0c;我们将讨论一些常用的C…

Spring Boot项目如何快速从零开始打造一个属于自己的RPC框架

一、前言 在平时Spring Boot项目开发过程中,我们进行远程服务调用大都采用@RestController + @RequestMapping相关注解发布接口,使用OpenFeign组件进行微服务之间调用。这套技术架构已经足够完善了,当然没有什么问题,但是作为一个开发者,老是用一套框架天天写代码,不免有…

环境分析检测小剂量移液用耐受硝酸盐酸PFA材质吸管特氟龙移液枪枪头

PFA枪头&#xff0c;为移液枪专业定制&#xff0c;广泛用于ICP-MS、ICP-OES等痕量分析以及同位素分析等实验室。地质、电子化学品、半导体分析测试、疾控中心、制药厂、环境检测中心等一些机构少量移液用。 规格参考:0.1-0.2ml、1ml、2ml、5ml、10ml等。 目前部分规格可适配普…