当使用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 Integer.parseInt(XSSFCell.getStringCellValue() )。

然后错误如下:

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

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

您可以使用为此单元格定义的格式将值作为String获取:

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

感谢这个答案 。

只需使用cell.setCellType(1); 在读取单元格值并将其始终作为String之前,您可以使用它自己的格式(类型)。

拉维

使用以下代码使用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 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 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; } } 

我还得到了POI版本3.12final的这个错误。
我认为这个bug已在那里注册: https : //bz.apache.org/bugzilla/show_bug.cgi?id = 56702我在那里发表评论并进行分析。

以下是我使用的解决方法:由DateUtil.isCellDateFormatted调用的HSSFCell.getNumericCellValue引发了exception。 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){ .... } } 

文档明确指出不要将setCellType设置为1而是使用DataFormatter,就像Thierry解释的那样:

https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html#setCellType(int)

Ravi的解决方案有效:只需使用cell.setCellType(1); 在读取单元格值并将其始终作为String之前,您可以使用它自己的格式(类型)。