Чтение строкового значения из Excel с помощью HSSF, но оно двойное

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

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

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

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

Ответ 1

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

cell.getCellType() == Cell.CELL_TYPE_NUMERIC

НЕ

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

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

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

Ответ 2

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

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

Иногда, особенно при выполнении Text Extraction (но не всегда), вы хотите, чтобы значение ячейки выглядело так, как в 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));
 }

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

Ответ 3

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

cell.setCellType(Cell.CELL_TYPE_STRING);

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

cell.getStringCellValue();

cell.getRichStringCellValue().getString();

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

Ответ 4

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

new BigDecimal(cell.getNumericCellValue()));

например.

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

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

Ответ 5

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

Ответ 6

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

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

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

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

  @Cell("type", A1)

A1 - ячейка для числа. Он отображает "l" для текста, "v" для чисел.

Ответ 7

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

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

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

Ответ 8

"Проблема в том, что у меня есть значения в ячейке, которые выглядят как число" = > , как показано в 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().