如何读取Excel单元格中的数字string作为string(不是数字)?
-
我有这样的内容excel文件:
-
A1:SomeString
-
A2:2
所有字段都设置为string格式。
-
-
当我使用POI在java中读取文件时,它告诉A2是数字单元格格式。
- 问题是,在A2中的值可以是2或2.0(我想能够区分它们),所以我不能只使用
.toString()
。
我能做些什么来读取string的值?
我有同样的问题。 我做了cell.setCellType(Cell.CELL_TYPE_STRING);
在读取string值之前,无论用户如何格式化单元格,解决了问题。
当你问这个问题时,我不认为我们有这个课,但今天有一个简单的答案。
你想要做的是使用DataFormatter类 。 您将这个单元格传递给它,并尽可能返回一个包含Excel将向您显示该单元格的string。 如果你传递一个string单元格,你会得到string。 如果您将格式化规则应用于数字单元格,则会根据格式化数字并将string返回。
对于你的情况,我会假设数字单元格有一个整数格式化规则适用于他们。 如果您要求DataFormatter格式化这些单元格,则会返回一个包含整数string的string。
此外,请注意,很多人build议做cell.setCellType(Cell.CELL_TYPE_STRING)
,但是Apache POI JavaDocs很清楚地表明你不应该这样做 ! 执行setCellType
调用会松散格式化,因为javadoc解释了转换为格式剩余的String的唯一方法是使用DataFormatter类 。
下面的代码适用于任何types的单元格。
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); }
当修改单元格types是不可取的时,我会推荐以下方法:
if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC) { String str = NumberToTextConverter.toText(cell.getNumericCellValue()) }
NumberToTextConverter可以使用Excel的规则将double值正确地转换为文本,而不会丢失精确度。
正如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);
尝试:
new java.text.DecimalFormat("0").format( cell.getNumericCellValue() )
应正确格式化数字。
是的,这是完美的
cell.setCellType(Cell.CELL_TYPE_STRING);
即使你在从具有公式的cell
中检索值时遇到问题,仍然有效。
只要在用户键入数字之前单元格是文本格式,POI将允许您以stringforms获取该值。 一个关键是如果格式化为文本的单元格左上angular有一个小的绿色三angular形,则可以以string的forms检索其值(绿色三angular形出现在看起来像是数字的地方被强制为文本格式)。 如果您的文本格式的单元格包含数字,但POI不会让您将这些值作为string获取,则可以对电子表格数据执行以下操作:
- 双击单元格,使编辑光标出现在单元格内,然后单击Enter(一次只能完成一个单元格)。
- 使用Excel 2007文本转换function(可以一次在多个单元格中完成)。
- 将违规值剪切到另一个位置,将文本格式的电子表格单元格重新格式化,然后将之前删除的值作为无格式值重新join适当的区域。
你可以做的最后一件事是,如果你使用POI从Excel 2007电子表格中获取数据,你可以使用Cell类的getRawValue()方法。 这不关心格式是什么。 它将简单地返回一个string与原始数据。
你可以预先在Excel中的string撇号? 它们不会显示在工作表上,而是强制单元格格式为文本,并且可以在导入过程中识别并剥离/强制。
我们遇到同样的问题,并迫使我们的用户在input值之前将单元格格式化为“文本”。 这样Excel正确地存储偶数作为文本。 如果格式改变之后,Excel只改变数值的显示方式,但不改变数值的存储方式,除非再次input数值(例如在单元格中按回车键)。
Excel是否正确地将值存储为文本,如果Excel认为单元格中包含一个数字,并将其格式化为文本,则Excel将在该单元格的左上angular显示一个绿色的小三angular形。
你是否控制了Excel工作表呢? 有没有用户给你的input模板? 如果是这样,你可以为你input单元格格式。
当我们使用Apache POI库读取MS Excel的数字单元格值时,将其作为数字读取。 但有时我们希望它读取为string(例如电话号码等)。 这是我做到的:
-
用第一个单元格= CONCATENATE(“!”,D2)插入一个新列。 我假设D2是您的电话号码列的单元ID。 拖动新的单元格结束。
-
现在,如果使用POI读取单元格,它将读取公式而不是计算值。 现在做以下事情:
-
添加另一列
-
select在步骤1中创build的完整列,然后select“编辑” – >“复制”
-
转到步骤3中创build的列的顶部单元格,然后select编辑 – >select性粘贴
-
在打开的窗口中,select“值”单选button
-
select“确定”
-
现在阅读使用POI API …阅读Java后…只是删除第一个字符,即“!”
我在数千个数据集上也遇到类似的问题,我想我已经find了一个简单的解决方法。 我需要在数字之前插入撇号,以便单独的数据库导入始终将数字视为文本。 在此之前,数字8将被导入为8.0。
解:
- 保持所有格式为一般。
- 在这里,我假设数字存储在第1行的列A中。
- 放在B列中,根据需要复制多行。 工作表中没有显示任何内容,但单击单元格,可以在“公式”栏中看到“启动”。
- 在C列:= B1&A1。
- select列C中的所有单元格,并使用值选项将特殊选项粘贴到列D中。
嘿Presto所有的数字,但存储为文本。
如果单元格types是数字,getStringCellValue将返回NumberFormatException。 如果您不想将单元格types更改为string,则可以执行此操作。
String rsdata = ""; try { rsdata = cell.getStringValue(); } catch (NumberFormatException ex) { rsdata = cell.getNumericValue() + ""; }
cell.setCellType(Cell.CELL_TYPE_STRING); 对我来说工作正常
强制转换为int,然后执行.toString()
。 这是丑陋的,但它的工作。
许多这些答案引用了旧的POI文档和类。 在最新的POI 3.16中, 具有inttypes的Cell已被弃用
Cell.CELL_TYPE_STRING
而是可以使用CellType枚举 。
CellType.STRING
只要确保将poi依赖项以及poi-ooxml依赖项更新到新的3.16版本,否则您将继续得到exception。 这个版本的一个优点是,你可以在创build单元格时指定单元格types,从而消除以前答案中所描述的所有额外步骤:
titleRowCell = currentReportRow.createCell(currentReportColumnIndex, CellType.STRING);
这对我来说非常合适。
Double legacyRow = row.getCell(col).getNumericCellValue(); String legacyRowStr = legacyRow.toString(); if(legacyRowStr.contains(".0")){ legacyRowStr = legacyRowStr.substring(0, legacyRowStr.length()-2); }