Je réalise que la question est un peu déroutante, mais je ne savais pas comment la formuler autrement. Quoi qu'il en soit, voici le code original:
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;
}
Je reçois l'erreur suivante:
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)
Même si je le modifie pour obtenir une chaîne utilisant XSSFCell.getStringCellValue()
ou même XFFSCell.getRichTextValue
, j'obtiens l'inverse du message d'erreur ci-dessus (et je m'assure d'en faire un int avec Integer.parseInt(XSSFCell.getStringCellValue()
).
L'erreur lit alors:
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)
Je sais pertinemment que la colonne de la feuille de calcul Excel est en fait une chaîne. Je ne peux pas modifier la feuille de calcul Excel car elle est téléchargée ailleurs. Toujours utiliser le même format et mettre en forme chaque colonne prend beaucoup de temps.
Aucune suggestion?
[Solution] Voici le code de solution que j'ai trouvé avec l'aide de @ 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();
}
Vous pouvez obtenir une valeur en tant que chaîne en utilisant le format défini pour cette cellule:
final DataFormatter df = new DataFormatter();
final XSSFCell cell = row.getCell(cellIndex);
String valueAsString = df.formatCellValue(cell);
Merci à cette réponse .
Il suffit d'utiliser cell.setCellType (1); avant de lire la valeur de la cellule et de l’obtenir toujours sous forme de chaîne, vous pourrez ensuite l’utiliser dans votre propre format (type).
Ravi
Utilisez le code ci-dessous pour lire tout type de données de xcels à l’aide de 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;
}
}
J'ai aussi eu ce bogue avec POI version 3.12final.
Je pense que le bogue est enregistré ici: https://bz.Apache.org/bugzilla/show_bug.cgi?id=56702 et j'y ai mis un commentaire avec mon analyse.
Voici la solution de contournement que j'ai utilisée: l'exception a été déclenchée par HSSFCell.getNumericCellValue qui a été appelée par DateUtil.isCellDateFormatted. DateUtil.isCellDateFormatted fait 2 choses:
1) Vérifiez le type de valeur de la cellule en appelant HSSFCell.getNumericCellValue puis DateUtil.isValidExcelDate (), ce qui est presque inutile à mon avis.
2) vérifier si le format de la cellule est un format de date
J'ai copié le code de la rubrique 2) ci-dessus dans une nouvelle fonction 'myIsADateFormat' et je l'ai utilisé à la place de DateUtil.isCellDateFormatted (c'est assez sale pour copier du code de bibliothèque, mais cela fonctionne ...):
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;
}
Si vous devez d'abord vérifier le type de valeur, vous pouvez également l'utiliser:
CellValue cellValue = evaluator.evaluate(cell);
int cellValueType = cellValue.getCellType();
if(cellValueType == Cell.CELL_TYPE_NUMERIC){
if(myIsADateFormat(cell){
....
}
}
La documentation indique clairement qu'il ne faut pas définir setCellType sur 1, mais plutôt utiliser DataFormatter, comme l'a expliqué Thierry:
https://poi.Apache.org/apidocs/org/Apache/poi/ss/usermodel/Cell.html#setCellType(int)
La solution de Ravi fonctionne: Utilisez simplement cell.setCellType (1); avant de lire la valeur de la cellule et de l’obtenir toujours sous forme de chaîne, vous pourrez ensuite l’utiliser dans votre propre format (type).