我正在使用HSSF-POI来读取Excel数据。问题是我在单元格中的值看起来像一个数字,但实际上是字符串。如果我在Excel中查看格式单元格,则表示类型为“text”。 HSSF Cell仍然认为它是数字的。如何将值作为字符串获取?
如果我尝试使用cell.getRichStringValue
,我会得到例外;如果cell.toString
,则它与Excel工作表中的值不完全相同。
修改:在此问题得到解决之前,我将使用
new BigDecimal(cell.getNumericCellValue()).toString()
答案 0 :(得分:11)
您在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));
}
格式化程序将按原样返回String单元格,对于Numeric单元格,将样式上的格式规则应用于单元格的数量
答案 1 :(得分:10)
如果要解析的文档始终采用特定布局,则可以在运行时将单元格类型更改为“string”,然后检索该值。例如,如果第2列应始终为字符串数据,请将其单元格类型设置为字符串,然后使用字符串类型的get方法读取它。
cell.setCellType(Cell.CELL_TYPE_STRING);
在我的测试中,更改单元格类型并未修改单元格的内容,但允许使用以下任一方法检索它:
cell.getStringCellValue();
cell.getRichStringCellValue().getString();
如果没有未正确转换的值的示例,很难知道它的行为是否与您在描述中描述的cell.toString()方法有任何不同。
答案 2 :(得分:6)
你的意思是HSSF-POI说
cell.getCellType() == Cell.CELL_TYPE_NUMERIC
不是
应该是 Cell.CELL_TYPE_STRING
吗?
我认为这是POI中的一个错误,但每个单元格都包含一个Variant,Variant有一个类型。在那里制作一个bug很难,所以我认为Excel使用一些额外的数据或启发式来将字段报告为文本。通常的MS方式,唉。
P.S。你不能在包含数字的Variant上使用任何getString()
,因为Variant数据的二进制表示取决于它的类型,并且尝试从实际数字中获取字符串将导致垃圾 - 因此异常。
答案 3 :(得分:4)
以下代码可以正常读取任何单元格类型,但该单元格应包含数值
new BigDecimal(cell.getNumericCellValue()));
e.g。
ase.setGss(new BigDecimal(hssfRow.getCell(3).getNumericCellValue()));
其中变量gss是BigDecimal类型。
答案 4 :(得分:2)
Excel将从字符串中转换任何看起来像数字或日期或时间的内容。请参阅MS Knowledge base article,其中基本上建议输入带有额外字符的数字,使其成为字符串。
答案 5 :(得分:1)
您可能正在处理Excel问题。创建电子表格时,默认单元格类型为Generic。使用此类型,Excel会根据输入猜测类型,并且每个单元格都会保存此类型。
稍后将单元格格式更改为“文本”时,您只需更改默认值。 Excel不会自动更改每个单元格的类型。我没有找到办法自动完成这项工作。
要确认这一点,您可以转到Excel并重新键入其中一个数字,然后查看它是否为HSSF中的文本。
您还可以使用此功能
查看真实的细胞类型 @Cell("type", A1)
A1是该数字的单元格。它显示文本“l”,数字显示“v”。
答案 6 :(得分:1)
Excel的问题是默认格式是通用的。使用此格式,Excel将在单元格中输入的数字存储为数字。您必须在>>输入值之前将格式更改为文本。更改格式后重新输入值也将起作用 如果内容看起来像Excel的数字,那将导致单元格左上角的绿色三角形变小。如果是这种情况,则该值实际上存储为文本。
使用新的BigDecimal(cell.getNumericCellValue())。toString(),你仍然会遇到很多问题。例如,如果您有识别号码(例如,部件号或分类号),则可能存在具有前导零的情况,这将是getNumericCellValue()方法的问题。
我尝试彻底解释如何正确创建Excel以创建我必须使用POI处理的文件。如果文件是由最终用户上传的,我甚至已经创建了一个验证程序,以便在我事先知道列时检查预期的单元格类型。作为副产品,您还可以检查所提供文件的各种其他内容(例如,提供的是正确的列还是必需的值)。
答案 7 :(得分:0)
“问题是我在一个看起来像数字的单元格中有值”=>在Excel中查看时看起来像数字?
“但确实是字符串”=>那是什么意思?你怎么知道他们真的是字符串?
“如果我查看格式单元格”=>什么是“格式单元格”???
'...在Excel中,它表示类型为“text”'=>请解释一下。
“HSSF Cell认为它仍然是数字。” =>你的意思是the_cell.getCellType()返回Cell.CELL_TYPE_NUMERIC?
“如何将值作为字符串获取?” => 如果是NUMERIC,请使用the_cell.getNumericCellValue()获取数值,然后以任意方式将其格式化为字符串。
“如果我尝试使用cell.getRichStringValue,我会得到异常;” =>所以它不是一个字符串。
“如果是cell.toString,它与Excel表格中的值不完全相同。” =>所以cell.toString()不会像Excel那样格式化它。
无论启发式Excel用于确定类型,都与您无关。这是存储在文件中并由重要的getCellType()显示的决定的结果。