如何将 Excel 单元格中的数字字符串读取为字符串(而不是数字)?
-
21-08-2019 - |
题
我有包含以下内容的 Excel 文件:
A1:一些字符串
A2:2
所有字段均设置为字符串格式。
当我使用 POI 在 java 中读取文件时,它告诉我 A2 是数字单元格格式。
- 问题是 A2 中的值可以是 2 或 2.0 (并且我希望能够区分它们),所以我不能只使用
.toString()
.
我该怎么做才能将值读取为字符串?
解决方案
我有同样的问题。我做到了 cell.setCellType(Cell.CELL_TYPE_STRING);
在读取字符串值之前,无论用户如何格式化单元格,这都解决了问题。
其他提示
当你问这个问题时,我认为我们还没有回到这堂课,但今天有一个简单的答案。
你想做的是使用 数据格式化类. 。您向其传递一个单元格,它会尽力返回一个字符串,其中包含 Excel 将向您显示的该单元格的内容。如果你向它传递一个字符串单元格,你就会得到该字符串。如果您向它传递一个应用了格式化规则的数字单元格,它将根据它们格式化数字并返回字符串。
对于您的情况,我假设数字单元格应用了整数格式规则。如果您要求 DataFormatter 设置这些单元格的格式,它会返回一个包含整数字符串的字符串。
另请注意,很多人建议这样做 cell.setCellType(Cell.CELL_TYPE_STRING)
, ,但是 Apache POI JavaDocs 非常明确地指出你不应该这样做!正在做的 setCellType
调用将丢失格式,因为 java文档解释 转换为字符串并保留格式的唯一方法是使用 数据格式化类.
下面的代码适用于任何类型的单元格。
InputStream inp =getClass().getResourceAsStream("filename.xls"));
Workbook wb = WorkbookFactory.create(inp);
DataFormatter objDefaultFormat = new DataFormatter();
FormulaEvaluator objFormulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook) wb);
Sheet sheet= wb.getSheetAt(0);
Iterator<Row> objIterator = sheet.rowIterator();
while(objIterator.hasNext()){
Row row = objIterator.next();
Cell cellValue = row.getCell(0);
objFormulaEvaluator.evaluate(cellValue); // This will evaluate the cell, And any type of cell will return string value
String cellValueStr = objDefaultFormat.formatCellValue(cellValue,objFormulaEvaluator);
}
当不需要修改单元格类型时,我建议使用以下方法:
if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
String str = NumberToTextConverter.toText(cell.getNumericCellValue())
}
NumberToTextConverter 可以使用 Excel 的规则正确地将双精度值转换为文本,而不会损失精度。
正如 Poi 的 JavaDocs 中已经提到的(https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html#setCellType%28int%29)不要使用:
cell.setCellType(Cell.CELL_TYPE_STRING);
但使用:
DataFormatter df = new DataFormatter();
String value = df.formatCellValue(cell);
是的,这很好用
受到推崇的:
DataFormatter dataFormatter = new DataFormatter();
String value = dataFormatter.formatCellValue(cell);
老的:
cell.setCellType(Cell.CELL_TYPE_STRING);
即使您在从中检索值时遇到问题 cell
有公式,仍然有效。
尝试:
new java.text.DecimalFormat("0").format( cell.getNumericCellValue() )
应正确格式化数字。
只要在用户输入数字之前单元格是文本格式,POI 就允许您获取字符串形式的值。一个关键是,如果格式化为文本的单元格左上角有一个绿色小三角形,您将能够以字符串形式检索其值(每当出现数字时,就会出现绿色三角形)被强制转换为文本格式)。如果您有包含数字的文本格式单元格,但 POI 不允许您以字符串形式获取这些值,您可以对电子表格数据执行以下操作:
- 双击单元格,使编辑光标出现在单元格内,然后单击 Enter(一次只能完成一个单元格)。
- 使用 Excel 2007 文本转换功能(可以一次在多个单元格上完成)。
- 将有问题的值剪切到另一个位置,将电子表格单元格重新格式化为文本,然后将之前剪切的值重新粘贴为 未格式化的值 回到正确的区域。
您可以做的最后一件事是,如果您使用 POI 从 Excel 2007 电子表格获取数据,则可以使用 Cell 类的“getRawValue()”方法。这并不关心格式是什么。它只会返回一个包含原始数据的字符串。
当我们使用 Apache POI 库读取 MS Excel 的数字单元格值时,它会将其读取为数字。但有时我们希望它读取为字符串(例如电话号码等)。我就是这样做的:
插入一个新列,其中第一个单元格 =CONCATENATE("!",D2)。我假设 D2 是您的电话号码列的单元格 ID。将新单元格拖到末尾。
现在,如果您使用 POI 读取单元格,它将读取公式而不是计算值。现在执行以下操作:
添加另一列
选择在步骤 1 中创建的完整列。并选择编辑->复制
转到步骤 3 中创建的列的顶部单元格。然后选择编辑->选择性粘贴
在打开的窗口中,选择“值”单选按钮
选择“确定”
现在使用 POI API 阅读...读完 Java 后...只需删除第一个字符即可“!”
我在数千个数字的数据集上也遇到了类似的问题,我认为我已经找到了一种简单的解决方法。我需要在数字之前插入撇号,以便单独的数据库导入始终将数字视为文本。在此之前,数字 8 将作为 8.0 导入。
解决方案:
- 将所有格式保留为常规。
- 这里我假设数字存储在从第 1 行开始的 A 列中。
- 在 B 列中输入 ' 并根据需要复制尽可能多的行。工作表中没有显示任何内容,但单击单元格,您可以在公式栏中看到撇号。
- 在 C 列中:=B1&A1。
- 选择 C 列中的所有单元格,然后使用“值”选项将特殊粘贴到 D 列中。
嘿,所有数字都转瞬即逝,但存储为文本。
如果单元格类型是数字,则 getStringCellValue 返回 NumberFormatException。如果您不想将单元格类型更改为字符串,可以这样做。
String rsdata = "";
try {
rsdata = cell.getStringValue();
} catch (NumberFormatException ex) {
rsdata = cell.getNumericValue() + "";
}
其中许多答案都引用了旧的 POI 文档和类。在最新的 POI 3.16 中, 具有 int 类型的单元格 已被弃用
Cell.CELL_TYPE_STRING
相反, 细胞类型枚举 可以使用。
CellType.STRING
请务必使用 poi 依赖项以及 poi-ooxml 依赖项将您的 pom 更新为新的 3.16 版本,否则您将继续遇到异常。此版本的一个优点是,您可以在创建单元格时指定单元格类型,从而消除前面答案中描述的所有额外步骤:
titleRowCell = currentReportRow.createCell(currentReportColumnIndex, CellType.STRING);
我更愿意走威尔的答案或 Vinayak Dornala 的路线,不幸的是他们对我的表现影响太大了。我去了一个 黑客 隐式转换的解决方案:
for (Row row : sheet){
String strValue = (row.getCell(numericColumn)+""); // hack
...
我不建议你这样做,对于我的情况来说,由于系统工作的性质,而且我有可靠的文件源,它是有效的。
脚注:NumericColumn是通过读取处理文件的标题而生成的INT。
public class Excellib {
public String getExceldata(String sheetname,int rownum,int cellnum, boolean isString) {
String retVal=null;
try {
FileInputStream fis=new FileInputStream("E:\\Sample-Automation-Workspace\\SampleTestDataDriven\\Registration.xlsx");
Workbook wb=WorkbookFactory.create(fis);
Sheet s=wb.getSheet(sheetname);
Row r=s.getRow(rownum);
Cell c=r.getCell(cellnum);
if(c.getCellType() == Cell.CELL_TYPE_STRING)
retVal=c.getStringCellValue();
else {
retVal = String.valueOf(c.getNumericCellValue());
}
我尝试过这个,它对我有用
我们遇到了同样的问题,并强制用户将单元格格式设置为“文本” 前 输入值。这样,Excel 就能正确地将偶数存储为文本。如果随后更改格式,Excel 只会更改值的显示方式,但不会更改值的存储方式,除非再次输入值(例如在单元格中按回车键)。
如果 Excel 认为单元格包含数字但格式为文本,则 Excel 会在单元格左上角显示绿色小三角形,以指示 Excel 是否正确地将值存储为文本。
你能控制 Excel 工作表吗?用户是否有一个模板可以为您提供输入?如果是这样,您可以使用代码格式化输入单元格。
cell.setCellType(Cell.CELL_TYPE_STRING);对我来说工作得很好
转换为 int 然后执行 .toString()
. 。它很丑,但很有效。
这对我来说很完美。
Double legacyRow = row.getCell(col).getNumericCellValue();
String legacyRowStr = legacyRow.toString();
if(legacyRowStr.contains(".0")){
legacyRowStr = legacyRowStr.substring(0, legacyRowStr.length()-2);
}