如何将Excel单元格中的数字字符串作为字符串(而非数字)读取?

时间:2009-07-02 04:50:56

标签: java excel apache-poi

  1. 我有excel文件包含这样的内容:

    • A1:SomeString

    • A2:2

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

  2. 当我使用POI在java中读取文件时,它告诉A2是数字单元格格式。

  3. 问题是A2中的值可以是2或2.0(我希望能够区分它们)所以我不能只使用.toString()
  4. 如何将值读取为字符串?

21 个答案:

答案 0 :(得分:296)

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

答案 1 :(得分:87)

当你提出这个问题时,我认为我们没有回复这个课程,但今天有一个简单的答案。

您要做的是使用DataFormatter class。你传递了一个单元格,它会尽力返回一个字符串,其中包含Excel为该单元格显示的内容。如果你传递一个字符串单元格,你将得到回来的字符串。如果您传递了一个应用了格式规则的数字单元格,它将根据它们格式化数字并返回字符串。

对于您的情况,我假设数字单元格应用了整数格式规则。如果你要求DataFormatter格式化这些单元格,它会返回一个包含整数字符串的字符串。

另外,请注意很多人建议cell.setCellType(Cell.CELL_TYPE_STRING)Apache POI JavaDocs quite clearly state that you shouldn't do this!执行setCellType调用将导致格式化失败,因为javadocs explain转换为格式为剩余的字符串的唯一方法是使用DataFormatter class

答案 2 :(得分:45)

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

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

}

答案 3 :(得分:25)

在修改单元格类型时,我建议使用以下方法:

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

NumberToTextConverter可以使用Excel的规则正确地将double值转换为文本,而不会出现精度损失。

答案 4 :(得分:15)

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

http://massapi.com/class/da/DataFormatter.html

上的更多示例

答案 5 :(得分:5)

是的,这完美无缺

建议:

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

旧:

cell.setCellType(Cell.CELL_TYPE_STRING);

即使您从cell检索具有公式的值时遇到问题,仍然可行。

答案 6 :(得分:4)

尝试:

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

应正确格式化数字。

答案 7 :(得分:1)

只要在用户输入数字之前单元格是文本格式,POI就会允许您以字符串形式获取值。一个关键是,如果单元格的左上角有一个绿色小三角形,格式为文本,您将能够将其值检索为字符串(只要看起来像是一个数字,就会出现绿色三角形被强制成文本格式)。如果您有包含数字的文本格式化单元格,但POI不允许您将这些值作为字符串获取,那么您可以对电子表格数据执行一些操作以允许:

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

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

答案 8 :(得分:0)

有一个现成的包装器 (可以应用一些其他优化)

  • 它支持数字和字符串单元格

  • 公式被自动识别并处理

  • 避免重复使用

     public final class Cell {
    
     private final static DataFormatter FORMATTER = new DataFormatter();
    
     private XSSFCell mCell;
    
     public Cell(@NotNull XSSFCell cell) {
         mCell = cell;
    
         if (isFormula()) {
             XSSFWorkbook book = mCell.getSheet().getWorkbook();
             FormulaEvaluator evaluator = book.getCreationHelper().createFormulaEvaluator();
             mCell = (XSSFCell) evaluator.evaluateInCell(mCell);
         }
     }
    
     /**
      * Get content
      */
     public final int getInt() {
         return (int) getLong();
     }
    
     public final long getLong() {
         return Math.round(getDouble());
     }
    
     public final double getDouble() {
         return mCell.getNumericCellValue();
     }
    
     public final String getString() {
         if (!isString()) {
             return FORMATTER.formatCellValue(mCell);
         }
         return mCell.getStringCellValue();
     }
    
     /**
      * Get properties
      */
     public final boolean isNumber() {
         if (isFormula()) {
             return mCell.getCachedFormulaResultType().equals(CellType.NUMERIC);
         }
         return mCell.getCellType().equals(CellType.NUMERIC);
     }
    
     public final boolean isString() {
         if (isFormula()) {
             return mCell.getCachedFormulaResultType().equals(CellType.STRING);
         }
         return mCell.getCellType().equals(CellType.STRING);
     }
    
     public final boolean isFormula() {
         return mCell.getCellType().equals(CellType.FORMULA);
     }
    
     /**
      * Debug info
      */
     @Override
     public String toString() {
         return getString();
     }
     }
    

答案 9 :(得分: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());
        }

我尝试了这个并且对我有用

答案 10 :(得分:0)

我更愿意选择Wil的回答路线或Vinayak Dornala,不幸的是,他们的表现远远超过了我。 我选择了 HACKY 隐式转换的解决方案:

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

我不建议你这样做,因为我的情况很有效,因为系统工作的性质和我有一个可靠的文件来源。

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

答案 11 :(得分:0)

其中许多答案都引用了旧的POI文档和类。在最新的POI 3.16中,Cell with the int types已被弃用

Cell.CELL_TYPE_STRING

enter image description here

而是可以使用CellType enum

CellType.STRING 

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

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

答案 12 :(得分:0)

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

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

答案 13 :(得分:0)

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

解决方案:

  • 将所有格式设置为“常规”。
  • 这里我假设数字从第1行开始存储在A列中。
  • 放入B列中的'并根据需要复制尽可能多的行。工作表中没有任何内容,但单击单元格可以看到公式栏中的撇号。
  • 在C栏中:= B1&amp; A1。
  • 选择C列中的所有单元格,然后使用“值”选项在“列D”中执行“将特殊区域粘贴”。

嘿Presto所有数字,但存储为文本。

答案 14 :(得分:0)

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

  1. 插入一个新列,第一个单元格= CONCATENATE(“!”,D2)。我假设D2是您的电话号码列的小区ID。将新单元格拖动到最后。

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

  3. 添加其他列

  4. 选择在步骤1中创建的完整列,然后选择编辑 - &gt;复制

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

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

  7. 选择“确定”

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

答案 15 :(得分:-1)

cell.setCellType(Cell.CELL_TYPE_STRING);对我来说工作正常

答案 16 :(得分:-1)

根据以下事实,看起来在当前版本的POI中无法做到这一点:

https://issues.apache.org/bugzilla/show_bug.cgi?id=46136

仍然很出色。

答案 17 :(得分:-1)

这对我来说非常适合。

localhost

答案 18 :(得分:-1)

你是否还在控制excel工作表?是否有用户为您提供输入的模板?如果是这样,您可以为您输入代码格式化输入单元格。

答案 19 :(得分:-1)

我们遇到了同样的问题,并强制我们的用户在输入值之前将单元格格式化为“text”。这样Excel就能正确存储偶数作为文本。 如果之后更改格式,则Excel仅更改显示值的方式,但不会更改值的存储方式,除非再次输入值(例如,在单元格中按回车键)。

Excel是否正确地将值存储为文本由Excel显示在单元格左上角的小绿色三角形指示,如果它认为单元格包含数字但是格式化为文本。

答案 20 :(得分:-1)

转换为int然后执行.toString()。它很丑,但它确实有效。