apache poi 实现下拉框联动校验

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

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 回帖

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    59 引用 • 25 回帖
  • Tomcat

    Tomcat 最早是由 Sun Microsystems 开发的一个 Servlet 容器,在 1999 年被捐献给 ASF(Apache Software Foundation),隶属于 Jakarta 项目,现在已经独立为一个顶级项目。Tomcat 主要实现了 JavaEE 中的 Servlet、JSP 规范,同时也提供 HTTP 服务,是市场上非常流行的 Java Web 容器。

    162 引用 • 529 回帖 • 10 关注
  • HBase

    HBase 是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文 “Bigtable:一个结构化数据的分布式存储系统”。就像 Bigtable 利用了 Google 文件系统所提供的分布式数据存储一样,HBase 在 Hadoop 之上提供了类似于 Bigtable 的能力。

    17 引用 • 6 回帖 • 72 关注
  • 运维

    互联网运维工作,以服务为中心,以稳定、安全、高效为三个基本点,确保公司的互联网业务能够 7×24 小时为用户提供高质量的服务。

    151 引用 • 257 回帖
  • Oracle

    Oracle(甲骨文)公司,全称甲骨文股份有限公司(甲骨文软件系统有限公司),是全球最大的企业级软件公司,总部位于美国加利福尼亚州的红木滩。1989 年正式进入中国市场。2013 年,甲骨文已超越 IBM,成为继 Microsoft 后全球第二大软件公司。

    107 引用 • 127 回帖 • 337 关注
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用
  • OneDrive
    2 引用
  • Kafka

    Kafka 是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是现代系统中许多功能的基础。 这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。

    36 引用 • 35 回帖
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖 • 5 关注
  • LeetCode

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

    209 引用 • 72 回帖 • 1 关注
  • 工具

    子曰:“工欲善其事,必先利其器。”

    303 引用 • 772 回帖
  • 互联网

    互联网(Internet),又称网际网络,或音译因特网、英特网。互联网始于 1969 年美国的阿帕网,是网络与网络之间所串连成的庞大网络,这些网络以一组通用的协议相连,形成逻辑上的单一巨大国际网络。

    98 引用 • 367 回帖
  • Ant-Design

    Ant Design 是服务于企业级产品的设计体系,基于确定和自然的设计价值观上的模块化解决方案,让设计者和开发者专注于更好的用户体验。

    17 引用 • 23 回帖 • 12 关注
  • Kotlin

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,由 JetBrains 设计开发并开源。Kotlin 可以编译成 Java 字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。在 Google I/O 2017 中,Google 宣布 Kotlin 成为 Android 官方开发语言。

    19 引用 • 33 回帖 • 92 关注
  • GitLab

    GitLab 是利用 Ruby 一个开源的版本管理系统,实现一个自托管的 Git 项目仓库,可通过 Web 界面操作公开或私有项目。

    46 引用 • 72 回帖 • 1 关注
  • CAP

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

    12 引用 • 5 回帖 • 638 关注
  • SMTP

    SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。SMTP 协议属于 TCP/IP 协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。

    4 引用 • 18 回帖 • 644 关注
  • Sublime

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

    10 引用 • 5 回帖 • 2 关注
  • Excel
    31 引用 • 28 回帖
  • 安装

    你若安好,便是晴天。

    131 引用 • 1184 回帖
  • 996
    13 引用 • 200 回帖 • 1 关注
  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    731 引用 • 1287 回帖
  • 小说

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

    32 引用 • 108 回帖
  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    498 引用 • 934 回帖 • 1 关注
  • ActiveMQ

    ActiveMQ 是 Apache 旗下的一款开源消息总线系统,它完整实现了 JMS 规范,是一个企业级的消息中间件。

    19 引用 • 13 回帖 • 687 关注
  • 新人

    让我们欢迎这对新人。哦,不好意思说错了,让我们欢迎这位新人!
    新手上路,请谨慎驾驶!

    52 引用 • 228 回帖
  • Love2D

    Love2D 是一个开源的, 跨平台的 2D 游戏引擎。使用纯 Lua 脚本来进行游戏开发。目前支持的平台有 Windows, Mac OS X, Linux, Android 和 iOS。

    14 引用 • 53 回帖 • 562 关注