无法从数字单元格获取文本值“Poi”

80

我想从Excel电子表格中读取数据,但总是出现错误。我已经尝试将工作表格式设置为文本和数字,但错误仍然存在。

我看到一个人使用了cell.setCellType(Cell.CELL_TYPE_STRING);解决了这个问题,但我不知道在我的代码中应该在哪里加入这行代码。

WebElement searchbox = driver.findElement(By.name("j_username"));
WebElement searchbox2 = driver.findElement(By.name("j_password"));         

try {
    FileInputStream file = new FileInputStream(new File("C:\\paulo.xls")); 
    HSSFWorkbook workbook = new HSSFWorkbook(file);
    HSSFSheet sheet = workbook.getSheetAt(0);

    for (int i=1; i <= sheet.getLastRowNum(); i++){
        String j_username = sheet.getRow(i).getCell(0).getStringCellValue();
        String j_password = sheet.getRow(i).getCell(0).getStringCellValue();

        searchbox.sendKeys(j_username);
        searchbox2.sendKeys(j_password);
        searchbox.submit();  

        driver.manage().timeouts().implicitlyWait(10000, TimeUnit.MILLISECONDS);
    }

    workbook.close();
    file.close();
} catch (FileNotFoundException fnfe) {
    fnfe.printStackTrace();
} catch (IOException ioe) {
    ioe.printStackTrace();

你能放置完整的堆栈跟踪错误信息吗? - Anatoly
10
sheet.getRow(i).getCell(0).toString() 是什么意思? - Abdull
1
@Abdull,你的评论比官方答案还有用 :) 解决了我的问题。 - pouyan021
1
如果您需要将数字类型转换为字符串形式,请尝试使用cell.getRawValue():https://dev59.com/h8_wz4gBFxS5KdRjRuRo - Criss
14个回答

95

在这种情况下,格式化程序将工作良好。

import org.apache.poi.ss.usermodel.DataFormatter;

FileInputStream fis = new FileInputStream(workbookName);
Workbook workbook = WorkbookFactory.create(fis);
Sheet sheet = workbook.getSheet(sheetName);
DataFormatter formatter = new DataFormatter();
String val = formatter.formatCellValue(sheet.getRow(row).getCell(col));
list.add(val);   //Adding value to list

3
这个东西对我不起作用,它的输出结果类似于:SUM(I38 + D39 +F39 - G39 - H39)。 - S Gaber
@SGaber,你需要将一个公式求值器作为formatCellValue方法的第二个参数提供,这样它才能正确地格式化公式。 - Andy

58

    Cell cell = sheet.getRow(i).getCell(0);
    cell.setCellType ( Cell.CELL_TYPE_STRING );
    String j_username = cell.getStringCellValue();

更新

好的,正如评论中所说,尽管这个方法可以工作,但它不是从Excel单元格中检索数据的正确方法。

根据手册这里

如果您想要获取数字单元格的字符串值,请停止!这不是这样做的方式。相反,为了获取数值或布尔值或日期单元格的字符串值,请使用DataFormatter。

根据DataFormatter API

DataFormatter包含用于格式化存储在单元格中的值的方法。这对于报告和GUI演示非常有用,当您需要精确显示与Excel中完全相同的数据时。支持的格式包括货币、社会安全号码、百分比、小数、日期、电话号码、邮政编码等。

因此,显示数字单元格的值的正确方式如下:

 DataFormatter formatter = new DataFormatter(); //creating formatter using the default locale
 Cell cell = sheet.getRow(i).getCell(0);
 String j_username = formatter.formatCellValue(cell); //Returns the formatted value of a cell as a String regardless of the cell type.

for (int i = 1; i <= sheet.getLastRowNum(); i++) { Cell cell = sheet.getRow(i).getCell(0); cell.setCellType(Cell.CELL_TYPE_STRING); String j_username = cell.getStringCellValue(); } - Paulo Roberto
出现了三个错误:类型不匹配:无法将HSSFCell转换为Table.Cell CELL_TYPE_STRING无法解析或不是字段 方法getStringCellValue()对于类型Table.Cell未定义 - Paulo Roberto
电子表格中只有数字89550536100002595717。 - Paulo Roberto
不要这样做!POI javadocs非常清楚,这不是正确的方法! - Gagravarr
@Gagravarr,你说得对。我不知道这个,稍后会修正我的回答。 - Anatoly
显示剩余3条评论

14
根据Apache POI Javadocs所述,您不应使用cell.setCellType(Cell.CELL_TYPE_STRING)来获取数字单元格的字符串值,因为这将导致所有格式丢失。
相反,如javadocs所述,应使用DataFormatter
DataFormatter所做的是将存储在文件中的表示单元格的浮点值和应用于其上的格式规则一起处理,并返回一个看起来像Excel中该单元格的字符串。
因此,如果您想要一个字符串形式的单元格,它看起来与Excel中的样子非常相似,只需执行以下操作:
 // Create a formatter, do this once
 DataFormatter formatter = new DataFormatter(Locale.US);

 .....

 for (int i=1; i <= sheet.getLastRowNum(); i++) {
        Row r = sheet.getRow(i);
        if (r == null) { 
           // empty row, skip
        } else {
           String j_username = formatter.formatCellValue(row.getCell(0));
           String j_password =  formatter.formatCellValue(row.getCell(1));

           // Use these
        }
 }

格式化程序将原样返回字符串单元格,并对数字单元格应用样式中的格式规则。


1
这个东西对我来说不起作用,它的输出类似于:SUM(I38+D39+F39-G39-H39)。 - S Gaber

9

在读取字符串值之前,使用代码
cell.setCellType(Cell.CELL_TYPE_STRING);
可以帮助您。 我正在使用POI 3.17 Beta1版本, 确保版本兼容性也要注意。


6
使用 DataFormatter 可以解决这个问题。感谢 "Gagravarr" 的初始帖子。
DataFormatter formatter = new DataFormatter();

String empno = formatter.formatCellValue(cell0);

1
这个东西对我来说不起作用,它的输出类似于:SUM(I38+D39+F39-G39-H39)。 - S Gaber

4
CellType cell = row.getCell(j).getCellTypeEnum();

switch(cell) {
    case NUMERIC:
        intVal = row.getCell(j).getNumericCellValue();
        System.out.print(intVal);
        break;
    case STRING:
        stringVal = row.getCell(j).getStringCellValue();
        System.out.print(stringVal);
        break;
}

2

不同单元格类型的辅助方法:

private static String returnStringValue(Cell cell) {
    CellType cellType = cell.getCellType();

    switch (cellType) {
        case NUMERIC -> {
            double doubleVal = cell.getNumericCellValue();
            if (doubleVal == (int) doubleVal) {
                int value = Double.valueOf(doubleVal).intValue();
                return String.valueOf(value);
            } else {
                return String.valueOf(doubleVal);
            }
        }
        case STRING -> {
            return cell.getStringCellValue();
        }
        case ERROR -> {
            return String.valueOf(cell.getErrorCellValue());
        }
        case BLANK -> {
            return "";
        }
        case FORMULA -> {
            return cell.getCellFormula();
        }
        case BOOLEAN -> {
            return String.valueOf(cell.getBooleanCellValue());
        }
    }
    return "error decoding string value of the cell";

}

1

使用那段代码,它一定有效,并且我已经进行了修改。

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
//import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.*;

public class TestApp {

    public static void main(String[] args) throws Exception {

        try {

            Class forName = Class.forName("com.mysql.jdbc.Driver");
            Connection con = null;
            con = DriverManager.getConnection("jdbc:mysql://localhost/tables", "root", "root");
            con.setAutoCommit(false);
            PreparedStatement pstm = null;
            FileInputStream input = new FileInputStream("C:\\Users\\Desktop\\a1.xls");
            POIFSFileSystem fs = new POIFSFileSystem(input);
            Workbook workbook;
            workbook = WorkbookFactory.create(fs);
            Sheet sheet = workbook.getSheetAt(0);
            Row row;
            for (int i = 1; i <= sheet.getLastRowNum(); i++) {
                row = (Row) sheet.getRow(i);
                String name = row.getCell(0).getStringCellValue();
                String add = row.getCell(1).getStringCellValue();

                int  contact = (int) row.getCell(2).getNumericCellValue();

                String email = row.getCell(3).getStringCellValue();

                String sql = "INSERT INTO employee (name, address, contactNo, email) VALUES('" + name + "','" + add + "'," + contact + ",'" + email + "')";
                pstm = (PreparedStatement) con.prepareStatement(sql);
                pstm.execute();
                System.out.println("Import rows " + i);
            }
            con.commit();
            pstm.close();
            con.close();
            input.close();
            System.out.println("Success import excel to mysql table");
        } catch (IOException e) {
        }
    }

}

如果您没有添加库文件,最有可能发生的情况是缺少以下文件:1)dom4j-1.6.jar 2)xmlbeans-2.3.0.jar 3)poi-ooxml-schemas-3.9.jar 4)poi-ooxml-3.9.jar 5)poi-3.10-FINAL.jar。 - Harshil Kulkarni

1
你可以在循环内添加 cell.setCellType(Cell.CELL_TYPE_STRING);,这样它就会按照你的要求处理单元格。
以下是代码:
WebElement searchbox = driver.findElement(By.name("j_username"));
WebElement searchbox2 = driver.findElement(By.name("j_password"));         

try {
    FileInputStream file = new FileInputStream(new File("C:\\paulo.xls")); 
    HSSFWorkbook workbook = new HSSFWorkbook(file);
    HSSFSheet sheet = workbook.getSheetAt(0);

    for (int i=1; i <= sheet.getLastRowNum(); i++){
        // Row will be iterated and Cell will be 0 and 1 as per the example:   
        row.getCell(0).setCellType(CellType.STRING); // set Cell Type as String
        row.getCell(1).setCellType(CellType.STRING); // set Cell Type as String

        String j_username = sheet.getRow(i).getCell(0).getStringCellValue();
        String j_password = sheet.getRow(i).getCell(1).getStringCellValue();

        searchbox.sendKeys(j_username);
        searchbox2.sendKeys(j_password);
        searchbox.submit();  

        driver.manage().timeouts().implicitlyWait(10000, TimeUnit.MILLISECONDS);
    }

    workbook.close();
    file.close();
} catch (FileNotFoundException fnfe) {
    fnfe.printStackTrace();
} catch (IOException ioe) {
    ioe.printStackTrace();

1
public class B3PassingExcelDataBase {


    @Test()
    //Import the data::row start at 3 and column at 1: 
    public static void imortingData () throws IOException {

        FileInputStream  file=new         FileInputStream("/Users/Downloads/Book2.xlsx");
        XSSFWorkbook book=new XSSFWorkbook(file);
        XSSFSheet sheet=book.getSheet("Sheet1");

        int rowNum=sheet.getLastRowNum();
        System.out.println(rowNum);

        //get the row and value and assigned to variable to use in application
        for (int r=3;r<rowNum;r++) {

            // Rows stays same but column num changes and this is for only one person. It iterate for other.
             XSSFRow currentRow=sheet.getRow(r);

             String fName=currentRow.getCell(1).toString();
             String lName=currentRow.getCell(2).toString();
             String phone=currentRow.getCell(3).toString();
             String email=currentRow.getCell(4).toString()

               //passing the data
                yogen.findElement(By.name("firstName")).sendKeys(fName);    ;
                yogen.findElement(By.name("lastName")).sendKeys(lName); ;
                yogen.findElement(By.name("phone")).sendKeys(phone);    ;

        }

        yogen.close();


    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接