При получении содержимого ячейки с помощью библиотеки Apache-POI я получаю как «Не удается получить числовое значение из текстовой ячейки», так и наоборот.Как мне это исправить? - PullRequest
22 голосов
/ 28 июня 2011

Я понимаю, что вопрос немного сбивает с толку, но я не знал, как еще это сформулировать. Во всяком случае, вот оригинальный код:

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, так как он загружен в другом месте, где всегда используется один и тот же формат, а форматирование каждого столбца сначала занимает много времени.

Есть предложения?

[Решение] Вот код решения, который я пришел из справки @ 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;
}

Ответы [ 7 ]

53 голосов
/ 08 сентября 2011
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();
            }
24 голосов
/ 18 сентября 2014

Вы можете получить значение в виде строки, используя формат, определенный для этой ячейки:

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

Благодаря этому ответу .

21 голосов
/ 10 декабря 2012

Просто используйте cell.setCellType (1);перед чтением значения ячейки и всегда получайте его как String, после этого вы можете использовать его в своем собственном формате (тип).

Ravi

3 голосов
/ 03 сентября 2015

Используйте приведенный ниже код для чтения любого типа данных из 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;
    }
}
2 голосов
/ 03 сентября 2015

Я получил также эту ошибку с 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){
        ....
    }
}
1 голос
/ 30 июня 2015

В документации ясно сказано, что не следует устанавливать дляCellType значение 1, вместо этого используйте DataFormatter, например, как объяснил Тьерри:

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

0 голосов
/ 02 июля 2014

Решение Рави работает: просто используйте cell.setCellType (1);перед чтением значения ячейки и всегда получайте его как String, после этого вы можете использовать его в своем собственном формате (тип).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...