java excel级联下拉框

excel级联设置

1)选择下拉框, 在公式 -》根据所选内容创建 在弹出的对话框中选择-》首行

每一个下拉框都这样设置后,在内容管理器中可以看到

这里需要注意:名称和值的关联关系。

设置下拉框: 省是内容管理值的名称

下拉级联 =INDIRECT(SUBSTITUTE(B2," ",""))
B2是需要级联的上一个单元格位置
三级级联和二级级联的方法是一样的,也是用公式 =INDIRECT(SUBSTITUTE(C2," ","
"))

java 代码:

java 复制代码
/**
     * 设置三级级联下拉框(基于SXSSFWorkbook)
     * @param workbook SXSSF工作簿
     * @param sheet 目标sheet
     * @param firstRow 起始行
     * @param endRow 结束行
     * @param level1Col 一级下拉列索引
     * @param level2Col 二级下拉列索引
     * @param level3Col 三级下拉列索引
     * @param dataMap 级联数据Map,结构: 一级选项 -> Map<二级选项, List<三级选项>>
     */
    public static void setCascadingValidation(SXSSFWorkbook workbook,
                                              SXSSFSheet sheet,
                                              int firstRow, int endRow,
                                              int level1Col, int level2Col, int level3Col,
                                              Map<String, Map<String, List<String>>> dataMap) {
        try {
            // 1. 创建隐藏Sheet,用于存放级联数据
            String hiddenSheetName = "CascadeData";
            SXSSFSheet hiddenSheet = (SXSSFSheet)workbook.createSheet(hiddenSheetName);

            int currentRow = 0;

            // 2. 构建一级下拉列表(去重后写入隐藏Sheet第一列)
            Set<String> level1Set = dataMap.keySet();
            String[] level1Array = level1Set.toArray(new String[0]);
            for (int i = 0; i < level1Array.length; i++) {
                hiddenSheet.createRow(currentRow + i).createCell(0).setCellValue(level1Array[i]);
            }

            // 创建一级下拉的命名区域
            String level1Name = "Level1List";
            Name level1NamedRange = workbook.createName();
            level1NamedRange.setNameName(level1Name);
            level1NamedRange.setRefersToFormula(hiddenSheetName + "!$A$1:$A$" + level1Array.length);

            // 3. 为每个一级选项创建【二级选项列表】对应的命名区域
            Map<String, String> level2NamedRangeMap = new HashMap<>();
            int startRowForLevel2 = currentRow + level1Array.length + 2; // 空两行分隔

            int rowIndex2 = startRowForLevel2;
            int colsIndex2 = 0;
            for (String level1Value : level1Array) {
                rowIndex2 = startRowForLevel2;
                Map<String, List<String>> level2Map = dataMap.get(level1Value);
                if (level2Map == null || level2Map.isEmpty()) continue;

                Set<String> level2Set = level2Map.keySet();
                String[] level2Array = level2Set.toArray(new String[0]);

                // 写入隐藏Sheet的某一列(动态列索引,每个一级值占用一列)
                for (int i = 0; i < level2Array.length; i++) {
                    if (hiddenSheet.getRow(rowIndex2 + i)==null){
                        hiddenSheet.createRow(rowIndex2 + i).createCell(colsIndex2).setCellValue(level2Array[i]);
                    }else{
                        hiddenSheet.getRow(rowIndex2 + i).createCell(colsIndex2).setCellValue(level2Array[i]);
                    }
                }

                // 命名范围名称(每个一级选项对应一个二级区域)
                String rangeName = level1Value;
                level2NamedRangeMap.put(level1Value, rangeName);

                Name namedRange = workbook.createName();
                namedRange.setNameName(rangeName);
                namedRange.setRefersToFormula(hiddenSheetName + "!$" + getColumnLetter(colsIndex2) + "$" + (rowIndex2 + 1) +
                        ":$" + getColumnLetter(colsIndex2) + "$" + (rowIndex2 + level2Array.length));
                rowIndex2 += level2Array.length + 1; // 空一行分隔
                colsIndex2++;
            }

            // 4. 为每个二级选项创建【三级选项列表】对应的命名区域
            int startRowForLevel3 = rowIndex2 + 2;
            int rowIndex3 = startRowForLevel3;
            int colsIndex3 = 0;
            Map<String, String> level3NamedRangeMap = new HashMap<>();

            for (String level1Value : level1Array) {

                Map<String, List<String>> level2Map = dataMap.get(level1Value);
                if (level2Map == null) continue;

                for (String level2Value : level2Map.keySet()) {
                    List<String> level3List = level2Map.get(level2Value);
                    if (level3List == null || level3List.isEmpty()) continue;

                    String[] level3Array = level3List.toArray(new String[0]);

                    rowIndex3 = startRowForLevel3;

                    for (int i = 0; i < level3Array.length; i++) {
                        if (hiddenSheet.getRow(rowIndex3 + i) == null){
                            hiddenSheet.createRow(rowIndex3 + i).createCell(colsIndex3).setCellValue(level3Array[i]) ;
                        }else{
                            hiddenSheet.getRow(rowIndex3 + i).createCell(colsIndex3).setCellValue(level3Array[i]);
                        }
                    }

                    String rangeName =  level2Value;
                    level3NamedRangeMap.put(level1Value + "|" + level2Value, rangeName);

                    Name namedRange = workbook.createName();
                    namedRange.setNameName(rangeName);
                    namedRange.setRefersToFormula(hiddenSheetName + "!$" + getColumnLetter(colsIndex3) + "$" + (rowIndex3 + 1) +
                            ":$" + getColumnLetter(colsIndex3) + "$" + (rowIndex3 + level3Array.length));
                    rowIndex3 += level3Array.length + 1;
                    colsIndex3++;
                }
            }

            // 5. 应用级联校验到目标Sheet
            DataValidationHelper helper = sheet.getDataValidationHelper();

            // 一级下拉校验(直接使用静态列表)
            DataValidationConstraint level1Constraint = helper.createFormulaListConstraint(level1Name);
            CellRangeAddressList level1Address = new CellRangeAddressList(firstRow, endRow, level1Col, level1Col);
            DataValidation level1Validation = helper.createValidation(level1Constraint, level1Address);
            level1Validation.setSuppressDropDownArrow(false);

            if (level1Validation instanceof XSSFDataValidation) {
                // 数据校验
                level1Validation.setSuppressDropDownArrow(true);
                level1Validation.setShowErrorBox(true);
            } else {
                level1Validation.setSuppressDropDownArrow(false);
            }
            // 作用在目标sheet上
            sheet.addValidationData(level1Validation);

            // 二级下拉校验(使用INDIRECT根据一级列的值动态获取命名区域)
            String level2Formula = "=INDIRECT(SUBSTITUTE(" +
                    getColumnLetter(level1Col) + (firstRow + 1) +
                    ",\" \",\"_\"))";
            DataValidationConstraint level2Constraint = helper.createFormulaListConstraint(level2Formula);
            CellRangeAddressList level2Address = new CellRangeAddressList(firstRow, endRow, level2Col, level2Col);
            DataValidation level2Validation = helper.createValidation(level2Constraint, level2Address);


            if (level2Validation instanceof XSSFDataValidation) {
                // 数据校验
                level2Validation.setSuppressDropDownArrow(true);
                level2Validation.setShowErrorBox(true);
            } else {
                level2Validation.setSuppressDropDownArrow(false);
            }
            sheet.addValidationData(level2Validation);

            // 三级下拉校验
            String level3Formula = "=INDIRECT(SUBSTITUTE(" +
                    getColumnLetter(level2Col) + (firstRow + 1) +
                    ",\" \",\"_\"))";
            DataValidationConstraint level3Constraint = helper.createFormulaListConstraint(level3Formula);
            CellRangeAddressList level3Address = new CellRangeAddressList(firstRow, endRow, level3Col, level3Col);
            DataValidation level3Validation = helper.createValidation(level3Constraint, level3Address);

            if (level3Validation instanceof XSSFDataValidation) {
                // 数据校验
                level3Validation.setSuppressDropDownArrow(true);
                level3Validation.setShowErrorBox(true);
            } else {
                level3Validation.setSuppressDropDownArrow(false);
            }

            sheet.addValidationData(level3Validation);


            // 6. 隐藏辅助Sheet
            workbook.setSheetHidden(workbook.getSheetIndex(hiddenSheetName), true);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

调用的方法:

java 复制代码
// 构建测试数据
        Map<String, Map<String, List<String>>> cascadeData = new LinkedHashMap<>();

        // 省份 -> 城市 -> 区县
        Map<String, List<String>> guangdong = new LinkedHashMap<>();
        guangdong.put("深圳", Arrays.asList("南山区", "福田区", "罗湖区"));
        guangdong.put("广州", Arrays.asList("天河区", "越秀区", "海珠区"));
        cascadeData.put("广东省", guangdong);

        Map<String, List<String>> jiangsu = new LinkedHashMap<>();
        jiangsu.put("南京", Arrays.asList("玄武区", "秦淮区", "建邺区"));
        jiangsu.put("苏州", Arrays.asList("姑苏区", "虎丘区", "吴中区"));
        cascadeData.put("江苏省", jiangsu);
        setCascadingValidation( workbook,   mainSheet,   1,  5000,  15,  16  ,17, cascadeData) ;
相关推荐
小则又沐风a1 小时前
初步了解进程的概念
java·linux·服务器·前端
斌果^O^1 小时前
普通 SpringBoot 单体项目改造成微服务(Nacos+Gateway + 内部服务免鉴权)
java·spring boot·spring
砍材农夫1 小时前
物联网 基于netty入门与线程模型探秘简述
java·物联网·struts
GentleDevin1 小时前
IntelliJ Idea常用快捷键(Window和Mac对照表)
java·ide·intellij-idea
Paxon Zhang1 小时前
JavaEE 初阶变强宝典 **线程安全问题,线程状态,锁synchronized**
java·java-ee
阿拉金alakin1 小时前
Java IO 核心类 File、InputStream/OutputStream 实战总结
java·开发语言
有梦想的小何1 小时前
Cursor AI 编程实战(篇二):Rules、速查与 Adapter/App 全文
java·大数据·elasticsearch·搜索引擎·ai·ai编程
Cloud_Shy6182 小时前
Python 数据分析基础入门:《Excel Python:飞速搞定数据分析与处理》学习笔记系列(第九章 Excel 自动化 下篇)
python·数据分析·excel·numpy·pandas
噢,我明白了3 小时前
表单的完整 CRUD 练习【极简个人记账本】(含前端后端链接mySQL)
java·前端·数据库·mysql