2015-08-26 44 views
2

在Excel文檔中讀取數據時,特別是從單元格獲取下拉值(數據驗證)時,我偶然發現了一個問題。我能夠獲得明確定義的值。 enter image description here如何獲取Excel數據驗證爲參考單元範圍下拉值

我能夠通過查看與以下獲得的值(720x486等),如果細胞內是:的CellRangeAddress

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

上面的代碼僅適用於明確的值。我看到的問題是,當一個範圍內的數據驗證的電池用源定義:

enter image description here

sheet.getDataValidations(); 

不問候的範圍內或在數據驗證任何信息返回任何東西。有沒有人能夠掌握Source並評估公式以獲得價值?

回答

1

我能夠檢索通過Excel表式定義的數據驗證新的比2003年

我不得不解析XSSFSheet的具體信息,然後重建和評估公式。

這裏是我做的,以實現上述所有資料驗證值:

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抓起CTExtensionList數據驗證forumla出現在表中:

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節點。如果找到將其保存在列表中:

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

可能看起來很複雜,但它的確有用。希望能幫助到你!

相關問題