2011-09-30 5 views
40

Używam API Apache POI do pobierania wartości z pliku Excel. Wszystko działa dobrze, z wyjątkiem komórek zawierających formuły. W rzeczywistości cell.getStringCellValue() zwraca formułę użytą w komórce, a nie wartość komórki.Jawne punkty POI: jak odczytać wartość komórki Excela, a nie formułę obliczającą ją?

Próbowałem użyć evaluateFormulaCell() metody, ale to nie działa, ponieważ używam formuły GETPIVOTDATA Excel i wzór ten nie jest realizowany w API:

Exception in thread "main" org.apache.poi.ss.formula.eval.NotImplementedException: Error evaluating cell Landscape!K11 
    at org.apache.poi.ss.formula.WorkbookEvaluator.addExceptionInfo(WorkbookEvaluator.java:321) 
    at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateAny(WorkbookEvaluator.java:288) 
    at org.apache.poi.ss.formula.WorkbookEvaluator.evaluate(WorkbookEvaluator.java:221) 
    at org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator.evaluateFormulaCellValue(HSSFFormulaEvaluator.java:320) 
    at org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator.evaluateFormulaCell(HSSFFormulaEvaluator.java:213) 
    at fromExcelToJava.ExcelSheetReader.unAutreTest(ExcelSheetReader.java:193) 
    at fromExcelToJava.ExcelSheetReader.main(ExcelSheetReader.java:224) 
Caused by: org.apache.poi.ss.formula.eval.NotImplementedException: GETPIVOTDATA 
    at org.apache.poi.hssf.record.formula.functions.NotImplementedFunction.evaluate(NotImplementedFunction.java:42) 

Odpowiedz

88

przypadku komórek z formułami, Excel przechowuje dwie rzeczy. Jedną jest sama formuła, drugą jest wartość "buforowana" (ostatnia wartość, która została oceniona jako forumla)

Jeśli chcesz uzyskać ostatnią buforowaną wartość (która może nie być już poprawna, ale tak długo jak Excel zapisany plik, a jeżeli jej nie powinno być zmieniane), będziemy chcieli coś takiego:

for(Cell cell : row) { 
    if(cell.getCellType() == Cell.CELL_TYPE_FORMULA) { 
     System.out.println("Formula is " + cell.getCellFormula()); 
     switch(cell.getCachedFormulaResultType()) { 
      case Cell.CELL_TYPE_NUMERIC: 
       System.out.println("Last evaluated as: " + cell.getNumericCellValue()); 
       break; 
      case Cell.CELL_TYPE_STRING: 
       System.out.println("Last evaluated as \"" + cell.getRichStringCellValue() + "\""); 
       break; 
     } 
    } 
} 
+1

tak, to działa. dobrze zrobione :) – Aminoss

+6

Jeśli to działa, pamiętaj, aby "zaakceptować" odpowiedź. – Wivani

+1

Co powiesz na daty z pamięci podręcznej? Komórki dat są oznaczane jako Cell.CELL_TYPE_NUMERIC. –

0

Istnieje alternatywa polecenia, gdzie można uzyskać wartość surowca komórki, gdzie formuła jest umieścić na . Jego typem zwracanym jest String. Zastosowanie:

cell.getRawValue(); 
+0

Ta metoda nie jest dla mnie wyświetlana [w javadocs POI] (https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html), czy na pewno Twoja odpowiedź dotyczy ta biblioteka? – Gagravarr

+0

Zajrzyj tutaj: https://poi.apache.org/apidocs/org/apache/poi/xssf/usermodel/XSSFCell.html –

+1

Ah, to tylko XSSF. Powinieneś to wyjaśnić, ponieważ model Common SS nie ma go, ani nie HSSF – Gagravarr

2

powyższe wskazówki nie działa dla mnie cell.getRawValue() wrócił sam wzór jak w komórce Excel w AUT tak pisał poniżej funkcji i to działało:

public void readFormula() throws IOException { 
    FileInputStream fis = new FileInputStream("Path of your file"); 
    Workbook wb = new XSSFWorkbook(fis); 
    Sheet sheet = wb.getSheetAt(0); 
    FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator(); 

    CellReference cellReference = new CellReference("C2"); //pass the cell which contains formula 
    Row row = sheet.getRow(cellReference.getRow()); 
    Cell cell = row.getCell(cellReference.getCol()); 

    CellValue cellValue = evaluator.evaluate(cell); 

    switch (cellValue.getCellType()) { 
     case Cell.CELL_TYPE_BOOLEAN: 
      System.out.println(cellValue.getBooleanValue()); 
      break; 
     case Cell.CELL_TYPE_NUMERIC: 
      System.out.println(cellValue.getNumberValue()); 
      break; 
     case Cell.CELL_TYPE_STRING: 
      System.out.println(cellValue.getStringValue()); 
      break; 
     case Cell.CELL_TYPE_BLANK: 
      break; 
     case Cell.CELL_TYPE_ERROR: 
      break; 

     // CELL_TYPE_FORMULA will never happen 
     case Cell.CELL_TYPE_FORMULA: 
      break; 
    } 

} 
Powiązane problemy