Чтение строкового значения из Excel с помощью HSSF, но оно двойное - PullRequest
15 голосов
/ 11 сентября 2009

Я использую HSSF-POI для чтения данных Excel. Проблема в том, что у меня есть значения в ячейке, которые выглядят как числа, но на самом деле являются строками. Если я смотрю на ячейку формата в Excel, она говорит, что тип «текст». Тем не менее, ячейка HSSF считает, что она числовая. Как я могу получить значение в виде строки?

Если я пытаюсь использовать cell.getRichStringValue, я получаю исключение; если cell.toString, это не то же самое значение, что и в листе Excel.

Редактировать : пока это не будет решено, я буду использовать

new BigDecimal(cell.getNumericCellValue()).toString()

Ответы [ 8 ]

11 голосов
/ 19 октября 2011

Класс, который вы ищете в POI: DataFormatter

Когда Excel записывает файл, некоторые ячейки сохраняются в виде буквенных строк, а другие - в виде чисел. Для последнего значение с плавающей запятой, представляющее ячейку, сохраняется в файле, поэтому, когда вы запрашиваете POI для значения ячейки, это то, что оно на самом деле имеет.

Иногда, особенно при выполнении извлечения текста (но не всегда), вы хотите, чтобы значение ячейки выглядело так же, как в Excel. Не всегда возможно получить это точно в String (например, заполнение не полным пробелом), но класс DataFormatter приблизит вас.

Если вам нужна строка в ячейке, которая выглядит так же, как в Excel, просто выполните:

 // Create a formatter, do this once
 DataFormatter formatter = new DataFormatter(Locale.US);

 .....

 for(Cell cell : row) {
     CellReference ref = new CellReference(cell);
     // eg "The value of B12 is 12.4%"
     System.out.println("The value of " + ref.formatAsString() + " is " + formatter.formatCellValue(cell));
 }

Форматер вернет строковые ячейки как есть, а для числовых ячеек применяет правила форматирования стиля к номеру ячейки

10 голосов
/ 18 сентября 2009

Если документы, которые вы анализируете, всегда имеют определенный макет, вы можете изменить тип ячейки на «string» на лету, а затем получить значение. Например, если столбец 2 всегда должен быть строковыми данными, установите для его типа ячейки значение string, а затем прочитайте его с помощью методов get строкового типа.

cell.setCellType(Cell.CELL_TYPE_STRING);

В моем тестировании изменение типа ячейки не изменило содержимое ячейки, но позволило получить ее с помощью одного из следующих подходов:

cell.getStringCellValue();

cell.getRichStringCellValue().getString();

Без примера значения, которое не преобразуется должным образом, трудно понять, будет ли это вести себя иначе, чем подход cell.toString (), который вы описали в описании.

6 голосов
/ 14 сентября 2009

Вы имеете в виду, что HSSF-POI говорит

cell.getCellType() == Cell.CELL_TYPE_NUMERIC

НЕ

Cell.CELL_TYPE_STRING как и должно быть?

Я бы подумал, что это ошибка в POI, но каждая ячейка содержит вариант, а вариант имеет тип. Там довольно сложно сделать ошибку, поэтому вместо этого я думаю, что Excel использует некоторые дополнительные данные или эвристику для сообщения поля в виде текста. Обычный способ MS, увы.

P.S. Вы не можете использовать getString() в Variant, содержащем числовое значение, поскольку двоичное представление данных Variant зависит от его типа, а попытка получить строку из того, что на самом деле является числом, приведет к мусору - отсюда исключение. *

4 голосов
/ 19 октября 2011

Этот код ниже хорошо работает для чтения любого типа ячейки, но эта ячейка должна содержать числовое значение

new BigDecimal(cell.getNumericCellValue()));

, например

ase.setGss(new BigDecimal(hssfRow.getCell(3).getNumericCellValue()));

где переменная gss имеет тип BigDecimal.

2 голосов
/ 16 сентября 2009

Excel преобразует из строки все, что выглядит как число, дату или время. См. статью базы знаний MS , в которой в основном предлагается вводить число с дополнительным символом, который превращает его в строку.

1 голос
/ 18 сентября 2009

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

С новым BigDecimal (cell.getNumericCellValue ()). ToString () у вас все еще будет много проблем. Например, если у вас есть идентифицирующие номера (например, номера деталей или классификационные номера), у вас, вероятно, есть случаи с начальными нулями, что будет проблемой при подходе getNumericCellValue ().

Я пытаюсь подробно объяснить, как правильно создать Excel для стороны, создающей файлы, которые я должен обработать с помощью POI. Если файлы загружаются конечными пользователями, я даже создал программу проверки для проверки ожидаемых типов ячеек, если я заранее знаю столбцы. В качестве побочного продукта вы также можете проверить различные другие элементы поставляемых файлов (например, указаны ли нужные столбцы или обязательные значения).

1 голос
/ 17 сентября 2009

Вы, вероятно, имеете дело с проблемой Excel. При создании электронной таблицы тип ячейки по умолчанию - «Универсальный». С этим типом Excel угадывает тип на основе ввода, и этот тип сохраняется с каждой ячейкой.

Когда вы позже изменяете формат ячейки на Текст, вы просто меняете значение по умолчанию. Excel не меняет тип каждой ячейки автоматически. Я не нашел способа сделать это автоматически.

Чтобы подтвердить это, вы можете перейти в Excel и набрать одно из чисел и посмотреть, если это текст в HSSF.

Вы также можете посмотреть реальный тип ячейки с помощью этой функции,

  @Cell("type", A1)

A1 - ячейка для номера. Он показывает «l» для текста, «v» для чисел.

0 голосов
/ 21 сентября 2009

"Проблема в том, что у меня есть значения в ячейке, которые выглядят как числа" => выглядят как числа при просмотре в Excel?

"но на самом деле это строки" => что это значит? Как вы ЗНАЕТЕ, что они действительно являются строками?

«Если я посмотрю на ячейку формата» => что такое «ячейка формата» ???

'... в Excel написано, что тип "text"' => Пожалуйста, объясните.

«Тем не менее, ячейка HSSF считает, что она числовая». => Вы имеете в виду, что the_cell.getCellType () возвращает Cell.CELL_TYPE_NUMERIC?

"Как я могу получить значение в виде строки?" => если это NUMERIC, получить числовое значение с помощью the_cell.getNumericCellValue (), а затем отформатировать его в виде строки любым удобным для вас способом.

«Если я попытаюсь использовать cell.getRichStringValue, я получу исключение;» => так что это не строка.

"если cell.toString, это не то же самое значение, что и в листе Excel." => поэтому cell.toString () не форматирует его так, как это делает Excel.

То, что эвристический Excel использует для определения типа, для вас не имеет значения. Это РЕЗУЛЬТАТ этого решения, хранящегося в файле и раскрываемого функцией getCellType (), имеет значение.

...