Апач пои в формате XLSX читать, ячейки со значением # - непредвиденная ошибка типа клеток(5)


Не могли бы вы помочь мне с таким вопросом.

Мне нужно прочитать каждую ячейку как строковое значение. В данном случае я использую appache poi lib. и такой способ нормализации каждой клетки:

String getNormilizedCell(Cell cell){
return new DataFormatter().formatCellValue(cell);}

Но когда В.xlsx файл я столкнулся с таким значением:

|#N|A / #N|A/...|...|...

Я получаю ошибку [неожиданный тип ячейки (5)] , и я не знаю, как с этим справиться. В google я не могу найти необходимую информацию.

3 3

3 ответа:

Класс DataFormatter обрабатывает только CELL_TYPE_FORMULA, CELL_TYPE_NUMERIC, CELL_TYPE_STRING, CELL_TYPE_BOOLEAN, и CELL_TYPE_BLANK. Он не справляется CELL_TYPE_ERROR, то есть 5.

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

if (cell.getCellType() == Cell.CELL_TYPE_ERROR) {
    byte errorValue = cell.getErrorCellValue();
    switch(errorValue) {
    case ERROR_DIV_0:
        return "#DIV/0!";
    case ERROR_NA:
        return "#N/A";
    case ERROR_NAME:
        return "#NAME?";
    case ERROR_NULL:
        return "#NULL!";
    case ERROR_NUM:
        return "#NUM!";
    case ERROR_REF:
        return "#REF!";
    case ERROR_VALUE:
        return "#VALUE!";
    default:
        return "Unknown error value: " + errorValue + "!";
    }
} else {
    return new DataFormatter().formatCellValue(cell);
}

Вам нужно обновить вашу копию Apache POI!

По состоянию на r1537552 DataFormatter теперь рад отформатировать ячейки ошибок для вас. Он вернет вам строку ошибки, отображаемую в Excel, используя константы FormulaError

, Как сказал @Gagravarr, DataFormatter обрабатывает большинство ошибок сейчас (я использую пои-3.11-бета2). Но, как сказано в моем комментарии, некоторые ошибки в формулах все еще могут вызывать исключения.

Например, при вычислении формулы, такой как =xxx(), когда xxx не является реальной функцией, Excel отображает #NAME?, но мы получаем исключение времени выполнения "не знаю, как вычислить имя" xxx"".

К счастью, он прост в обращении:

public String readCellValue(Cell cell)
{
    switch (cell.getCellType())
    {
    case Cell.CELL_TYPE_BLANK:
        return "(blank)";
    case Cell.CELL_TYPE_BOOLEAN:
        return String.valueOf(cell.getBooleanCellValue());
    case Cell.CELL_TYPE_ERROR:
        return String.valueOf(cell.getErrorCellValue());
    case Cell.CELL_TYPE_FORMULA:
        return readFormattedCellValue(cell);
    case Cell.CELL_TYPE_NUMERIC:
        return String.valueOf(cell.getNumericCellValue());
    case Cell.CELL_TYPE_STRING:
        return cell.getStringCellValue();
    default:
        return "Unknown type!";
    }
}

public String readFormattedCellValue(Cell cell)
{
    try
    {
        return formatter.formatCellValue(cell, evaluator);
    }
    catch (RuntimeException e)
    {
        return e.getMessage(); // Error from evaluator, for example "Don't know how to evaluate name 'xxx'" if we have =xxx() in cell
    }
}

Для записи, formatter и evaluator создаются как в преобразовании в CSV пример:

    try (FileInputStream fis = new FileInputStream(file))
    {
        // Open the workbook and then create the FormulaEvaluator and
        // DataFormatter instances that will be needed to, respectively,
        // force evaluation of formulae found in cells and create a
        // formatted String encapsulating the cells contents.
        workbook = WorkbookFactory.create(fis);
        evaluator = workbook.getCreationHelper().createFormulaEvaluator();
        formatter = new DataFormatter(true);
    }
По какой-то неизвестной причине WorkbookFactory живет только в poi-ooml-3.11-beta2.jar, а не в poi-3.11-beta2.банка первая.