15

我正在使用 HSSF-POI 读取 excel 数据。问题是我在一个单元格中有一个看起来像数字但实际上是字符串的值。如果我查看 Excel 中的格式单元格,它会显示类型是“文本”。HSSF Cell 仍然认为它是数字的。如何将值作为字符串获取?

如果我尝试使用cell.getRichStringValue,我会得到异常;如果cell.toString,它与 Excel 工作表中的值不完全相同。

编辑:直到这个问题得到解决,我会使用

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

8 回答 8

11

您在 POI 中寻找的类是DataFormatter

当 Excel 写入文件时,一些单元格存储为文字字符串,而其他单元格存储为数字。对于后者,代表单元格的浮点值存储在文件中,因此当您向 POI 询问单元格的值时,这就是它实际拥有的值。

但有时,特别是在进行文本提取时(但并非总是如此),您希望使单元格值看起来像在 Excel 中所做的那样。并非总是可以在字符串中准确地得到它(例如,非完整空间填充),但 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));
 }

格式化程序将按原样返回字符串单元格,对于数字单元格,会将样式上的格式化规则应用于单元格的编号

于 2011-10-19T09:26:26.913 回答
10

如果您正在解析的文档始终处于特定布局中,您可以即时将单元格类型更改为“字符串”,然后检索该值。例如,如果第 2 列应始终为字符串数据,请将其单元格类型设置为字符串,然后使用字符串类型的 get 方法读取它。

cell.setCellType(Cell.CELL_TYPE_STRING);

在我的测试中,更改单元格类型不会修改单元格的内容,但确实允许使用以下任一方法对其进行检索:

cell.getStringCellValue();

cell.getRichStringCellValue().getString();

如果没有未正确转换的值的示例,很难知道这是否会与您在描述中描述的 cell.toString() 方法有任何不同。

于 2009-09-18T04:58:21.563 回答
6

你的意思是 HSSF-POI 说

cell.getCellType() == Cell.CELL_TYPE_NUMERIC

不是

Cell.CELL_TYPE_STRING应该是这样吗?

我认为这是 POI 中的一个错误,但每个单元格都包含一个 Variant,而 Variant 有一个类型。在那里制造错误有点困难,所以我认为 Excel 使用一些额外的数据或启发式方法将字段报告为文本。通常的 MS 方式,唉。

PS 您不能getString()在包含数字的 Variant 上使用任何内容,因为 Variant 数据的二进制表示取决于它的类型,并且尝试从实际数字中获取字符串会导致垃圾 - 因此异常。

于 2009-09-14T13:56:41.790 回答
4

下面的代码可以很好地读取任何单元格类型,但该单元格应包含数值

new BigDecimal(cell.getNumericCellValue()));

例如

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

其中变量 gss 是 BigDecimal 类型。

于 2011-10-19T08:44:42.550 回答
2

Excel 将从字符串转换任何看起来像数字或日期或时间的东西。请参阅MS 知识库文章,该文章基本上建议输入带有额外字符的数字,使其成为字符串。

于 2009-09-16T15:12:39.377 回答
1

您可能正在处理 Excel 问题。创建电子表格时,默认单元格类型为通用。使用这种类型,Excel 会根据输入猜测类型,并且这种类型与每个单元格一起保存。

当您稍后将单元格格式更改为文本时,您只是更改了默认值。Excel 不会自动更改每个单元格的类型。我还没有找到自动执行此操作的方法。

要确认这一点,您可以转到 Excel 并重新输入其中一个数字,看看它是否是 HSSF 中的文本。

您还可以使用此功能查看真实的细胞类型,

  @Cell("type", A1)

A1 是数字的单元格。它显示“l”表示文本,“v”表示数字。

于 2009-09-16T22:01:05.993 回答
1

Excel 的问题在于默认格式是通用的。使用这种格式,Excel 将在单元格中输入的数字存储为数字。在输入值之前,您必须将格式更改为文本。更改格式后重新输入值也将起作用。
如果内容在 Excel 中看起来像数字,这将导致单元格左上角出现小绿色三角形。如果是这种情况,则该值实际上存储为文本。

使用 new BigDecimal(cell.getNumericCellValue()).toString() 你仍然会有很多问题。例如,如果您有识别编号(例如零件编号或分类编号),您可能会遇到带有前导零的案例,这将是 getNumericCellValue() 方法的问题。

我尝试向创建我必须使用 POI 处理的文件的一方彻底解释如何正确创建 Excel。如果文件是由最终用户上传的,我什至已经创建了一个验证程序来检查预期的单元格类型,如果我事先知道这些列的话。作为副产品,您还可以检查所提供文件的各种其他内容(例如,是否提供了正确的列或强制值)。

于 2009-09-18T05:23:20.727 回答
0

“问题是我的单元格中有一个看起来像数字的值”=> 在 Excel 中查看时看起来像数字?

“但实际上是字符串” => 这是什么意思?你怎么知道它们真的是字符串?

“如果我查看格式单元格”=> 什么是“格式单元格”???

'... 在 Excel 中,它说类型是“文本”' => 请解释一下。

“HSSF Cell 仍然认为它是数字的。” => 你的意思是 the_cell.getCellType() 返回 Cell.CELL_TYPE_NUMERIC 吗?

“如何将值作为字符串获取?” =>如果它是 NUMERIC,则使用 the_cell.getNumericCellValue() 获取数值,然后以任何您想要的方式将其格式化为字符串。

“如果我尝试使用 cell.getRichStringValue,我会得到异常;” => 所以它不是一个字符串。

“如果 cell.toString,它与 Excel 表中的值不完全相同。” => 所以 cell.toString() 不会像 Excel 那样格式化它。

Excel 用于确定类型的任何启发式方法都与您无关。重要的是存储在文件中并由 getCellType() 显示的决定的结果。

于 2009-09-21T12:09:59.093 回答