web-dev-qa-db-fra.com

Lorsque j'obtiens un contenu de cellule à l'aide d'Apache-POI Library, j'obtiens le message "Impossible d'obtenir une valeur numérique à partir d'une cellule de texte" et inversement. Comment je le répare?

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;
}
21
crstamps2
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();
            }
52
Mayank

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 .

23
Thierry

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

21
user1891180

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;
    }
}
3
Nirmal Dhara

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){
        ....
    }
}
2
Herve

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)

1
Jobin Thomas

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).

0
JavaLover