springboot+easyexcel实现下载excels模板下拉选择

定义下拉注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelDropDown {/*** 固定下拉选项*/String[] source() default {};/*** 动态数据源key(从上下文中获取)*/String sourceMethod() default "";/*** 下拉框起始行(默认从第2行开始)*/int firstRow() default 1;/*** 下拉框结束行(默认到10000行)*/int lastRow() default 10000;
}

实现CellWriteHandler 接口


@Slf4j
public class DynamicDropDownHandler implements CellWriteHandler {private final ApplicationContext applicationContext;public DynamicDropDownHandler(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}@Overridepublic void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {}@Overridepublic void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {Class clazz = writeSheetHolder.getClazz();try {String fieldName = head.getFieldName();Field field = clazz.getDeclaredField(fieldName);ExcelDropDown dropDown = field.getAnnotation(ExcelDropDown.class);if (dropDown != null) {String[] source = dropDown.source();if (source.length == 0) {//判断是否有从库中查询数据的方法String method = dropDown.sourceMethod();if (null != method && !"".equals(method)) {source = applicationContext.getBean(method, String[].class);}if (source.length == 0) {return;}}Sheet sheet = writeSheetHolder.getSheet();Workbook workbook = sheet.getWorkbook();// 1. 创建隐藏Sheet存储下拉选项String optionSheetName = fieldName+"_options";Sheet optionsSheet = workbook.getSheet(optionSheetName);if (optionsSheet == null) {optionsSheet = workbook.createSheet(optionSheetName);workbook.setSheetHidden(workbook.getSheetIndex(optionsSheet), true); // 隐藏Sheet}// 2. 写入选项数据到隐藏Sheetint optionCol = 0; // 使用第一列存储选项for (int i = 0; i < source.length; i++) {Row row = optionsSheet.getRow(i);if (row == null) {row = optionsSheet.createRow(i);}row.createCell(optionCol).setCellValue(source[i]);}// 3. 创建名称引用String rangeName = "DROP_DOWN_" + fieldName.toUpperCase();Name namedRange = workbook.getName(rangeName);if (namedRange == null) {namedRange = workbook.createName();namedRange.setNameName(rangeName);}namedRange.setRefersToFormula(String.format(optionSheetName+"!$A$1:$A$%d", source.length));// 4. 设置数据验证(使用公式引用)DataValidationHelper helper = sheet.getDataValidationHelper();DataValidationConstraint constraint =helper.createFormulaListConstraint(rangeName);// 设置下拉范围:从第二行开始到最大行,当前列int columnIndex = cell.getColumnIndex();CellRangeAddressList addressList = new CellRangeAddressList(1, // 从第二行开始2, // Excel最大行号columnIndex,columnIndex);DataValidation validation = helper.createValidation(constraint, addressList);validation.setSuppressDropDownArrow(true);validation.setShowErrorBox(true);sheet.addValidationData(validation);}} catch (Exception e) {log.error(e.getMessage());}}@Overridepublic void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {}
}

使用下载模板接口

    public void downloadTemplate(HttpServletResponse response) {try {// 设置响应头response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");String fileName = URLEncoder.encode("模板", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");// 写入ExcelEasyExcel.write(response.getOutputStream(), ImportVo.class).autoCloseStream(true).registerWriteHandler(new DynamicDropDownHandler(applicationContext)).sheet("Sheet").doWrite(Collections.singletonList(Collections.emptyList())); } catch (Exception e) {throw new RuntimeException(e);}}

实体类

public class ImportVo {@ExcelProperty(value = "动态数据下拉")@ExcelDropDown(sourceMethod = "getNameList")private String name;@ExcelProperty(value = "性别")@ExcelDropDown(source = {"男","女"})private String sex;
}

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

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

相关文章

第15周:注意力汇聚:Nadaraya-Watson 核回归

注意力汇聚&#xff1a;Nadaraya-Watson 核回归 Nadaraya-Watson 核回归是一个经典的注意力机制模型&#xff0c;它展示了如何通过注意力权重来对输入数据进行加权平均。以下是该内容的核心总结&#xff1a; 关键概念 注意力机制框架&#xff1a;由查询&#xff08;自主提示…

adb devices报错 ADB server didn‘t ACK

ubuntu下连接手机首次使用adb devices 报错ADB server didn’t ACK adb devices * daemon not running; starting now at tcp:5037 ADB server didnt ACK Full server startup log: /tmp/adb.1000.log Server had pid: 52986 --- adb starting (pid 52986) --- 04-03 17:23:23…

Mac下Homebrew的安装与使用

Mac下Homebrew的安装与使用 一蓑烟羽 关注 2017.10.19 11:59* 字数 515 阅读 7684评论 0喜欢 3 Homebrew简介&#xff0c;安装与使用 简介 Homebrew 官方网站 Homebrew是一个包管理器&#xff0c;用于安装Apple没有预装但你需要的UNIX工具。&#xff08;比如著名的wget&am…

非常适合做后台项目的go脚手架

分享一个非常适合做后台脚手架的go项目&#xff0c;该项目使用gin作为mvc框架搭建。她就是Gin-vue-admin。该一个基于 vue 和 gin 开发的全栈前后端分离的开发基础平台&#xff0c;集成jwt鉴权&#xff0c;动态路由&#xff0c;动态菜单&#xff0c;casbin鉴权&#xff0c;表单…

优化 Django 数据库查询

优化 Django 数据库查询 推荐超级课程: 本地离线DeepSeek AI方案部署实战教程【完全版】Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战目录 优化 Django 数据库查询**理解 N+1 查询问题****`select_related`:外键的急加载**示例何时使用 `select_re…

大数据(5)Spark部署核弹级避坑指南:从高并发集群调优到源码级安全加固(附万亿级日志分析实战+智能运维巡检系统)

目录 背景一、Spark核心架构拆解1. 分布式计算五层模型 二、五步军工级部署阶段1&#xff1a;环境核弹级校验阶段2&#xff1a;集群拓扑构建阶段3&#xff1a;黄金配置模板阶段4&#xff1a;高可用启停阶段5&#xff1a;安全加固方案 三、万亿级日志分析实战1. 案例背景&#x…

【学Rust写CAD】36 颜色插值函数(alpha256.rs补充方法)

源码 pub fn alpha_lerp(self,src: Argb, dst: Argb, clip: u32) -> Argb {self.alpha_mul_256(clip).lerp(src, dst)}这个函数 alpha_lerp 是一个颜色插值&#xff08;线性插值&#xff0c;lerp&#xff09;函数&#xff0c;它结合了透明度混合&#xff08;alpha_mul_256&…

解决Ubuntu系统鼠标不流畅的问题

电脑是联想的台式组装机&#xff0c;安装ubuntu系统&#xff08;不管是16、18、20、22&#xff09;后&#xff0c;鼠标都不流畅。最近几天想解决这个问题&#xff0c;于是怀疑到了显卡驱动上。怀疑之前一直用的是集成显卡&#xff0c;而不是独立显卡&#xff0c;毕竟2060的显卡…

oracle asm 相关命令和查询视图

有关asm磁盘的命令 添加磁盘 alter diskgroup data1 add disk /devices/diska*;---runs with a rebalance power of 5 , and dose not return until the rebalance operation is completealter diskgroup data1 add disk /devices/diskd* rebalance power 5 wait;查询 select …

C++基于rapidjson的Json与结构体互相转换

简介 使用rapidjson库进行封装&#xff0c;实现了使用C对结构体数据和json字符串进行互相转换的功能。最短只需要使用两行代码即可无痛完成结构体数据转换为Json字符串。 支持std::string、数组、POD数据&#xff08;int,float,double等&#xff09;、std::vector、嵌套结构体…

Python爬虫HTTP代理使用教程:突破反爬的实战指南

目录 一、代理原理&#xff1a;给爬虫穿上"隐身衣" 二、代理类型选择指南 三、代码实战&#xff1a;三行代码实现代理设置 四、代理池管理&#xff1a;打造智能IP仓库 代理验证机制 动态切换策略 自动重试装饰器 五、反反爬对抗技巧 请求头伪装 访问频率控…

STM32江科大----IIC

声明&#xff1a;本人跟随b站江科大学习&#xff0c;本文章是观看完视频后的一些个人总结和经验分享&#xff0c;也同时为了方便日后的复习&#xff0c;如果有错误请各位大佬指出&#xff0c;如果对你有帮助可以点个赞小小鼓励一下&#xff0c;本文章建议配合原视频使用❤️ 如…

使用 React 和 Konva 实现一个在线画板组件

文章目录 一、前言二、Konva.js 介绍三、创建 React 画板项目3.1 安装依赖3.2 创建 CanvasBoard 组件 四、增加画布控制功能4.1 清空画布4.2 撤销 & 重做功能 五、增加颜色和画笔大小选择5.1 选择颜色5.2 选择画笔大小 六、最终效果七、总结 一、前言 在线画板是许多应用&…

服务器配置虚拟IP

服务器配置虚拟IP的核心步骤取决于具体场景&#xff0c;主要包括本地单机多IP配置和高可用集群下的虚拟IP管理两种模式。‌ 一、本地虚拟IP配置&#xff08;单服务器多IP&#xff09; ‌基于Linux系统‌&#xff1a; ‌确认网络接口‌&#xff1a;使用 ip addr 或 ifconfig 查…

C++ —— 文件操作(流式操作)

C —— 文件操作&#xff08;流式操作&#xff09; ofstream文件创建文件写入 ofstream 文件打开模式std::ios::out 写入模式std::ios::app 追加模式std::ios::trunc 截断std::ios::binary 二进制std::ios::ate at the end模式 ifstreamstd::ios::in 读取模式&#xff08;默认&…

【Cursor】打开Vscode设置

在这里打开设置界面 打开设置json

智能指针和STL库学习思维导图和练习

思维导图&#xff1a; #include <iostream> #include <vector> #include <string> using namespace std;// 用户结构体 struct User {string username;string password; };vector<User> users; // 存储所有注册用户// 使用迭代器查找用户名是否存在 ve…

前端工具方法整理

文章目录 1.在数组中找到匹配项&#xff0c;然后创建新对象2.对象转JSON字符串3.JSON字符串转JSON对象4.有个响应式对象&#xff0c;然后想清空所有属性5.判断参数不为空6.格式化字符串7.解析数组内容用逗号拼接8.刷新整个页面 1.在数组中找到匹配项&#xff0c;然后创建新对象…

状态空间建模与极点配置 —— 理论、案例与交互式 GUI 实现

目录 状态空间建模与极点配置 —— 理论、案例与交互式 GUI 实现一、引言二、状态空间建模的基本理论2.1 状态空间模型的优势2.2 状态空间模型的物理意义三、极点配置的理论与方法3.1 闭环系统的状态反馈3.2 极点配置条件与方法3.3 设计流程四、状态空间建模与极点配置的优缺点…

仿modou库one thread one loop式并发服务器

源码&#xff1a;田某super/moduo 目录 SERVER模块&#xff1a; Buffer模块&#xff1a; Socket模块&#xff1a; Channel模块&#xff1a; Connection模块&#xff1a; Acceptor模块&#xff1a; TimerQueue模块&#xff1a; Poller模块&#xff1a; EventLoop模块&a…