apache poi 实现下拉框联动校验

apache poi 提供了 DataValidation​ 接口 让我们可以轻松实现 Excel 下拉框数据局校验。但是下拉框联动校验是无法直接通过 DataValidation ​实现,所以我们可以通过其他方式间接实现。

步骤如下:

  1. 创建一个隐藏 sheet
 private static void createHiddenSheet(List<String> provinceList, Map<String, String[]> regionMap, Workbook workbook) {String hiddenSheetName = "region";Sheet hiddenSheet = workbook.createSheet(hiddenSheetName);// 这里也可以设置 hidden 为 false 这样可以直接看到 sheet 内容workbook.setSheetHidden(workbook.getSheetIndex(hiddenSheet), true);}
  1. 将数据放入隐藏 sheet
        int rowNum = 0;// 第一行存放省数据Row row = hiddenSheet.createRow(rowNum);for (int i = 0; i < provinceList.size(); i++) {Cell cell = row.createCell(i);cell.setCellValue(provinceList.get(i));}rowNum++;for (String key : regionMap.keySet()) {String[] dataArray = regionMap.get(key);// 循环创建行,每行存放一个数组row = hiddenSheet.createRow(rowNum);// key 放在每行第一个,value 放在每行的后面Cell keyCell = row.createCell(0);keyCell.setCellValue(key);for (int i = 0, length = dataArray.length; i < length; i++) {Cell cell = row.createCell(i + 1);cell.setCellValue(dataArray[i]);}Name name = workbook.createName();// 将key 设置为下拉框的keyname.setNameName(key);String formula = hiddenSheetName + "!$B$" + (rowNum + 1) + ":$" + (convertNumberToLetter(dataArray.length + 1)) + "$" + (rowNum + 1);name.setRefersToFormula(formula);// 可以将formula 放在最后一列Cell formulaCell = row.createCell(dataArray.length + 1);formulaCell.setCellValue(formula);rowNum++;}
  1. 在主 sheet 中使用 formula 来使用隐藏 sheet 的数据
    DataValidationHelper helper = mainSheet.getDataValidationHelper();// 设置省份下拉框CellRangeAddressList provRangeAddressList = new CellRangeAddressList(1, 1000, 0, 0);// formula 为  region!$A$1:$E$1DataValidationConstraint dvConstraint = helper.createFormulaListConstraint("region!$A$1:$" + (convertNumberToLetter(provinceList.size())) + "$1");DataValidation provinceDataValidation = helper.createValidation(dvConstraint, provRangeAddressList);provinceDataValidation.setSuppressDropDownArrow(true);mainSheet.addValidationData(provinceDataValidation);
  1. 设置联动下拉框 DataValidation
 // 设置市下拉框  firstCol lastCol 根据实际情况设置CellRangeAddressList cityRange = new CellRangeAddressList(1, 1000, 1, 1);DataValidationConstraint cityConstraint = helper.createFormulaListConstraint("INDIRECT(A2)");DataValidation cityValidation = helper.createValidation(cityConstraint, cityRange);mainSheet.addValidationData(cityValidation);// 设置县下拉框 firstCol lastCol 根据实际情况设置CellRangeAddressList districtRange = new CellRangeAddressList(1, 1000, 2, 2);DataValidation districtValidation = helper.createValidation(helper.createFormulaListConstraint("INDIRECT(B2)"), districtRange);mainSheet.addValidationData(districtValidation);
  1. 完整代码如下:
package com.shang;import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.FileOutputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/**
* @author: shangwei
* @date: 2024/11/3 13:01
*/
public class ExcelUtil {public static void createExcel(String path, List<String> provinceList, Map<String, String[]> regionMap) {try {Workbook workbook = new XSSFWorkbook();createHiddenSheet(provinceList, regionMap, workbook);Sheet mainSheet = workbook.createSheet("mainSheet");// 主sheet 第一行数据String[] titles = {"省", "市", "县"};int rowNum = 0;Row row = mainSheet.createRow(rowNum);for (int i = 0; i < titles.length; i++) {Cell cell = row.createCell(i);cell.setCellValue(titles[i]);}DataValidationHelper helper = mainSheet.getDataValidationHelper();// 设置省份下拉框CellRangeAddressList provRangeAddressList = new CellRangeAddressList(1, 1000, 0, 0);// formula 为  region!$A$1:$E$1DataValidationConstraint dvConstraint = helper.createFormulaListConstraint("region!$A$1:$" + (convertNumberToLetter(provinceList.size())) + "$1");DataValidation provinceDataValidation = helper.createValidation(dvConstraint, provRangeAddressList);provinceDataValidation.setSuppressDropDownArrow(true);mainSheet.addValidationData(provinceDataValidation);// 设置市下拉框  firstCol lastCol 根据实际情况设置CellRangeAddressList cityRange = new CellRangeAddressList(1, 1000, 1, 1);DataValidationConstraint cityConstraint = helper.createFormulaListConstraint("INDIRECT(A2)");DataValidation cityValidation = helper.createValidation(cityConstraint, cityRange);mainSheet.addValidationData(cityValidation);// 设置县下拉框 firstCol lastCol 根据实际情况设置CellRangeAddressList districtRange = new CellRangeAddressList(1, 1000, 2, 2);DataValidation districtValidation = helper.createValidation(helper.createFormulaListConstraint("INDIRECT(B2)"), districtRange);mainSheet.addValidationData(districtValidation);FileOutputStream fileOutputStream = new FileOutputStream(path);workbook.write(fileOutputStream);} catch (Exception e) {e.printStackTrace();}}private static void createHiddenSheet(List<String> provinceList, Map<String, String[]> regionMap, Workbook workbook) {String hiddenSheetName = "region";Sheet hiddenSheet = workbook.createSheet(hiddenSheetName);int rowNum = 0;// 第一行存放省数据Row row = hiddenSheet.createRow(rowNum);for (int i = 0; i < provinceList.size(); i++) {Cell cell = row.createCell(i);cell.setCellValue(provinceList.get(i));}rowNum++;for (String key : regionMap.keySet()) {String[] dataArray = regionMap.get(key);// 循环创建行,每行存放一个数组row = hiddenSheet.createRow(rowNum);// key 放在每行第一个,value 放在每行的后面Cell keyCell = row.createCell(0);keyCell.setCellValue(key);for (int i = 0, length = dataArray.length; i < length; i++) {Cell cell = row.createCell(i + 1);cell.setCellValue(dataArray[i]);}Name name = workbook.createName();// 将key 设置为下拉框的keyname.setNameName(key);String formula = hiddenSheetName + "!$B$" + (rowNum + 1) + ":$" + (convertNumberToLetter(dataArray.length + 1)) + "$" + (rowNum + 1);name.setRefersToFormula(formula);// 可以将formula 放在最后一列Cell formulaCell = row.createCell(dataArray.length + 1);formulaCell.setCellValue(formula);rowNum++;}// 这里也可以设置 hidden 为 false 这样可以直接看到 sheet 内容workbook.setSheetHidden(workbook.getSheetIndex(hiddenSheet), true);}/*** 将数字 1 到 26 转换为对应的字母 A 到 Z。** @param number 要转换的数字,范围是 1 到 26。* @return 对应的字母。*/public static String convertNumberToLetter(int number) {if (number < 1 || number > 26) {throw new IllegalArgumentException("Number must be between 1 and 26");}return String.valueOf((char) ('A' + number - 1));}public static void main(String[] args) {Map<String, String[]> regionMap = new HashMap<>();List<String> provinceList = Arrays.asList("湖北省", "湖南省", "广东省", "江苏省", "浙江省");regionMap.put("湖北省", new String[]{"武汉市", "黄石市", "十堰市", "宜昌市", "襄樊市", "鄂州市", "荆门市", "孝感市", "荆州市", "黄冈市", "咸宁市", "随州市"});regionMap.put("湖南省", new String[]{"长沙市", "株洲市", "湘潭市", "衡阳市", "邵阳市", "岳阳市", "常德市", "张家界市", "益阳市", "郴州市", "永州市", "怀化市"});regionMap.put("广东省", new String[]{"广州市", "韶关市", "深圳市", "珠海市", "汕头市", "佛山市", "江门市", "湛江市", "茂名市", "肇庆市", "惠州市", "梅州市", "汕尾市", "河源市", "阳江市", "清远市"});regionMap.put("江苏省", new String[]{"南京市", "无锡市", "徐州市", "常州市", "苏州市", "南通市", "连云港市", "淮安市", "盐城市", "扬州市", "镇江市", "泰州市", "宿迁市"});regionMap.put("浙江省", new String[]{"杭州市", "宁波市", "温州市", "嘉兴市", "湖州市", "绍兴市", "金华市", "衢州市", "舟山市", "台州市", "丽水市"});regionMap.put("武汉市", new String[]{"江岸镇", "江汉镇", "江夏镇", "硚口镇", "武昌镇", "江夏镇"});regionMap.put("黄石市", new String[]{"黄石港镇", "西塞山镇", "下陆镇", "大冶镇", "大冶镇"});String path = "/Users/shangwei/Desktop/example" + System.currentTimeMillis() + ".xlsx";createExcel(path, provinceList, regionMap);}}

相关 Maven 依赖

<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.3</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version></dependency>

运行截图:

​​运行截图

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

盘点和嗨格式一样好用的10款数据恢复!!

亲爱的朋友们&#xff0c;相信大家都知道&#xff0c;一旦不小心删除了重要文件或者遇到了硬盘故障&#xff0c;心情简直如同坐过山车一般此起彼伏&#xff0c;那么这个时候就需要一款好的数据恢复工具来解救我们的数据危机。今天就来给大家推荐嗨格式数据恢复以及另外这10款我…

【Python】怎么创建一个新的conda环境,并在其中安装所需的软件包

最近在运行前同事留下的包的时候&#xff0c;遇到了numpy包和pandas包不匹配的问题&#xff0c;见前一篇&#xff1a; 屋漏偏逢连夜雨&#xff0c;今天打开spyder的时候&#xff0c;也没法运行spyder了。 于是&#xff0c;痛定思痛&#xff0c;打算换一个conda环境&#xff0…

通讯录(C 语言)

目录 一、通讯录设计思路1. 伪代码设计思路2. 代码设计思路 二、代码实现三、程序运行演示四、整体分析 一、通讯录设计思路 1. 伪代码设计思路 通讯录可以用来存储 100 个人的信息&#xff0c;每个人的信息包括&#xff1a;姓名、性别、年龄、电话、住址。 提供方法&#x…

海明码校验和纠错

1.计算1011海明码的校验位 根据公式nk<-1 &#xff08;n是信息码位数&#xff0c;1011就是4&#xff09; 则 k3 43<-1 由上可知校验码有3个 又因为 4 2 1 可以列出下列表格 7654321d3d2d1x2d0x1x01011 x0 x1 x2 分别为3个校验码的位置 又因为 7421 642 541…

SpringMVC的执行流程以及运行原理

文章目录 SpringMVC的执行流程以及运行原理一、引言二、SpringMVC核心组件与执行流程1、SpringMVC核心组件1.1、DispatcherServlet配置 2、SpringMVC执行流程 三、SpringMVC配置文件及注解四、总结 SpringMVC的执行流程以及运行原理 一、引言 SpringMVC作为Spring框架的核心模…

Unity XR Interaction Toolkit 开发教程(4)XR Origin:追踪参考系与相机高度【3.0以上版本】

获取完整课程以及答疑&#xff0c;工程文件下载&#xff1a; https://www.spatialxr.tech/ 视频试看链接&#xff1a; 4.XR Origin&#xff1a;追踪参考系与相机高度【Unity XR Interaction Toolkit 跨平台开发教程】&#xff08;3.0以上版本&#xff09; 系列教程专栏&#…

【基于Zynq FPGA对雷龙SD NAND的测试】

一、SD NAND 特征 1.1 SD 卡简介 雷龙的 SD NAND 有很多型号&#xff0c;在测试中使用的是 CSNP4GCR01-AMW 与 CSNP32GCR01-AOW。芯片是基于 NAND FLASH 和 SD 控制器实现的 SD 卡。具有强大的坏块管理和纠错功能&#xff0c;并且在意外掉电的情况下同样能保证数据的安全。 …

小程序与服务器通信webSocket和UDPSocket

UDPSocket 官方文档链接UDPSocket webSocket 官方文档链接 WebSocket 任务 先用webSocket 测试成功后&#xff0c;由于WSS的问题最后决定用UDPSocket&#xff0c;两个都记录一下。 UDPSocket 项目里主要就使用了以下几个方法, 先用wx.createUDPSocket创建UDP Socket 实例&a…

HTMLCSS:爱上班的猫咪

这段HTML和CSS代码是一个SVG动画的示例&#xff0c;它描述了一个包含猫咪和笔记本电脑的复杂场景 HTML <div class"content"><div class"container"><svg id"bongo-cat" xmlns"http://www.w3.org/2000/svg" xmlns:x…

使用SearXNG-搭建个人搜索引擎(附国内可用Docker镜像源)

介绍 SearXNG是聚合了七十多种搜索服务的开源搜索工具。我们可以匿名浏览页面&#xff0c;不会被记录和追踪。作为开发者&#xff0c;SearXNG也提供了清晰的API接口以及完整的开发文档。 部署 我们可以很方便地使用Docker和Docker compose部署SearXNG。下面给出Docker部署Se…

基于前后端分离架构,SaaS云平台与私有云部署的智慧校园源码,java电子班牌源码

基于前后端分离架构&#xff0c;SaaS云平台与私有云部署的智慧校园源码&#xff0c;java电子班牌源码&#xff0c;自主研发&#xff0c;自主版权&#xff0c;上百个学校应用案例&#xff0c;支持二次开发。 在信息技术飞速发展的今天&#xff0c;教育领域也迎来了一场革命性的变…

java.lang.NoClassDefFoundError: kotlin/jvm/JvmInline

springboot项目&#xff0c;调用接口时&#xff0c;报这个错误&#xff0c;跟踪断点发现数据库也查询到了数据&#xff0c;就是在返回时报错了&#xff0c;后来一看是pom.xml中引入了 <dependency><groupId>com.fasterxml.jackson.module</groupId><artif…

yolov8涨点系列之替换幽灵卷积GhostConv

文章目录 核心思想主要步骤优势yolov8.yaml文件增加CBAMyolov8.yamlyolov8.yaml将Conv卷积替换成GhostConv 幽灵卷积&#xff08;Ghost Conv&#xff09;是一种新颖的卷积操作方法&#xff0c;旨在解决传统卷积神经网络中参数量和计算量过大的问题&#xff0c;尤其适用于资源受…

MongoDB Shell 基本命令(三)聚合管道

管道含义 类似Linux中的管道&#xff0c;前一个命令的输出作为后一个命令的输入。 显示网络连接、路由表和网络接口统计信息 netstat -ano -netstat:network statistics 网络统计 -a:显示所有连接和监听端口&#xff0c;包括所有活动的TCP和UDP连接。 -n:以数字形式显示地址…

C++重启/秋招已保底备战春招

C面向对象高级开发&#xff08;上&#xff09;学习笔记 第三节&#xff1a; 问题1&#xff1a;C中对构造函数使用初始列和函数体中赋值结果是一样的&#xff0c;但是为什么使用初始列的形式更好 解答&#xff1a;最重要的还是1和2&#xff0c;效率更高避免调用默认构造函数&…

云渲染怎么用?一片看懂云渲染渲染农场渲染100操作指南

就拿“渲染 100”云渲染来说吧&#xff0c;它的使用教程是这样的&#xff1a; 1.安装客户端 在渲染之前要准备好安装“渲染 100”云渲染客户端&#xff0c;注册个账号然后登录客户端。 您可以在浏览器里打开渲染 100 云渲染的官网&#xff1a;xuanran100.com/?ycode5858, 在…

私有化视频平台EasyCVR海康大华宇视视频平台视频诊断技术是如何实时监测视频质量的?

在现代视频监控系统中&#xff0c;确保视频流的质量和稳定性至关重要。随着技术的进步&#xff0c;视频诊断技术已经成为实时监测视频质量的关键工具。这种技术通过智能分析算法对视频流进行实时评估和处理&#xff0c;能够自动识别视频中的各种质量问题&#xff0c;并给出相应…

ECRS工时分析软件:工业工程优化利器,引领生产工序革新

在竞争日益激烈的工业领域&#xff0c;生产效率的提升成为企业持续发展的关键。为此&#xff0c;工业工程学中的程序分析原则应运而生&#xff0c;其中最为核心的便是ECRS四大原则——取消、合并、调整顺序和简化。这些原则为生产工序的优化提供了有力的指导&#xff0c;旨在消…

端侧小模型新星,SmolLM2 1.7B击败了Llama 3.2、Qwen 2.5

SmolLM2开源了&#xff1a;更快、更好、更便宜&#xff0c; 包含三个尺寸&#xff1a;135M、360M 和 1.7B。 端侧小型语言模型新星——SmolLM2 1.7B击败了Qwen 2.5 1.5B和Llama 3.2 1B&#xff1a; Apache 2.0许可 训练于11万亿个令牌 在FineWeb-Edu、DCLM、The Stack以及新的…

[LeetCode-45] 基于贪心算法的跳跃游戏 II-最少跳跃次数的求解(C语言版)

/* 题目出处&#xff1a;LeetCode 题目序号&#xff1a;45. 跳跃游戏 II 题目叙述&#xff1a;给定一个长度为 n 的整数数组 nums。初始位置为 nums[0]。每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转…