apache poi 实现下拉框联动校验

本贴最后更新于 192 天前,其中的信息可能已经时移世易

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); }
  2. 将数据放入隐藏 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 设置为下拉框的key name.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++; }
  3. 在主 sheet 中使用 formula 来使用隐藏 sheet 的数据

    DataValidationHelper helper = mainSheet.getDataValidationHelper(); // 设置省份下拉框 CellRangeAddressList provRangeAddressList = new CellRangeAddressList(1, 1000, 0, 0); // formula 为 region!$A$1:$E$1 DataValidationConstraint dvConstraint = helper.createFormulaListConstraint("region!$A$1:$" + (convertNumberToLetter(provinceList.size())) + "$1"); DataValidation provinceDataValidation = helper.createValidation(dvConstraint, provRangeAddressList); provinceDataValidation.setSuppressDropDownArrow(true); mainSheet.addValidationData(provinceDataValidation);
  4. 设置联动下拉框 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);
  5. 完整代码如下:

    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$1 DataValidationConstraint 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 设置为下拉框的key name.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>

运行截图:

image

  • POI
    23 引用 • 21 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3201 引用 • 8216 回帖
  • WebComponents

    Web Components 是 W3C 定义的标准,它给了前端开发者扩展浏览器标签的能力,可以方便地定制可复用组件,更好的进行模块化开发,解放了前端开发者的生产力。

    1 引用 • 8 关注
  • 小说

    小说是以刻画人物形象为中心,通过完整的故事情节和环境描写来反映社会生活的文学体裁。

    32 引用 • 108 回帖 • 1 关注
  • etcd

    etcd 是一个分布式、高可用的 key-value 数据存储,专门用于在分布式系统中保存关键数据。

    6 引用 • 26 回帖 • 543 关注
  • Maven

    Maven 是基于项目对象模型(POM)、通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

    188 引用 • 319 回帖 • 252 关注
  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    117 引用 • 99 回帖 • 201 关注
  • 房星科技

    房星网,我们不和没有钱的程序员谈理想,我们要让程序员又有理想又有钱。我们有雄厚的房地产行业线下资源,遍布昆明全城的 100 家门店、四千地产经纪人是我们坚实的后盾。

    6 引用 • 141 回帖 • 591 关注
  • CongSec

    本标签主要用于分享网络空间安全专业的学习笔记

    1 引用 • 1 回帖 • 31 关注
  • 笔记

    好记性不如烂笔头。

    310 引用 • 794 回帖
  • 书籍

    宋真宗赵恒曾经说过:“书中自有黄金屋,书中自有颜如玉。”

    78 引用 • 396 回帖
  • BND

    BND(Baidu Netdisk Downloader)是一款图形界面的百度网盘不限速下载器,支持 Windows、Linux 和 Mac,详细介绍请看这里

    107 引用 • 1281 回帖 • 35 关注
  • HHKB

    HHKB 是富士通的 Happy Hacking 系列电容键盘。电容键盘即无接点静电电容式键盘(Capacitive Keyboard)。

    5 引用 • 74 回帖 • 504 关注
  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    96 引用 • 155 回帖 • 4 关注
  • LeetCode

    LeetCode(力扣)是一个全球极客挚爱的高质量技术成长平台,想要学习和提升专业能力从这里开始,充足技术干货等你来啃,轻松拿下 Dream Offer!

    209 引用 • 72 回帖
  • CentOS

    CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise Linux 依照开放源代码规定释出的源代码所编译而成。由于出自同样的源代码,因此有些要求高度稳定的服务器以 CentOS 替代商业版的 Red Hat Enterprise Linux 使用。两者的不同在于 CentOS 并不包含封闭源代码软件。

    239 引用 • 224 回帖
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    499 引用 • 1395 回帖 • 246 关注
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    170 引用 • 1150 回帖
  • Mac

    Mac 是苹果公司自 1984 年起以“Macintosh”开始开发的个人消费型计算机,如:iMac、Mac mini、Macbook Air、Macbook Pro、Macbook、Mac Pro 等计算机。

    168 引用 • 597 回帖
  • Notion

    Notion - The all-in-one workspace for your notes, tasks, wikis, and databases.

    10 引用 • 77 回帖
  • WebClipper

    Web Clipper 是一款浏览器剪藏扩展,它可以帮助你把网页内容剪藏到本地。

    3 引用 • 9 回帖 • 1 关注
  • JetBrains

    JetBrains 是一家捷克的软件开发公司,该公司位于捷克的布拉格,并在俄国的圣彼得堡及美国麻州波士顿都设有办公室,该公司最为人所熟知的产品是 Java 编程语言开发撰写时所用的集成开发环境:IntelliJ IDEA

    18 引用 • 54 回帖 • 3 关注
  • 京东

    京东是中国最大的自营式电商企业,2015 年第一季度在中国自营式 B2C 电商市场的占有率为 56.3%。2014 年 5 月,京东在美国纳斯达克证券交易所正式挂牌上市(股票代码:JD),是中国第一个成功赴美上市的大型综合型电商平台,与腾讯、百度等中国互联网巨头共同跻身全球前十大互联网公司排行榜。

    14 引用 • 102 回帖 • 317 关注
  • sts
    2 引用 • 2 回帖 • 229 关注
  • CAP

    CAP 指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。

    12 引用 • 5 回帖 • 631 关注
  • Sublime

    Sublime Text 是一款可以用来写代码、写文章的文本编辑器。支持代码高亮、自动完成,还支持通过插件进行扩展。

    10 引用 • 5 回帖 • 3 关注
  • 域名

    域名(Domain Name),简称域名、网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。

    43 引用 • 208 回帖 • 1 关注
  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    286 引用 • 248 回帖