在我们实际的程序开发中,经常需要用到从excel导入数据中系统中,而为了防止用户在excel中乱输入文字,有些需要用到下拉选的地方,就需要从程序中动态生成模板。本例子简单的讲解一下,如何生成级联下拉选。
效果图:(选择汽车这个下拉选、后面水果下拉选的值动态改变)
级联下拉选的实现步骤:
1.在excel中的另外一个sheet页中,保存着下拉选的值
2.给下拉中的数据创建一个名字( 类似于在excel中操作命名管理器 )
3.使用INDIRECT()函数获取到级联下拉选的值。
4.poi官网上创建级联下拉选的说明
本例子中,动态excel模板的生成的一个简单思路。
注意:每一个模板字段,都是一个ExportDefinition对象,如果是下拉选的类型,则mainDict字段有值,根据它的值从DictData中加载下拉选的值,如果选择它存在一个级联操作,那么subDict和subField字段有值。subDict也是从DictData中加载数据,subField表示级联的字段
思路:
1.根据一组ExportDefinition定义对象,生成excel的导出模板,此时导出的模板中只有一行到出头数据。
2.创建数据字典页,这个里面保存下拉选需要用到的数据。
3.如果是主下拉选,则给主下拉选创建一个名称管理。
4.如果是主下拉选,并且关联了级联下拉选,则此时需要加载子下拉选的数据,且根据主下拉选中的每一项创建一个名称管理,值为关联的子下拉选的值
5.使用INDIRECT函数、设置数据的有效性等。
步骤:
1.创建下拉选的值
public class DictData { public static Map<String, Object> dict = null; static { dict = new HashMap<>(); List<String> list = new ArrayList<>(); list.add("汽车"); list.add("水果"); dict.put("car-dict", list); Map<String, List<String>> subMap = new HashMap<>(); list = new ArrayList<>(); list.add("宝马"); list.add("大众"); subMap.put("汽车", list); list = new ArrayList<>(); list.add("苹果"); list.add("梨子"); subMap.put("水果", list); dict.put("fruit-dict", subMap); list = new ArrayList<>(); list.add("汽车-1"); list.add("水果-1"); dict.put("t-dict", list); } /** 获取数据字典中的值 */ public static Object getDict(String dict) { return DictData.dict.get(dict); } }
2.创建一个RowCellIndex对象,用于维护,当前创建了下拉选的第几行第几列
public class RowCellIndex { /** 单元格的行索引 */ private int rowIndex; /** 单元格的列索引 */ private int cellIndex; public RowCellIndex(int rowIndex, int cellIndex) { this.rowIndex = rowIndex; this.cellIndex = cellIndex; } public int getRowIndex() { return rowIndex; } public void setRowIndex(int rowIndex) { this.rowIndex = rowIndex; } public int getCellIndex() { return cellIndex; } public void setCellIndex(int cellIndex) { this.cellIndex = cellIndex; } public int incrementRowIndexAndGet() { this.rowIndex++; return this.getRowIndex(); } public int incrementCellIndexAndGet() { this.cellIndex++; return this.getCellIndex(); } }
3.创建一个excel列的导出定义对象,省略部分getter和setter方法
public class ExportDefinition { private String title; // 标题 private String field; // 字段 private int rowIndex; // 所在的行 private int cellIndex; // 所在的列 private String mainDict; // 主字典-用于加载主字典的数据 private String subDict; // 子字典-用于加载subField的数据 private String subField; // 即需要级联的字典 private String refName; // 主字段所在的位置 private String point; // 标题的坐标 private boolean validate;// 是否设置数据的有限性 public ExportDefinition(String title, String field, String mainDict, String subDict, String subField) { this.title = title; this.field = field; this.mainDict = mainDict; this.subDict = subDict; this.subField = subField; }
4.实现导出
package com.huan.excel.ex2; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import org.apache.poi.hssf.usermodel.DVConstraint; import org.apache.poi.hssf.usermodel.HSSFDataValidation; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.util.CellReference; import org.apache.poi.ss.usermodel.DataValidation; import org.apache.poi.ss.usermodel.Name; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.CellRangeAddressList; /** * 生成级联下拉选 * * @描述 * @作者 huan * @时间 2017年3月31日 - 下午9:14:43 */ public class DropDownListTest { private static final String DICT_SHEET = "DICT_SHEET"; public static void main(String[] args) throws IOException { // 1.准备需要生成excel模板的数据 List<ExportDefinition> edList = new ArrayList<>(2); edList.add(new ExportDefinition("生活用品", "xx", null, null, null)); edList.add(new ExportDefinition("汽车", "cat", "car-dict", "fruit-dict", "fruit")); edList.add(new ExportDefinition("水果", "fruit", "fruit-dict", "", "")); edList.add(new ExportDefinition("测试", "yy", "t-dict", null, null)); // 2.生成导出模板 Workbook wb = new HSSFWorkbook(); Sheet sheet = createExportSheet(edList, wb); // 3.创建数据字典sheet页 createDictSheet(edList, wb); // 4.设置数据有效性 setDataValidation(edList, sheet); // 5.保存excel到本地 OutputStream os = new FileOutputStream("d:/4.xls"); wb.write(os); System.out.println("模板生成成功."); } public static void createDataValidateSubList(Sheet sheet, ExportDefinition ed) { int rowIndex = ed.getRowIndex(); CellRangeAddressList cal; DVConstraint constraint; CellReference cr; DataValidation dataValidation; System.out.println(ed); for (int i = 0; i < 100; i++) { int tempRowIndex = ++rowIndex; cal = new CellRangeAddressList(tempRowIndex, tempRowIndex, ed.getCellIndex(), ed.getCellIndex()); cr = new CellReference(rowIndex, ed.getCellIndex() - 1, true, true); constraint = DVConstraint.createFormulaListConstraint("INDIRECT(" + cr.formatAsString() + ")"); dataValidation = new HSSFDataValidation(cal, constraint); dataValidation.setSuppressDropDownArrow(false); dataValidation.createPromptBox("操作提示", "请选择下拉选中的值"); dataValidation.createErrorBox("错误提示", "请从下拉选中选择,不要随便输入"); sheet.addValidationData(dataValidation); } } /** * @param edList * @param sheet */ private static void setDataValidation(List<ExportDefinition> edList, Sheet sheet) { for (ExportDefinition ed : edList) { if (ed.isValidate()) {// 说明是下拉选 DVConstraint constraint = DVConstraint.createFormulaListConstraint(ed.getField()); if (null == ed.getRefName()) {// 说明是一级下拉选 createDataValidate(sheet, ed, constraint); } else {// 说明是二级下拉选 createDataValidateSubList(sheet, ed); } } } } /** * @param sheet * @param ed * @param constraint */ private static void createDataValidate(Sheet sheet, ExportDefinition ed, DVConstraint constraint) { CellRangeAddressList regions = new CellRangeAddressList(ed.getRowIndex() + 1, ed.getRowIndex() + 100, ed.getCellIndex(), ed.getCellIndex()); DataValidation dataValidation = new HSSFDataValidation(regions, constraint); dataValidation.setSuppressDropDownArrow(false); // 设置提示信息 dataValidation.createPromptBox("操作提示", "请选择下拉选中的值"); // 设置输入错误信息 dataValidation.createErrorBox("错误提示", "请从下拉选中选择,不要随便输入"); sheet.addValidationData(dataValidation); } /** * @param edList * @param wb */ private static void createDictSheet(List<ExportDefinition> edList, Workbook wb) { Sheet sheet = wb.createSheet(DICT_SHEET); RowCellIndex rci = new RowCellIndex(0, 0); for (ExportDefinition ed : edList) { String mainDict = ed.getMainDict(); if (null != mainDict && null == ed.getRefName()) {// 是第一个下拉选 List<String> mainDictList = (List<String>) DictData.getDict(mainDict); String refersToFormula = createDictAndReturnRefFormula(sheet, rci, mainDictList); // 创建 命名管理 createName(wb, ed.getField(), refersToFormula); ed.setValidate(true); } if (null != mainDict && null != ed.getSubDict() && null != ed.getSubField()) {// 联动时加载ed.getSubField()的数据 ExportDefinition subEd = fiterByField(edList, ed.getSubField());// 获取需要级联的那个字段 if (null == subEd) { continue; } subEd.setRefName(ed.getPoint());// 保存主下拉选的位置 subEd.setValidate(true); Map<String, List<String>> subDictListMap = (Map<String, List<String>>) DictData.getDict(ed.getSubDict()); for (Entry<String, List<String>> entry : subDictListMap.entrySet()) { String refersToFormula = createDictAndReturnRefFormula(sheet, rci, entry.getValue()); // 创建 命名管理 createName(wb, entry.getKey(), refersToFormula); } } } } /** * @param sheet * @param rci * @param mainDict * @return */ private static String createDictAndReturnRefFormula(Sheet sheet, RowCellIndex rci, List<String> datas) { Row row = sheet.createRow(rci.incrementRowIndexAndGet()); rci.setCellIndex(0); int startRow = rci.getRowIndex(); int startCell = rci.getCellIndex(); for (String dict : datas) { row.createCell(rci.incrementCellIndexAndGet()).setCellValue(dict); } int endRow = rci.getRowIndex(); int endCell = rci.getCellIndex(); String startName = new CellReference(DICT_SHEET, startRow, startCell, true, true).formatAsString(); String endName = new CellReference(endRow, endCell, true, true).formatAsString(); String refersToFormula = startName + ":" + endName; System.out.println(refersToFormula); return refersToFormula; } /** * @param wb * @param nameName * 表示命名管理的名字 * @param refersToFormula */ private static void createName(Workbook wb, String nameName, String refersToFormula) { Name name = wb.createName(); name.setNameName(nameName); name.setRefersToFormula(refersToFormula); } private static ExportDefinition fiterByField(List<ExportDefinition> edList, String field) { for (ExportDefinition ed : edList) { if (Objects.equals(ed.getField(), field)) { return ed; } } return null; } /** * @param edList * @param wb */ private static Sheet createExportSheet(List<ExportDefinition> edList, Workbook wb) { Sheet sheet = wb.createSheet("导出模板"); RowCellIndex rci = new RowCellIndex(0, 0); Row row = sheet.createRow(rci.getRowIndex()); CellReference cr = null; for (ExportDefinition ed : edList) { row.createCell(rci.incrementCellIndexAndGet()).setCellValue(ed.getTitle()); ed.setRowIndex(rci.getRowIndex()); ed.setCellIndex(rci.getCellIndex()); cr = new CellReference(ed.getRowIndex() + 1, ed.getCellIndex(), true, true); ed.setPoint(cr.formatAsString()); } return sheet; } }
相关推荐
Java 使用POI生成带联动下拉框的excel表格实例代码 Java 是一种广泛使用的编程语言,而 POI(Poor Obfuscation Implementation)则是一个流行的 Java 库,用于读写 Microsoft Office 文件格式,包括 Excel、Word ...
在处理数据和制作报表时,使用Excel的下拉列表功能可以大大提升工作效率,尤其是在涉及到联动选择的场景中。三级联下拉列表是一种高级数据输入方式,它能够根据前一个下拉列表中选定的选项,动态更新后一个下拉列表...
这个excel模版是根据我的文章“POI设置级联关系”最终生成的一个模版
**地区区域联动**:这是一种常见的Web表单设计,当用户在一个下拉列表中选择一个选项(如省份)时,另一个下拉列表(如城市)会根据所选的省份动态更新其内容。这通常通过Ajax实现,提高了用户输入的效率和准确性。 ...
1、文件说明: Centos8操作系统texmacs-fedora-fonts-2.1-1.el8.rpm以及相关依赖,全打包为一个tar.gz压缩包 2、安装指令: #Step1、解压 tar -zxvf texmacs-fedora-fonts-2.1-1.el8.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm
内容概要:本文详细介绍了如何使用Matlab/Simulink对直流电动机双闭环调速系统进行建模与仿真。文中首先解释了双闭环调速系统的原理,即通过转速外环和电流内环的协同工作,使电机快速达到并维持稳定的运行状态。接着,逐步指导读者在Simulink中搭建模型,包括设置信号源、配置PI控制器参数、选择电机模块以及连接各个组件。此外,还提供了具体的参数设置示例和优化技巧,如调整PI控制器的比例系数和积分系数,确保系统的快速响应和平稳过渡。最后,通过对仿真结果的分析,展示了双闭环调速系统的优势及其在实际应用中的价值。 适合人群:从事电力电子实验的研究人员和技术爱好者,尤其是那些希望深入了解直流电动机控制系统原理的人。 使用场景及目标:适用于需要精确控制直流电动机转速的应用场合,如工业自动化设备、机器人等领域。通过学习本文,读者可以掌握使用Matlab/Simulink进行系统建模和仿真的方法,提高对复杂控制系统的理解和应用能力。 其他说明:文中提到的一些参数设置和优化技巧来源于实践经验,对于初学者来说可能需要多次尝试才能找到最适合自己的解决方案。同时,在撰写相关实验报告时,可以根据提供的建议整理和展示仿真数据,以便更好地表达研究成果。
电子仿真教程,从基础到精通,每个压缩包15篇教程,每篇教程5000字以上。
电子仿真教程,从基础到精通,每个压缩包15篇教程,每篇教程5000字以上。
内容概要:本文档详细介绍了Proxmox网络组件(vmbr、SDN)、Linux网络基础(桥接、VLAN、Bonding)以及虚拟化网络模型的核心概念,并通过一系列课后习题及其答案帮助读者巩固所学知识。第一部分讲解了Linux网桥与物理交换机的异同、桥接设备的配置方法、VLAN的相关概念及配置步骤;第二部分探讨了Proxmox中vmbr0的作用和创建新桥接接口的方法,以及SDN的核心组件和多租户场景下的优势;第三部分对比了桥接模型与NAT模型的适用场景及局限性,并提供了虚拟机无法访问互联网的排查步骤;第四部分通过故障案例分析和设计题,进一步加深对网络隔离和SDN网络设计的理解。 适合人群:具有Linux和网络基础知识的IT技术人员,特别是从事虚拟化、网络管理和云计算领域的工程师。 使用场景及目标:① 掌握Linux网络基础,包括桥接、VLAN、Bonding的配置与原理;② 理解Proxmox网络组件的功能及配置方法;③ 学习虚拟化网络模型的不同应用场景及优缺点;④ 提升网络故障排查能力和复杂网络的设计能力。 阅读建议:此文档不仅提供了理论知识,还结合了大量实际操作题目,建议读者在学习过程中动手实践,通过配置真实环境来加深理解。同时,对于关键知识点,可以查阅相关资料进行补充学习。
立式插秧机sw16可编辑_三维3D设计图纸_包括零件图_机械3D图可修改打包下载_三维3D设计图纸_包括零件图_机械3D图可修改打包下载.zip
内容概要:本文深入探讨了A*算法和跳点搜索算法(JPS+)在机器人路径规划领域的应用及其与动态窗口算法(DWA)相结合的改进。首先介绍了A*算法的基本原理和实现方式,然后详细解释了JPS+算法如何通过跳点搜索提高效率。接着讨论了这两种算法与DWA结合的具体方法,特别是在多机器人场景下的路径冲突避免和动态避障策略。文中还展示了多种改进措施的效果,如通过八叉树预处理地图、引入朝向变化惩罚以及采用异步优先级协商机制等。最后比较了单机器人和多机器人场景下的性能差异,强调了算法选择的重要性。 适合人群:从事机器人技术研发的专业人士,尤其是关注路径规划算法的研究人员和技术开发者。 使用场景及目标:适用于希望深入了解并优化机器人路径规划系统的团队和个人。目标是在单机器人和多机器人场景中提升路径规划的效率和灵活性,确保机器人能够在复杂的环境中稳定运行。 其他说明:文章不仅提供了理论分析,还包括了大量的代码片段和实际案例,有助于读者更好地理解和应用这些先进的路径规划技术。
内容概要:本文深入探讨了转差频率控制的异步电机矢量控制系统仿真模型。首先介绍了转差频率控制的基本原理,即通过控制转差频率间接调控电机转矩。接着阐述了矢量控制的思想,即将定子电流分解为励磁和转矩两个独立控制的分量。随后展示了仿真模型的具体实现,包括电机参数设定、状态空间模型构建、PI控制器参数配置以及关键模块如转差频率计算、坐标变换、磁链观测等的代码示例。最后强调了配套的50页说明文档对于理解和调试模型的重要价值。 适用人群:适用于电气工程专业学生、电机控制领域的研究人员和技术人员。 使用场景及目标:帮助读者掌握异步电机矢量控制的技术细节,提高对复杂控制系统的设计能力,同时提供实践指导,便于进行相关实验和项目开发。 其他说明:文中提供了大量MATLAB/Simulink代码片段作为实例,有助于加深理解并应用于实际工作中。此外,还分享了一些调试技巧和注意事项,如坐标变换系数选择、积分抗饱和处理等。
内容概要:本文详细介绍了基于Simulink平台构建的黑鹰单旋翼直升机非线性动力学模型。该模型涵盖了主旋翼挥舞角动力学、尾桨控制、机身气动力等多个关键模块,并提供了完整的MATLAB源码。文章深入剖析了各个模块的工作原理,如挥舞角计算、气动耦合补偿、侧向力计算等,并分享了多个实用的仿真技巧和常见问题解决方案。此外,文中还提到了一些优化建议,如调整时间常数、改进积分方法以及处理代数环错误等。 适合人群:从事直升机仿真研究的技术人员、航空航天领域的研究人员、高校相关专业的师生。 使用场景及目标:帮助读者理解和掌握直升机非线性动力学建模的方法和技术,提高仿真的精度和效率。适用于教学、科研项目以及工业应用中的直升机性能评估和控制系统设计。 其他说明:附带的文献资料进一步补充了模型背后的理论依据,特别是关于旋翼失速特性和地面效应的研究成果。对于希望深入了解直升机空气动力学特性的读者来说,这些资料非常有价值。
python 基础:个人自用输入输出
电子仿真教程,从基础到精通,每个压缩包15篇教程,每篇教程5000字以上。
1、文件说明: Centos8操作系统textern-0.8-1.el8.rpm以及相关依赖,全打包为一个tar.gz压缩包 2、安装指令: #Step1、解压 tar -zxvf textern-0.8-1.el8.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm
内容概要:本文档《互联网大厂200道高频Node.js面试题.pdf》涵盖了Node.js技术栈的核心知识点及实际应用技巧。文档详细列举了200个常见面试问题及其解答,内容涵盖Node.js的基础概念、事件循环机制、错误处理、模块系统、Buffer和Stream的使用、进程与线程的区别及应用、异步操作的多种实现方式、集群模式下的性能优化、WebSocket的实现、大文件处理、全局对象的使用、Promise和async/await的优势、RESTful API的设计、环境变量管理、跨域请求处理、调试工具、内存管理和优化、Worker Threads的应用、负载均衡策略、测试框架的选择、静态文件服务、日志管理、HTTP/2的支持、数据库连接方式、微服务架构的设计、JWT认证、性能监控、文件上传与下载、Reactor模式的理解、定时任务的设置、多语言支持、文件预览、安全实践、Server-Sent Events(SSE)的使用、微前端集成、长轮询、GraphQL服务的构建、命令行工具的开发、单元测试编写、process对象的功能、优雅退出的方法、os模块的作用、CPU密集型任务的处理、加密解密、文件锁定、TCP服务创建、DNS解析、事件循环优化、数据压缩、内存缓存、自定义协议、分布式锁、工具函数、文件分片处理、HTTPS实现、请求超时控制、日志切割、URL参数解析、请求重试机制、V8模块的作用、文件内容搜索、断言模块的使用、动态路由、国际化域名处理、性能测量、文件同步、REPL交互环境、请求限
内容概要:本文详细介绍了3次B样条优化算法及其在Matlab中的具体实现。3次B样条作为一种广泛应用于计算机图形学和数据处理领域的曲线表示方法,因其良好的局部控制特性和光滑性而备受青睐。文中不仅阐述了3次B样条的基本理论,如基函数的递归计算公式,还给出了完整的Matlab代码实现,包括节点向量的生成、基函数的计算以及最终的曲线优化过程。此外,作者还分享了一些实用技巧,如避免常见的错误、提高计算效率的方法等。 适合人群:具有一定Matlab编程基础,对数值计算、数据拟合、计算机图形学等领域感兴趣的科研人员和技术开发者。 使用场景及目标:①需要对离散数据进行平滑处理的应用场合;②涉及轨迹规划、路径优化等问题的研究项目;③希望通过引入先进的数学工具改进现有算法性能的研发团队。 其他说明:文章提供的代码可以直接集成到现有的Matlab项目中,帮助用户快速实现3次B样条优化。同时,文中提到的一些优化建议和注意事项也有助于读者更好地理解和应用这一技术。
内容概要:本文详细介绍了如何使用COMSOL进行层合材料的超声波仿真,涵盖了从材料参数设置、几何建模、网格划分、物理场设置到求解器配置以及后处理的全过程。文中提供了大量MATLAB和Java代码片段,帮助用户快速构建并优化仿真模型。同时,作者分享了许多实践经验,如正确设置材料参数、采用合适的网格划分策略、调整求解器参数等,确保仿真结果更加贴近实际情况。 适合人群:从事复合材料研究的技术人员、超声波检测工程师、仿真软件使用者,尤其是有一定COMSOL使用基础的研究人员。 使用场景及目标:①掌握层合材料超声波仿真的完整流程;②提高仿真精度,解决常见的仿真误差问题;③通过实例学习如何优化模型设置,提升仿真效率。 其他说明:文章强调了材料参数设置、网格划分、求解器配置等方面的关键技术和注意事项,并提供了一些实用的代码示例和技巧,有助于读者更好地理解和应用这些知识点。
功能定位:这是一款专业的 Java 堆内存分析工具,主要用于: 诊断内存泄漏:通过分析堆转储文件(Heap Dump),定位未释放的无用对象。 优化内存使用:统计对象实例数量、内存占用及引用关系,提升应用性能。 支持场景:适用于开发调试、性能优化、故障排查(如 OOM 异常)等场景。