Apache Poi 实现Excel多级联动下拉框
由于最近做的功能,需要将接口返回的数据列表,输出到excel中,以供后续导入,且网上现有的封装,使用起来都较为麻烦,故参考已有做法封装了工具类。
使用apache poi实现excel联动下拉框思路
- 创建隐藏单元格,存储下拉数据
- 创建名称管理器
- 使用indirect表达式进行联动
添加依赖
<!--Java程序对Microsoft Office格式档案读和写的功能-->
<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.2.2</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.2</version>
</dependency>
直接上代码
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.*;import java.util.List;
import java.util.Map;
import java.util.Set;/*** excel验证工具类** @author chenchuancheng github.com/meethigher* @since 2023/08/20 23:55*/
public class ExcelValidationUtils {private static final int minRow = 1;private static final int maxRow = 100;private static final boolean debugHideSheet = true;/*** 创建一个xlsx** @return {@link XSSFWorkbook}*/public static XSSFWorkbook createOneXLSX() {return new XSSFWorkbook();}/*** 为xlsx添加一个sheet** @param wb xlsx* @param sheetName sheet名* @param headers 首行标题头* @return sheet*/public static XSSFSheet addOneSheet(XSSFWorkbook wb, String sheetName, String[] headers) {XSSFSheet st = wb.createSheet(sheetName);//表头样式CellStyle style = wb.createCellStyle();style.setAlignment(HorizontalAlignment.CENTER); // 创建一个居中格式//字体样式Font fontStyle = wb.createFont();fontStyle.setFontName("微软雅黑");fontStyle.setFontHeightInPoints((short) 12);style.setFont(fontStyle);//单元格格式为文本XSSFDataFormat format = wb.createDataFormat();style.setDataFormat(format.getFormat("@"));//写标题XSSFRow row = st.createRow(0);st.createFreezePane(0, 1, 0, 1);for (int i = 0; i < headers.length; i++) {String value = headers[i];XSSFCell cell = row.createCell(i);st.setColumnWidth(i, value.length() * 1000);cell.setCellStyle(style);st.setDefaultColumnStyle(i, style);cell.setCellValue(value);}return st;}/*** 添加两层级联数据** @param wb xlsx* @param targetSheet 目标sheet* @param linkageData 两层级联数据* @param parentCol 父列* @param childCol 孩子列* @param parentColIdentifier 父列标识符* @return {@link XSSFSheet}*/public static XSSFSheet addLinkageDataValidation(XSSFWorkbook wb, XSSFSheet targetSheet, Map<String, List<String>> linkageData,int parentCol, int childCol, String parentColIdentifier) {XSSFSheet hideSt = wb.createSheet();wb.setSheetHidden(wb.getSheetIndex(hideSt), !debugHideSheet);int rowId = 0;Set<String> keySet = linkageData.keySet();for (String parent : keySet) {List<String> sonList = linkageData.get(parent);XSSFRow row = hideSt.createRow(rowId++);row.createCell(0).setCellValue(parent);for (int i = 0; i < sonList.size(); i++) {XSSFCell cell = row.createCell(i + 1);cell.setCellValue(sonList.get(i));}// 添加名称管理器,1表示b列,从b列开始往后,都是子级String range = getRange(1, rowId, sonList.size());Name name = wb.createName();name.setNameName(parent);String formula = hideSt.getSheetName() + "!" + range;name.setRefersToFormula(formula);}//创建表达式校验XSSFDataValidationHelper helper = new XSSFDataValidationHelper(targetSheet);// //父级校验,如需生成更多,用户手动拖拽下拉即可。此操作会导致数组内容总长度超过255时报错
// DataValidation parentValidation = helper.createValidation(helper.createExplicitListConstraint(keySet.toArray(new String[0])),
// new CellRangeAddressList(minRow, maxRow, parentCol, parentCol));
// parentValidation.createErrorBox("错误", "请选择正确的父级类型");
// parentValidation.setShowErrorBox(true);
// parentValidation.setSuppressDropDownArrow(true);
// targetSheet.addValidationData(parentValidation);//解决长度为255的问题Name name = wb.createName();name.setNameName(hideSt.getSheetName());name.setRefersToFormula(hideSt.getSheetName() + "!$A$1:$A$" + keySet.size());DataValidation parentValidation = helper.createValidation(helper.createFormulaListConstraint(hideSt.getSheetName()), new CellRangeAddressList(minRow, maxRow, parentCol, parentCol));parentValidation.createErrorBox("错误", "请选择正确的父级类型");parentValidation.setShowErrorBox(true);targetSheet.addValidationData(parentValidation);//子级校验,如需生成更多,用户手动拖拽下拉即可for (int i = minRow; i < maxRow; i++) {DataValidation childValidation = helper.createValidation(helper.createFormulaListConstraint("INDIRECT(" + parentColIdentifier + "" + (i + 1) + ")"),new CellRangeAddressList(i, i, childCol, childCol));childValidation.createErrorBox("错误", "请选择正确的子级类型");childValidation.setShowErrorBox(true);childValidation.setSuppressDropDownArrow(true);targetSheet.addValidationData(childValidation);}return hideSt;}/*** 添加简单下拉列表验证-下拉列表总内容不超过255字符** @param st sheet* @param dropDownList 下拉列表数据* @param firstCol 开始列,从0开始* @param lastCol 结束列,从0开始*/public static void addSimpleDropDownListValidation(XSSFSheet st, String[] dropDownList, int firstCol, int lastCol) {XSSFDataValidationHelper helper = new XSSFDataValidationHelper(st);XSSFDataValidationConstraint constraint = (XSSFDataValidationConstraint) helper.createExplicitListConstraint(dropDownList);CellRangeAddressList addressList = new CellRangeAddressList(minRow, maxRow, firstCol, lastCol);XSSFDataValidation validation = (XSSFDataValidation) helper.createValidation(constraint, addressList);validation.setSuppressDropDownArrow(true);validation.setShowErrorBox(true);st.addValidationData(validation);}/*** 添加复杂下拉列表验证-下拉列表总内容允许超过255字符** @param wb xlsx* @param dropDownList 下拉列表数据* @param firstCol 开始列,从0开始* @param lastCol 结束列,从0开始*/public static void addComplexDropDownListValidation(XSSFWorkbook wb, XSSFSheet st, String[] dropDownList, int firstCol, int lastCol) {XSSFSheet hideSt = wb.createSheet();wb.setSheetHidden(wb.getSheetIndex(hideSt), !debugHideSheet);XSSFDataValidationHelper helper = new XSSFDataValidationHelper(st);for (int i = 0, length = dropDownList.length; i < length; i++) {String value = dropDownList[i];XSSFRow row = hideSt.createRow(i);XSSFCell cell = row.createCell(0);cell.setCellValue(value);}//解决长度为255的问题Name name = wb.createName();name.setNameName(hideSt.getSheetName());name.setRefersToFormula(hideSt.getSheetName() + "!$A$1:$A$" + dropDownList.length);DataValidation parentValidation = helper.createValidation(helper.createFormulaListConstraint(hideSt.getSheetName()), new CellRangeAddressList(minRow, maxRow, firstCol, lastCol));parentValidation.createErrorBox("错误", "请选择正确的类型");parentValidation.setShowErrorBox(true);st.addValidationData(parentValidation);}/*** 计算formula** @param offset 偏移量,如果给0,表示从A列开始,1,就是从B列* @param rowId 第几行* @param colCount 一共多少列* @return 如果给入参 1,1,10. 表示从B1-K1。最终返回 $B$1:$K$1*/private static String getRange(int offset, int rowId, int colCount) {char start = (char) ('A' + offset);if (colCount <= 25) {char end = (char) (start + colCount - 1);return "$" + start + "$" + rowId + ":$" + end + "$" + rowId;} else {char endPrefix = 'A', endSuffix;if ((colCount - 25) / 26 == 0 || colCount == 51) {// 26-51之间,包括边界(仅两次字母表计算)if ((colCount - 25) % 26 == 0) {// 边界值endSuffix = (char) ('A' + 25);} else {endSuffix = (char) ('A' + (colCount - 25) % 26 - 1);}} else {// 51以上if ((colCount - 25) % 26 == 0) {endSuffix = (char) ('A' + 25);endPrefix = (char) (endPrefix + (colCount - 25) / 26 - 1);} else {endSuffix = (char) ('A' + (colCount - 25) % 26 - 1);endPrefix = (char) (endPrefix + (colCount - 25) / 26);}}return "$" + start + "$" + rowId + ":$" + endPrefix + endSuffix + "$" + rowId;}}
}
使用示例
public class TestExportExcelWithValidation {private final static String[] headers = new String[]{"性别","省","市","区",};private static Map<String, List<String>> 省级() {Map<String, List<String>> map = new HashMap<>();map.put("湖北省", Arrays.asList("武汉市", "襄阳市"));map.put("吉林省", Arrays.asList("长春市", "吉林市"));return map;}private static Map<String, List<String>> 市级() {Map<String, List<String>> map = new HashMap<>();map.put("武汉市", Arrays.asList("洪山区", "江夏区"));map.put("长春市", Arrays.asList("宽城区", "南关区"));return map;}public static void main(String[] args) throws Exception {XSSFWorkbook wb = createOneXLSX();XSSFSheet st = addOneSheet(wb, "data", headers);addSimpleDropDownListValidation(st, new String[]{"男", "女"}, 0, 0);addLinkageDataValidation(wb, st, 省级(), 1, 2, "B");addLinkageDataValidation(wb, st, 市级(), 2, 3, "C");wb.write(new FileOutputStream("aaa.xlsx"));}
}
最终结果展示如图

idation(st, new String[]{“男”, “女”}, 0, 0);
addLinkageDataValidation(wb, st, 省级(), 1, 2, “B”);
addLinkageDataValidation(wb, st, 市级(), 2, 3, “C”);
wb.write(new FileOutputStream("aaa.xlsx"));
}
}
最终结果展示如图[外链图片转存中...(img-zQCvRcAm-1693070160923)]
相关文章:
Apache Poi 实现Excel多级联动下拉框
由于最近做的功能,需要将接口返回的数据列表,输出到excel中,以供后续导入,且网上现有的封装,使用起来都较为麻烦,故参考已有做法封装了工具类。 使用apache poi实现excel联动下拉框思路 创建隐藏单元格&a…...
常见的 HTML<meta> 标签的 name 属性及其作用
HTML中的 <meta> 标签可以通过 name 属性提供元数据,这些元数据可以用于指定有关文档的信息,以及控制浏览器和搜索引擎的行为。name 属性通常与其他属性一起使用,如 content、charset、http-equiv 等,以提供更具体的元数据信…...
【网络安全】理解报文加密、数字签名能解决的实际问题
文章目录 前言1. 防止报文泄露 —— 加密体系的出现1.1 理解非对称加密体系的实施难点1.2 加密体系的实际应用 2. 防止报文被篡改 —— 数字签名的出现2.1 数字签名的原理2.2 数字签名的实施难点2.2 数字签名的实际应用 —— 引入摘要算法 3. 实体鉴别 —— CA证书 后记 前言 …...
linux中安装nodejs,卸载nodejs,更新nodejs
卸载nodejs 卸载node sudo apt-get remove nodejs清理掉自动安装的并且不需要软件包 sudo apt autoremove查看node相关的文件 sudo whereis node如果有文件需要手动删除文件 删除该文件命令 sudo rm -rf /usr/local/bin/node在此查看node -v 是未找到,说明你已经…...
浅谈Python网络爬虫应对反爬虫的技术对抗
在当今信息时代,数据是非常宝贵的资源。而作为一名专业的 Python 网络爬虫程序猿,在进行网页数据采集时经常会遭遇到各种针对爬虫行为的阻碍和限制,这就需要我们掌握一些应对反爬机制的技术手段。本文将从不同层面介绍如何使用 Python 进行网…...
代理池在过程中一直运行
Hey,爬虫达人们!在爬虫的过程中,要保持代理池的稳定性可不容易。今天就来和大家分享一些实用经验,教你如何让代理池在爬虫过程中一直运行!方法简单易行,让你的爬虫工作更顺畅. 在进行爬虫工作时࿰…...
基于Java+SpringBoot+Vue前后端分离党员教育和管理系统设计和实现
博主介绍:✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专…...
【flutter直接上传图片到阿里云OSS】
flutter直接上传文件到阿里云需要获取凭证,通过调用阿里云获取凭证的接口能拿到下面这些参数 {"StatusCode": 200,"AccessKeyId": "STS.NSsrKZes4cqm.....","AccessKeySecret": "7eGnLZaEFsRCGYJAnrtdE9n....."…...
【MySQL系列】表的内连接和外连接学习
「前言」文章内容大致是对MySQL表的内连接和外连接。 「归属专栏」MySQL 「主页链接」个人主页 「笔者」枫叶先生(fy) 目录 一、内连接二、外连接2.1 左外连接2.2 右外连接 一、内连接 内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选,前面篇章学习的…...
C语言日常刷题 3
文章目录 题目答案与解析1234、5、6、 题目 1.已知函数的原型是: int fun(char b[10], int *a); ,设定义: char c[10];int d; ,正确的调用语句是( ) A: fun(c,&d); B: fun(c,d); C: fun(&c,&d…...
.net6中, 用数据属性事件触发 用httpclient向服务器提交Mes工单
MES开发中, 客户往往会要求 工单开始时记录工艺数据, 工单结束时将这些工艺数据回传到更上一级的WES系统中. 因为MES系统和PLC 是多线程读取, 所以加锁, 事件触发是常用手段. using MyWebApiTest.PLC; using MyWebApiTest.Service; using MyWebApiTest.Service.Entry; using M…...
sin(A)的意义
若存在矩阵A,则sin(A)表示对于矩阵A的每一个元素,进行对应的函数运算。 如:...
ctfshow-web14
0x00 前言 CTF 加解密合集CTF Web合集 0x01 题目 0x02 Write Up 首先看到这个,swith,那么直接输入4,则会打印$url的值 然后访问一下 查看一下,发现完整的请求是http://c7ff9ed6-dccd-4d01-907a-f1c61c016c15.challenge.ctf.sho…...
数据结构—循环队列(环形队列)
循环队列(环形队列) 循环队列的概念及结构循环队列的实现 循环队列的概念及结构 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。…...
vue3 实现按钮权限管理
在做后台管理系统时,经常会有权限管理的功能,这里来记录一下关于按钮权限管理的实现方法 1、自定义指令 v-permission。新建js文件用来写指令代码。 export default function btnPerms(app) {app.directive(permission, {mounted(el, binding) {if (!p…...
C语言练习4(巩固提升)
C语言练习4 选择题 前言 面对复杂变化的世界,人类社会向何处去?亚洲前途在哪里?我认为,回答这些时代之问,我们要不畏浮云遮望眼,善于拨云见日,把握历史规律,认清世界大势。 选择题 …...
将AI融入CG特效工作流;对谈Dify创始人张路宇;关于Llama 2的一切资源;普林斯顿LLM高阶课程;LLM当前的10大挑战 | ShowMeAI日报
👀日报&周刊合集 | 🎡生产力工具与行业应用大全 | 🧡 点赞关注评论拜托啦! 🤖 将AI融入CG特效工作流,体验极致的效率提升 BV1pP411r7HY 这是 B站UP主 特效小哥studio 和 拓星研究所 联合投稿的一个AI特…...
Vue2学习笔记のVue中的ajax
目录 Vue中的ajaxvue脚手架配置代理方法一方法二 插槽 hello, 这篇文章是Vue2学习笔记的第四篇,也是第四章:Vue中的ajax。 Vue中的ajax vue脚手架配置代理 方法一 在vue.config.js中添加如下配置: devServer:{proxy:"http://localho…...
C# 使用NPOI操作EXCEL
1.添加NOPI 引用->管理NuGet程序包->添加NOPI 2.相关程序集 3....
分布式 - 服务器Nginx:一小时入门系列之 return 指令
文章目录 1. return 指令语法2. return code URL 示例3. return code text 示例4. return URL 示例 1. return 指令语法 return指令用于立即停止当前请求的处理,并返回指定的HTTP状态码和响应头信息,它可以用于在Nginx中生成自定义错误页面,…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...
Linux部署私有文件管理系统MinIO
最近需要用到一个文件管理服务,但是又不想花钱,所以就想着自己搭建一个,刚好我们用的一个开源框架已经集成了MinIO,所以就选了这个 我这边对文件服务性能要求不是太高,单机版就可以 安装非常简单,几个命令就…...
[特殊字符] 手撸 Redis 互斥锁那些坑
📖 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作,想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁,也顺便跟 Redisson 的 RLock 机制对比了下,记录一波,别踩我踩过…...
简单介绍C++中 string与wstring
在C中,string和wstring是两种用于处理不同字符编码的字符串类型,分别基于char和wchar_t字符类型。以下是它们的详细说明和对比: 1. 基础定义 string 类型:std::string 字符类型:char(通常为8位)…...
C# WPF 左右布局实现学习笔记(1)
开发流程视频: https://www.youtube.com/watch?vCkHyDYeImjY&ab_channelC%23DesignPro Git源码: GitHub - CSharpDesignPro/Page-Navigation-using-MVVM: WPF - Page Navigation using MVVM 1. 新建工程 新建WPF应用(.NET Framework) 2.…...
