2011-06-28 21 views
21

我意識到這個問題有點令人困惑,但我不知道該怎麼說。總之,這裏是原代碼:使用Apache-POI庫獲取單元格內容時,我同時得到「無法從文本單元格獲取數值」及其相反的結果。我如何解決它?

private void readFile(String excelFileName) throws FileNotFoundException, IOException { 
    XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(excelFileName)); 
    if (workbook.getNumberOfSheets() > 1){ 
     System.out.println("Please make sure there is only one sheet in the excel workbook."); 
    } 
    XSSFSheet sheet = workbook.getSheetAt(0); 
    int numOfPhysRows = sheet.getPhysicalNumberOfRows(); 
    XSSFRow row; 
    XSSFCell num; 
    for(int y = 1;y < numOfPhysRows;y++){ //start at the 2nd row since 1st should be category names 
     row = sheet.getRow(y); 
     poNum = row.getCell(1); 
     item = new Item(Integer.parseInt(poNum.getStringCellValue()); 
     itemList.add(item); 
     y++; 
    } 
} 

private int poiConvertFromStringtoInt(XSSFCell cell){ 
    int x = Integer.parseInt(Double.toString(cell.getNumericCellValue())); 
    return x; 
} 

我收到以下錯誤:

Exception in thread "main" java.lang.IllegalStateException: Cannot get a numeric value from a text cell 
    at org.apache.poi.xssf.usermodel.XSSFCell.typeMismatch(XSSFCell.java:781) 
    at org.apache.poi.xssf.usermodel.XSSFCell.getNumericCellValue(XSSFCell.java:199) 

即使我改變它使用XSSFCell.getStringCellValue()甚至XFFSCell.getRichTextValue得到一個字符串,我得到的反上面的錯誤信息(並且我確保最終使用Integer.parseInt(XSSFCell.getStringCellValue()來使其成爲int)。然後

錯誤讀取:

Exception in thread "main" java.lang.IllegalStateException: Cannot get a text value from a numeric cell 
    at org.apache.poi.xssf.usermodel.XSSFCell.typeMismatch(XSSFCell.java:781) 
    at org.apache.poi.xssf.usermodel.XSSFCell.getNumericCellValue(XSSFCell.java:199) 

我知道一個事實,即Excel電子表格列實際上是一個字符串。我無法更改Excel表格,因爲它始終使用相同的格式和格式化每個列首先佔用大量處理時間。

有什麼建議嗎?

[解決方法]這裏是我想出了從@ Wivani的幫助下解決方案代碼:

private long poiGetCellValue(XSSFCell cell){ 
    long x; 
    if(cell.getCellType() == 0) 
     x = (long)cell.getNumericCellValue(); 
    else if(cell.getCellType() == 1) 
     x = Long.parseLong(cell.getStringCellValue()); 
    else 
     x = -1; 
    return x; 
} 
+0

檢查API;有方法來查詢列的類型,所以你可以用它來檢查你是否需要轉換。 PS該代碼片段不足以真正幫助您調試。 – Wivani

+0

爲了讓大家知道發生了什麼事,我發現前100個數字有一個前導0.這導致excel自動將它作爲一個字符串。所以我不得不寫一種方法來首先檢查類型,然後相應地進行格式化。謝謝@Wivani – crstamps2

+0

有趣的或許將來的參考添加您的'解決方案代碼'? – Wivani

回答

50
Use This as reference 

switch (cell.getCellType()) { 
       case Cell.CELL_TYPE_STRING: 
        System.out.println(cell.getRichStringCellValue().getString()); 
        break; 
       case Cell.CELL_TYPE_NUMERIC: 
        if (DateUtil.isCellDateFormatted(cell)) { 
         System.out.println(cell.getDateCellValue()); 
        } else { 
         System.out.println(cell.getNumericCellValue()); 
        } 
        break; 
       case Cell.CELL_TYPE_BOOLEAN: 
        System.out.println(cell.getBooleanCellValue()); 
        break; 
       case Cell.CELL_TYPE_FORMULA: 
        System.out.println(cell.getCellFormula()); 
        break; 
       default: 
        System.out.println(); 
      } 
+0

謝謝,但案件應該是'XSSFCell.CELL_TYPE _...' –

+0

@Mayank在System.out.println(cell.getNumericCellValue())上添加一個強制轉換;得到整數值,因爲avove語句返回一個double。所以正確的答案爲整數值是System.out.println((int)cell.getNumericCellValue()); –

+0

@Mayank使用toString()將RichStringCellValue轉換爲普通字符串,以獲取可存儲在字符串變量內的字符串值。所以回答是System.out.println(cell.getRichStringCellValue()。getString()。toString()); –

21

只需使用cell.setCellType(1);在讀取單元格值並以String形式獲取之前,您可以在自己的格式(類型)中使用它。

拉維

+1

不推薦這樣做,因爲它會丟失所有單元格格式信息 – Gagravarr

+0

我認爲這樣做可能會導致它不能按照您希望的方式返回日期字段......要記住的是一個問題。 – BVernon

0

拉維的解決方案工作: 只需使用cell.setCellType(1);在讀取單元格值並以String形式獲取之前,您可以在自己的格式(類型)中使用它。

21

可以作爲字符串中使用此單元格中定義的格式獲得價值:

final DataFormatter df = new DataFormatter(); 
final XSSFCell cell = row.getCell(cellIndex); 
String valueAsString = df.formatCellValue(cell); 

感謝this answer

+0

謝謝,這就像一個魅力meee! –

3

使用下面的代碼來讀取使用POI xcels任何數據類型。

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.util.Iterator; 
import org.apache.poi.ss.usermodel.Cell; 
import org.apache.poi.ss.usermodel.DataFormatter; 
import org.apache.poi.ss.usermodel.Row; 
import org.apache.poi.xssf.usermodel.XSSFSheet; 
import org.apache.poi.xssf.usermodel.XSSFWorkbook; 

/** 
* 
* @author nirmal 
*/ 
public class ReadWriteExcel { 

    public static void main(String ar[]) { 
     ReadWriteExcel rw = new ReadWriteExcel(); 
     rw.readDataFromExcel(); 

    } 
    Object[][] data = null; 

    public File getFile() throws FileNotFoundException { 
     File here = new File("test/com/javaant/ssg/tests/test/data.xlsx"); 
     return new File(here.getAbsolutePath()); 

    } 

    public Object[][] readDataFromExcel() { 
     final DataFormatter df = new DataFormatter(); 
     try { 

      FileInputStream file = new FileInputStream(getFile()); 
      //Create Workbook instance holding reference to .xlsx file 
      XSSFWorkbook workbook = new XSSFWorkbook(file); 

      //Get first/desired sheet from the workbook 
      XSSFSheet sheet = workbook.getSheetAt(0); 

      //Iterate through each rows one by one 
      Iterator<Row> rowIterator = sheet.iterator(); 

      int rownum = 0; 
      int colnum = 0; 
      Row r=rowIterator.next(); 

      int rowcount=sheet.getLastRowNum(); 
      int colcount=r.getPhysicalNumberOfCells(); 
      data = new Object[rowcount][colcount]; 
      while (rowIterator.hasNext()) { 
       Row row = rowIterator.next(); 

       //For each row, iterate through all the columns 
       Iterator<Cell> cellIterator = row.cellIterator(); 
       colnum = 0; 
       while (cellIterator.hasNext()) { 

        Cell cell = cellIterator.next(); 
        //Check the cell type and format accordingly 
        data[rownum][colnum] = df.formatCellValue(cell); 
        System.out.print(df.formatCellValue(cell)); 
        colnum++; 
        System.out.println("-"); 
       } 
       rownum++; 
       System.out.println(""); 
      } 
      file.close(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     return data; 
    } 
} 
2

我也得到了POI版本3.12final的這個bug。
我認爲這個bug是在那裏註冊的:https://bz.apache.org/bugzilla/show_bug.cgi?id=56702,我在那裏用我的分析來發表評論。

以下是我使用的解決方法:異常由由DateUtil.isCellDateFormatted調用的HSSFCell.getNumericCellValue提升。 DateUtil.isCellDateFormatted做了兩件事:
1)通過調用HSSFCell.getNumericCellValue和DateUtil.isValidExcelDate()來檢查單元格的值類型,這在我看來幾乎毫無意義。
2)檢查單元格的格式是在一個新的函數「myIsADateFormat」上方的日期格式

我複製主題2的代碼),並用它來代替DateUtil.isCellDateFormatted(那是相當髒複製庫中的代碼,但它的作品...):

private boolean myIsADateFormat(Cell cell){ 
    CellStyle style = cell.getCellStyle(); 
    if(style == null) return false; 
    int formatNo = style.getDataFormat(); 
    String formatString = style.getDataFormatString(); 
    boolean result = DateUtil.isADateFormat(formatNo, formatString); 
    return result; 
} 

如果你需要先檢查值類型,你也可以使用此:

CellValue cellValue = evaluator.evaluate(cell); 
int cellValueType = cellValue.getCellType(); 
if(cellValueType == Cell.CELL_TYPE_NUMERIC){ 
    if(myIsADateFormat(cell){ 
     .... 
    } 
} 
相關問題