如何在Excel单元格中将数字字符串读取为字符串(不是数字)?


146
  1. 我有这样的内容的Excel文件:

    • A1:SomeString

    • A2:2

    所有字段均设置为字符串格式。

  2. 当我使用POI读取Java中的文件时,它表明A2为数字单元格格式。

  3. 问题在于A2中的值可以是2或2.0(并且我希望能够区分它们),所以我不能只使用.toString()

如何将值读取为字符串?

Answers:


319

我有同样的问题。我cell.setCellType(Cell.CELL_TYPE_STRING);在读取字符串值之前做了此操作,无论用户如何格式化单元格,它都能解决问题。


我使用poi-3.8-beta4,它按预期工作!TS为什么不接受此答案?
swdev 2012年

请注意,POI数值到字符串的转换未考虑系统区域设置,它始终使用点作为小数点分隔符。例如,如果您的系统使用“,”,并且在Excel中数字看起来像“ 1,9”,则POI将返回“ 1.9”。
Alexey Berezkin 2013年

53
请注意,Apache POI javadocs明确表示不这样做!正如他们所解释的,您应该改用DataFormatter
Gagravarr 2015年

6
Gagravarr禁止这样做的警告是正确的!从文档中:“如果要为数字单元格获取字符串值,请停止!。这不是这样做的方法。相反,要获取数字或布尔值或日期单元格的字符串值,请使用而是使用DataFormatter。” poi.apache.org/apidocs/org/apache/poi/ss/usermodel / ... 我一直在使用这种技术,直到我无意间更改了我不想更改的数据。(将类型设置为字符串,读取值,将类型设置回数字,再次读取并获得其他数字值!)
克里斯·芬利

6
使用DataFormatter。Javadoc警告我们不要使用以上方法。
Balu SKT '02

96

当您提出问题时,我认为我们没有上过这堂课,但是今天有一个简单的答案。

您要做的是使用DataFormatter类。您将其传递给一个单元格,它会尽力返回一个字符串,其中包含Excel将对该单元格显示的内容。如果将字符串单元格传递给它,则将字符串取回。如果您向其传递一个应用了格式设置规则的数字单元格,它将根据它们格式化数字并返回字符串。

对于您的情况,我假设数字单元格已应用整数格式设置规则。如果您要求DataFormatter格式化这些单元格,它将给您返回其中包含整数字符串的字符串。

另外,请注意,很多人建议这样做cell.setCellType(Cell.CELL_TYPE_STRING),但是Apache POI JavaDocs明确指出您不应该这样做!进行setCellType调用将导致格式设置松散,因为javadocs解释了剩下的格式转换为String的唯一方法是使用DataFormatter类


感谢@Gagravarr仅您的答案对我有用,<code> cell.setCellType(Cell.CELL_TYPE_STRING); <code>将2.2值转换为2.2000000000000002,但是我想要2.2。它以字符串格式返回任何内容谢谢
ankush yadav

dataformatter似乎不适用于公式单元格,它返回公式的字符串表示形式而不是值
gaurav5430 '16

1
仅需一点注意:请提供简短的代码段,以供回答,也请在提供的链接中进行说明
BAERUS

@ gaurav5430是的,它与公式配合得不太好...根据文件,When passed a null or blank cell, this method will return an empty String (""). Formulas in formula type cells will not be evaluated.
SaratBhaswanth

53

以下代码适用于任何类型的单元格。

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);

}

4
工作得很好!我的建议是更改FormulaEvaluator的检索方式。Workbook类通过该getCreationHelper().createFormulaEvaluator()方法提供了一个公式评估器。这样,您的代码将不会与HSSFFormulaEvaluator类结合使用。
Vitor Santos

这应该是公认的答案。感谢@Vinayak
Phas1c

可以FormulaEvaluator简单地从该解决方案中删除吗?它有目的吗?
P.Brian.Mackey

1
不需要调用objFormulaEvaluator.evaluate。那的返回值在这里没有被使用。
Radu Simionescu

32

当不希望修改单元格的类型时,我建议使用以下方法:

if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
    String str = NumberToTextConverter.toText(cell.getNumericCellValue())
}

NumberToTextConverter可以使用Excel规则将双精度值正确转换为文本,而不会造成精度损失。


真是令人兴奋的建议!谢谢!与将cellType设置为String相比,它允许获取未转换的值。
Gleb Egunov

我得到44007作为单元格值25/06/2020的输出。我究竟做错了什么?
Vinay


10

是的,这很完美

推荐的:

        DataFormatter dataFormatter = new DataFormatter();
        String value = dataFormatter.formatCellValue(cell);

旧:

cell.setCellType(Cell.CELL_TYPE_STRING);

即使您在通过cell公式检索值时遇到问题,仍然可以使用。


5
但是您必须谨慎使用此值作为double值。对我来说,它将值7.9转换为7.8999956589965 ...
克里斯(Chris)

2
Apache的POI的javadoc是很清楚的,你不应该这样做是如果你想要做的是得到一个字符串值,为您的数字小区,停!这不是这样做的方法。相反,要获取数字或布尔值或日期单元格的字符串值,请使用DataFormatter。
加格雷瓦尔2016年

4

尝试:

new java.text.DecimalFormat("0").format( cell.getNumericCellValue() )

应该正确格式化数字。


据我了解,申请者希望能够区分22.0。您的解决方案无法做到这一点。(但仍然欢迎Stack Overflow!)
PaŭloEbermann 2011年

1

只要用户输入数字之前该单元格为文本格式,POI便可以让您以字符串形式获取该值。一个关键是,如果单元格的左上角有一个小小的绿色三角形,其格式设置为“文本”,则您将能够以字符串形式检索其值(只要出现数字,该绿色三角形就会出现强制转换为文本格式)。如果您具有包含数字的文本格式的单元格,但是POI不允许您将这些值作为字符串获取,则可以对电子表格数据执行以下操作以允许这样做:

  • 双击单元格,使编辑光标出现在单元格中,然后单击Enter(一次只能完成一个单元格)。
  • 使用Excel 2007文本转换功能(可以一次在多个单元格上完成)。
  • 将有问题的值切出到另一个位置,将电子表格单元格重新格式化为文本,然后将以前切出的值重新格式化为“未格式化的值”,放回到适当的区域。

您可以做的最后一件事是,如果使用POI从Excel 2007电子表格中获取数据,则可以使用Cell类的“ getRawValue()”方法。这并不关心格式是什么。它只会返回带有原始数据的字符串。


0

当我们使用Apache POI库读取MS Excel的数字单元格值时,它会将其读取为数字。但是有时候我们希望它读为字符串(例如电话号码等)。这是我的方法:

  1. 用第一个单元格= CONCATENATE(“!”,D2)插入新列。我假设D2是您的电话号码列的手机ID。向上拖动新单元格。

  2. 现在,如果您使用POI读取单元格,它将读取公式而不是计算值。现在执行以下操作:

  3. 添加另一列

  4. 选择在步骤1中创建的完整列,然后选择“编辑”->“复制”

  5. 转到在步骤3中创建的列的顶部单元格。然后选择“编辑”->“选择性粘贴”

  6. 在打开的窗口中,选择“值”单选按钮

  7. 选择“确定”

  8. 现在,使用POI API进行阅读...用Java读取之后...只需删除第一个字符即“!”


如果自己不生成excel文件,您的解决方案似乎不可用,是吗?(另外,您能否将摘录添加到您的答案中?时间不会太长。)
PaŭloEbermann 2011年

是的,如果自己不生成excel文件,则不能使用它。
阿西夫·沙扎德

0

在成千上万的数据集上我也遇到过类似的问题,我认为我找到了一种简单的解决方法。我需要在数字前插入撇号,以便单独的数据库导入始终将数字视为文本。在此之前,数字8将被导入为8.0。

解:

  • 保持所有格式为常规。
  • 在这里,我假设数字从第1行开始存储在A列中。
  • 在B列中放入',然后根据需要向下复制尽可能多的行。工作表中什么都没有显示,但是单击该单元格,您可以在公式栏中看到撇号。
  • 在C列中:= B1&A1。
  • 选择列C中的所有单元格,然后使用“值”选项将特殊粘贴粘贴到列D中。

嘿普雷斯托所有的数字,但存储为文本。


0

如果单元格类型为数字,则getStringCellValue返回NumberFormatException。如果您不想将单元格类型更改为字符串,则可以执行此操作。

String rsdata = "";
try {
    rsdata = cell.getStringValue();
} catch (NumberFormatException ex) {
    rsdata = cell.getNumericValue() + "";
}

0

这些答案中有许多参考旧的POI文档和类。在最新的POI 3.16中,不推荐使用具有int类型的Cell

Cell.CELL_TYPE_STRING

在此处输入图片说明

而是可以使用CellType枚举

CellType.STRING 

只需确保使用poi依赖项以及poi-ooxml依赖项将pom更新到新的3.16版本,否则您将继续获得异常。此版本的一个优点是,您可以在创建单元格时指定单元格类型,从而消除了先前答案中描述的所有其他步骤:

titleRowCell = currentReportRow.createCell(currentReportColumnIndex, CellType.STRING);

0

我更愿意选择wil的答案或Vinayak Dornala的方法,不幸的是,它们对我的表现影响很大。我去了一个隐式转换的HACKY解决方案:

for (Row row : sheet){
String strValue = (row.getCell(numericColumn)+""); // hack
...

我不建议您这样做,因为我的情况是可行的,因为系统是如何工作的,并且我拥有可靠的文件源。

脚注:numericColumn是从读取已处理文件的标头生成的int。


0
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());
        }

我试过了,对我有用


-1

您是否仍然控制excel工作表?用户是否有模板可以为您提供输入?如果是这样,您可以使用代码为输入单元格设置格式。




-1

这对我来说很完美。

Double legacyRow = row.getCell(col).getNumericCellValue();
String legacyRowStr = legacyRow.toString();
if(legacyRowStr.contains(".0")){
    legacyRowStr = legacyRowStr.substring(0, legacyRowStr.length()-2);
}

-2

我们遇到了同样的问题,并迫使我们的用户输入值之前将单元格格式设置为“文本” 。这样,Excel可以将偶数正确地存储为文本。如果此后更改了格式,则Excel仅会更改值的显示方式,而不会更改值的存储方式,除非再次输入值(例如,在单元格中按回车键)。

如果Excel认为该单元格包含数字但格式设置为文本,则Excel会在该单元格的左上角显示绿色的小三角形,以指示Excel是否将值正确存储为文本。


-3

转换为int然后执行.toString()。这是丑陋的,但有效。


问题是,如果A2中有2.0,我需要获取字符串“ 2.0”,如果有2,则需要获取字符串“ 2”。
joycollector
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.