При получении содержимого ячейки с использованием Apache-POI Library я получаю как "Не могу получить числовое значение из текстовой ячейки", так и наоборот. Как это исправить?
Я понимаю, что этот вопрос немного запутан, но я не знал, как еще это сказать. Во всяком случае, вот исходный код:
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
, я получаю обратную ссылку на вышеупомянутое сообщение об ошибке (и я уверен, что в конечном итоге сделаю его 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 является фактически строкой. Я не могу изменить лист 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;
}
Ответы
Ответ 1
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();
}
Ответ 2
Вы можете получить значение как String, используя формат, определенный для этой ячейки:
final DataFormatter df = new DataFormatter();
final XSSFCell cell = row.getCell(cellIndex);
String valueAsString = df.formatCellValue(cell);
Благодаря этому ответу.
Ответ 3
Просто используйте cell.setCellType(1); прежде чем считывать значение ячейки и всегда получать ее как строку, после чего вы можете использовать ее в своем собственном формате (тип).
Рави
Ответ 4
Используйте приведенный ниже код для чтения любого типа данных из xcels с помощью poi.
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;
}
}
Ответ 5
Я тоже получил эту ошибку с POI версии 3.12.
Я думаю, что ошибка зарегистрирована там: https://bz.apache.org/bugzilla/show_bug.cgi?id=56702, и я добавил комментарий там с моим анализом.
Вот обходной путь, который я использовал: Исключение было поднято HSSFCell.getNumericCellValue, которое было вызвано DateUtil.isCellDateFormatted. DateUtil.isCellDateFormatted делает 2 вещи:
1) проверьте тип значения ячейки, вызвав HSSFCell.getNumericCellValue, а затем DateUtil.isValidExcelDate(), что почти бесполезно здесь, я думаю.
2) проверьте, является ли формат ячейки форматом даты
Я скопировал код темы 2) выше в новой функции myIsADateFormat и использовал его вместо 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){
....
}
}
Ответ 6
Документация ясно говорит, что вместо setCellType вместо 1 использовать DataFormatter, как объяснил Тьерри:
https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html#setCellType(int)
Ответ 7
Решение Рави работает:
Просто используйте cell.setCellType(1); прежде чем считывать значение ячейки и всегда получать ее как строку, после чего вы можете использовать ее в своем собственном формате (тип).