如何获取Excel数据validation下拉参考单元范围的值

在Excel文档中阅读时,我偶然发现了一个问题,特别是从单元格获取下拉值(数据validation)。 我能够明确定义的值。 在这里输入图像说明

我能够通过查看cell是否在CellRangeAddress内获得值(720×486等)与以下:

Map<CellRangeAddress, String[]> dropDownValues = new HashMap<>(); List<? extends DataValidation> dataValidations = sheet.getDataValidations(); for(DataValidation dataValidation : dataValidations) { for(CellRangeAddress cellRangeAddress : dataValidation.getRegions().getCellRangeAddresses()) { String[] explicitListValues = dataValidation.getValidationConstraint().getExplicitListValues(); if(explicitListValues == null) { continue; } dropDownValues.put(cellRangeAddress, explicitListValues); } } 

上面的代码仅适用于显式值。 我看到的问题是在数据有效性的单元格中定义范围时:

在这里输入图像说明

 sheet.getDataValidations(); 

不会返回有关数据validation范围或任何信息的任何内容。 有没有人能够获得来源和评估的公式来获得价值?

我能够检索由比2003年更新的Excel表格定义的数据validation。

我不得不parsingXSSFSheet的具体信息,然后重build和评估公式。

以下是我所做的所有DataValidation值:

 Map<CellRangeAddress, String[]> dropDownValues = new HashMap<>(); List<ExtendedDataValidations> extendedDataValidationsList = getExtendedDataValidations(sheet); for (ExtendedDataValidations extendedDataValidations : extendedDataValidationsList) { AreaReference formulaReference = new AreaReference(extendedDataValidations.formula); CellReference[] allReferencedCells = formulaReference.getAllReferencedCells(); FormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator(); String[] values = new String[allReferencedCells.length]; for (int j = 0; j < allReferencedCells.length; j++) { CellReference cellReference = allReferencedCells[j]; Sheet valueSheet = wb.getSheet(cellReference.getSheetName()); Cell cell = valueSheet.getRow(cellReference.getRow()).getCell(cellReference.getCol()); CellValue evaluate = formulaEvaluator.evaluate(cell); values[j] = StringUtils.trimToEmpty(StringUtils.removeStart(StringUtils.removeEnd(evaluate.formatAsString(), "\""), "\"")); } String stRef = extendedDataValidations.sqref; String[] regions = stRef.split(" "); for (String region : regions) { String[] parts = region.split(":"); CellReference begin = new CellReference(parts[0]); CellReference end = parts.length > 1 ? new CellReference(parts[1]) : begin; CellRangeAddress cellRangeAddress = new CellRangeAddress(begin.getRow(), end.getRow(), begin.getCol(), end.getCol()); dropDownValues.put(cellRangeAddress, values); } } 

另外我为公式和单元格引用定义了一个Struc。

 private static class ExtendedDataValidations { public String formula; public String sqref; } 

getExtendedDataValidations获取了数据validation论坛在表单中出现的CTExtensionList:

 public static List<ExtendedDataValidations> getExtendedDataValidations(Sheet sheet) { List<ExtendedDataValidations> extendedDataValidationsList = new ArrayList<>(); if (sheet instanceof XSSFSheet) { CTExtensionList extLst = ((XSSFSheet) sheet).getCTWorksheet().getExtLst(); if (extLst == null) { return extendedDataValidationsList; } CTExtension[] extArray = extLst.getExtArray(); List<Node> dataValidationNodes = new ArrayList<>(); for (CTExtension anExtArray : extArray) { searchForDataValidation(anExtArray.getDomNode(), dataValidationNodes); } for (Node dataValidationNode : dataValidationNodes) { ExtendedDataValidations dataValidations = new ExtendedDataValidations(); getDataValidationInfo(dataValidationNode, dataValidations); extendedDataValidationsList.add(dataValidations); } } return extendedDataValidationsList; } 

searchForDataValidation必须遍历工作表的DOM节点,以查找DataValidation上的特定信息。 如果find保存在列表中:

 private static void searchForDataValidation(Node node, List<Node> nodesInQuestion) { if (StringUtils.equalsIgnoreCase("x14:dataValidation", node.getNodeName())) { nodesInQuestion.add(node); return; } for (int i = 0; i < node.getChildNodes().getLength(); i++) { searchForDataValidation(node.getChildNodes().item(i), nodesInQuestion); } } 

getDataValidationInfo负责获取公式和单元格引用。

 private static void getDataValidationInfo(Node node, ExtendedDataValidations dataValidations) { if (StringUtils.equalsIgnoreCase("#text", node.getNodeName())) { if (StringUtils.equalsIgnoreCase("xm:sqref", node.getParentNode().getNodeName())) { dataValidations.sqref = node.getNodeValue(); } else if (StringUtils.equalsIgnoreCase("xm:f", node.getParentNode().getNodeName())) { dataValidations.formula = node.getNodeValue(); } return; } for (int i = 0; i < node.getChildNodes().getLength(); i++) { getDataValidationInfo(node.getChildNodes().item(i), dataValidations); } } 

可能看起来很复杂,但它是有用的。 希望能帮助到你!