【问题标题】:Reading cell values from excel file using Apache POI使用 Apache POI 从 excel 文件中读取单元格值
【发布时间】:2023-03-12 01:23:01
【问题描述】:

我正在使用 Selenium 2 并设置了一个 LoginTest.java 文件,该文件从数据驱动的 excel 文件中读取。我读入用户名和密码并在登录页面上运行它。它实际上运行良好。数据如下所示:

用户1 pw1
用户 2 pw2
用户 3 pw3
用户4 pw4

问题是这样的:如果我修改 excel 文件并将参数的数量更改为如下所示:

用户1 pw1
用户2 pw2

并运行相同的脚本,ReadExcel 类文件返回错误消息:

“不支持这种类型的单元格”。

我认为发生了什么,是第 3 行和第 4 行 用于 在其单元格中包含数据(user3 pw3 和 user4 pw4),而现在它们没有......所以有些不同关于我的ExcelRead() 类没有被忽略的那些以前使用过的单元格。我敢打赌,这个单元格现在是“空”的,而以前不是,反之亦然。以前保存数据的单元格与从未保存数据的单元格有所不同。

(我在互联网上找到了ExcelRead 并正在使用它。我自己没有从头开始创建它。除了这个“问题”之外,它似乎可以很好地读取 xcel 文件)。

感谢您的帮助。

public class ExcelRead {
    public Object[][] main( String[] args) throws Exception{        
    File excel = new File(args[0]);
    FileInputStream fis = new FileInputStream(excel);
    HSSFWorkbook wb = new HSSFWorkbook(fis);
    HSSFSheet ws = wb.getSheet(args[1]);

    int rowNum = ws.getLastRowNum() + 1;
    int colNum = ws.getRow(0).getLastCellNum();
    String[][] data = new String[rowNum][colNum];

    for (int i = 0 ; i < rowNum ; i++) {
        HSSFRow row = ws.getRow(i);
            for (int j = 0 ; j < colNum ; j++) {
                HSSFCell cell = row.getCell(j);
                String value = cellToString(cell);
                data[i][j] = value ;
                //System.out.println("the value is " + value);
            }
        }
    return data;
    }

public static String cellToString(HSSFCell cell) {  
    int type;
    Object result;
    type = cell.getCellType();

    switch (type) {

        case 0: // numeric value in Excel
            result = cell.getNumericCellValue();
            break;
        case 1: // String Value in Excel 
            result = cell.getStringCellValue();
            break;
        default:  
            throw new RuntimeException("There is no support for this type of cell");                        
    }

    return result.toString();
}

【问题讨论】:

    标签: java selenium apache-poi


    【解决方案1】:

    您下载的代码使用 Java Apache POI 库来读取 excel 文件。如果您仔细阅读代码,您将看到 cellToString() 方法无法处理所有类型的单元格类型 - 它仅查找数字和字符串单元格,并抛出您看到的异常。

    从行中删除单元格值后,单元格值现在为空白,您将获得CELL_TYPE_BLANK 的单元格类型。

    你需要扩展cellToString()方法中的switch语句来处理Cell.CELL_TYPE_BLANK、Cell.CELL_TYPE_BOOLEAN等其他单元格类型。

    请参阅Cell 界面上的Apache POI documentation,了解不同的单元格类型是什么以及如何处理每种类型。

    public static String cellToString(HSSFCell cell) {  
        int type;
        Object result;
        type = cell.getCellType();
    
        switch (type) {
    
            case Cell.CELL_TYPE_NUMERIC: // numeric value in Excel
            case Cell.CELL_TYPE_FORMULA: // precomputed value based on formula
                result = cell.getNumericCellValue();
                break;
            case Cell.CELL_TYPE_STRING: // String Value in Excel 
                result = cell.getStringCellValue();
                break;
            case Cell.CELL_TYPE_BLANK:
                result = "";
            case Cell.CELL_TYPE_BOOLEAN: //boolean value 
                result: cell.getBooleanCellValue();
                break;
            case Cell.CELL_TYPE_ERROR:
            default:  
                throw new RuntimeException("There is no support for this type of cell");                        
        }
    
        return result.toString();
    }
    

    【讨论】:

    • 是的,我现在明白了,谢谢。我添加到 switch 语句以检查空白,但 for 循环返回空白,但是,我希望发生的是当我删除一行中的数据时,该行根本不返回。我想我不明白 POI 类是如何确定行数的。在我的示例中,我删除了第 3 行和第 4 行,但 ExcelRead 方法仍返回 4 行(2 行包含数据,2 行包含空白)。
    • 您所拥有的是带有空白单元格的空白行。如果您只是想摆脱它,请通过右键单击行左侧的行标题,然后从上下文菜单中单击删除来删除行。这将只留下包含数据的行。
    • 我明白了,但我想知道一个单元格中已删除的单元格数据与从未包含数据的单元格之间的区别是什么?
    • 我想知道 int rowNum = ws.getLastRowNum() + 1 ;知道有多少行数据?如果我删除单元格数据,它仍然认为该行中有数据。
    • 如果您将 Excel 工作表保存为 .csv 文件,您会看到它的末尾还有空行 - Excel 在内部维护这一点,这与您的代码或 Apache 库无关。
    【解决方案2】:

    使用 Java 从 Excel 读取数据,您需要以下 jars。从this link下载

    poi-4.1.0.jar 
    poi-ooxml-4.1.0.jar
    xmlbeans-3.1.0.jar 
    ooxml-schemas-1.4.jar 
    commons-compress-1.18.jar
    xlsx-streamer-2.1.0.jar
    

    要读取 Excel 文件,请将其放置在下载或用户所需的位置。下面的程序使用下面的Excel file。

    Excel 文件可能包含不同类型的 CellType。当您阅读列数据时,您需要提及 Apache POI 支持的大多数可用的 CellTypes。

    我参考以下案例BOOLEAN, STRING, NUMERIC, FORMULA, BLANK, _NONE, ERROR,,如果没有案例支持,则转到getCellValueAsString 方法中的default。

    package com.java.file.excel;
    
    import java.io.FileInputStream;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    
    import org.apache.poi.ss.usermodel.Cell;
    import org.apache.poi.ss.usermodel.Row;
    import org.apache.poi.ss.usermodel.Sheet;
    import org.apache.poi.ss.usermodel.Workbook;
    
    import com.monitorjbl.xlsx.StreamingReader;
    
    /**
     * 
     * @author udaykiran p
     *
     */
    public class ReadExcelFile {
    
        public static void main(String[] args) {
            try {
                FileInputStream inputStream = new FileInputStream("C:\\Users\\udaykiranp\\Downloads\\Users.xlsx");// Read Excel file from this location
                if (inputStream != null) {
                    Workbook wb = StreamingReader.builder().rowCacheSize(100) // number of rows to keep in memory (default to 10)
                            .bufferSize(4096) // buffer size is to use when reading InputStream to file (defaults to 1024)
                            .open(inputStream);
                    Sheet sheet = wb.getSheetAt(0);//reading first sheet. You can pass argument as well.
                    System.out.println("Excel Reading - Number Of Sheets: "+ wb.getNumberOfSheets() +", Active Sheet: "+ sheet.getSheetName());
                    Map<String, String> map = new HashMap<String, String>();
                    Iterator<Row> iterator = sheet.iterator();
                    int rowCount = 0;
                    while(iterator.hasNext()) {
                        Row row = iterator.next();
                        rowCount = row.getRowNum();
                        rowCount++;
                        int columnNum = 0;
                        String key = null, value = null;
                        for(Iterator<Cell> cellIterator = row.cellIterator(); cellIterator.hasNext();) {
                            Cell cell = cellIterator.next();
                            columnNum = cell.getColumnIndex();
                            String cellData = getCellValueAsString(cell);
                            System.out.println("RowNumber: "+ rowCount +", CellData: "+ cellData +", CellNumber: "+ columnNum);
                            //Reading data from Excel upto 6 rows only
    //                      if (rowCount == 6) {
                                //rowCount == 1 Headers Section(User ID, User Name)
                                if (rowCount > 1) {
                                    if (columnNum == 0) {
                                        key = cellData;//User ID
                                    }
                                    if (columnNum == 1) {
                                        value = cellData;//User Name
                                    }
                                }
    //                      }
                        }
                        if (key != null && value != null) {
                            map.put(key, value);
                        }
                    }
                    String userID = "1";
                    System.out.println("User ID: "+ userID +", User Name: "+ map.get("1"));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        private static String getCellValueAsString(Cell cell) {
            String cellValue = null;
            switch(cell.getCellType()) {
            case BOOLEAN:
                cellValue = String.valueOf(cell.getBooleanCellValue());
                break;
            case STRING:
                cellValue = String.valueOf(cell.getRichStringCellValue().toString());
                break;
            case NUMERIC:
                Double value = cell.getNumericCellValue();
                if (value != null) {
                    String valueAsStr = value.toString();
                    int indexOf = valueAsStr.indexOf(".");
                    if (indexOf > 0) {
                        cellValue = valueAsStr.substring(0, indexOf);//decimal numbers truncated
                    } else {
                        cellValue = value.toString();
                    }
                }
                break;
            case FORMULA:
                //if the cell contains formula, this case will be executed.
                cellValue = cell.getStringCellValue();
                break;
            case BLANK:
                cellValue = "";
                break;
            case _NONE:
                cellValue = "";
                break;
            case ERROR:
                throw new RuntimeException("There is no support for this type of cell");
            default:
                cellValue = "";
            }
            return cellValue;
        }
    }
    

    输出:

    DEBUG [main] (StreamingWorkbookReader.java:89) - Created temp file 
    
    [C:\Users\UDAY~1\AppData\Local\Temp\tmp-6803178981463652112.xlsx]
    Excel Reading - Number Of Sheets: 1, Active Sheet: Sheet1
    RowNumber: 1, CellData: User ID, CellNumber: 0
    RowNumber: 1, CellData: User Name, CellNumber: 1
    RowNumber: 2, CellData: 1, CellNumber: 0
    RowNumber: 2, CellData: Steve Jobs, CellNumber: 1
    RowNumber: 3, CellData: 2, CellNumber: 0
    RowNumber: 3, CellData: Bill Gates, CellNumber: 1
    RowNumber: 4, CellData: 3, CellNumber: 0
    RowNumber: 4, CellData: Sergey Brin, CellNumber: 1
    RowNumber: 5, CellData: 4, CellNumber: 0
    RowNumber: 5, CellData: Fritz Sennheiser, CellNumber: 1
    RowNumber: 6, CellData: 5, CellNumber: 0
    RowNumber: 6, CellData: Thomas Olsen, CellNumber: 1
    User ID: 1, User Name: Steve Jobs
    

    【讨论】:

      【解决方案3】:

      添加这个。

      case 3: break;
      

      实际上,您需要检查空单元类型 (HSSFCell.CELL_TYPE_BLANK)。

      如果你发现一个空单元格,你还可以做的是用i=rowNum 停止for 循环。

      有不止两种类型的 cell 。 getCellType() 方法可以返回这些整数:

      Cell.CELL_TYPE_NUMERIC, Cell.CELL_TYPE_STRING, Cell.CELL_TYPE_FORMULA, Cell.CELL_TYPE_BLANK, Cell.CELL_TYPE_BOOLEAN, Cell.CELL_TYPE_ERROR
      

      已编辑:

      根据 Faiz 的观察,这将得到一个异常,因为 Object result 未初始化和未分配。相反,写case 3: return ""; 它将在找到空白单元格时返回一个空字符串。无论如何,您的算法并不是最有效的。您应该搜索单元格,直到找到空单元格(如果工作表中没有空行),而不是搜索预定义的大区域。您应该可以使用 ArrayList 而不是 Array,从而完全避免在密码检查过程中处理空字符串。

      【讨论】:

      • return result.toString(); 将抛出一个错误,因为在这种情况下,result 没有被赋值。你应该给result赋值。
      • 我的输出现在是这样的: PASSED: LoginTest("a", "b", null, null) PASSED: LoginTest("c", "d", null, null) PASSED: LoginTest( null,null,null,null)通过:LoginTest(null,null,null,null)我的excel数据是:a b c d所以我期望在输出中看到的是:通过:LoginTest(“a”,“b” ) PASSED: LoginTest("c", "d") 我为 (int j = 0 ; j
      • >您应该搜索单元格,直到找到空单元格。我确实添加了一个 value == "" 检查,我认为它会停止行处理,但显然它没有。我对 Java 编程相当陌生。我想我不知道如何或理解如何在找到空白单元格时停止方法调用。
      • for (int j = 0 ; j
      • 要评估字符串值,您应该使用 equals() 方法而不是比较器 ==""。所以,写 if (value.equals(""){ break; } else{ data[i][j] = value ; } 代替,但这会在字符串数组(数据)的某些部分留下空值您需要在密码检查过程中捕获,最后,如果您在包含字符串的两行之间有一个空行(我不确定您的要求),这将不起作用。
      猜你喜欢
      • 1970-01-01
      • 2020-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-22
      相关资源
      最近更新 更多