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) ;