首页 文章

查找Excel电子表格中的最后一行

提问于
浏览
13

我正在尝试使用Apache的POI for Java查找Excel电子表格中最后一行的索引 .

我认为这应该可以使用 getLastRowNum()getPhysicalNumberOfRows() ,但它们似乎没有给出正确的结果 . 例如,我有一行电子表格,这两个函数返回值1140.另外两行电子表格的值为1162 .

另一个问题是我不能只查找第一个空行,因为有效数据行之间可能有空行 .

那么有没有办法找到最后一行的索引?我想我可以要求在数据之间没有空行,但我希望有更好的解决方案 .

编辑:对于使用迭代器的记录没有帮助 . 它只是迭代了1140/1162所谓的行 .

8 回答

  • 1

    我使用poi-3.6-20091214获得了预期的输出,并且 test.xls 有两个空行,后面跟着三个占用的行:

    InputStream myxls = new FileInputStream("test.xls");
    Workbook book = new HSSFWorkbook(myxls);
    Sheet sheet = book.getSheetAt(0);
    System.out.println(sheet.getLastRowNum());
    

    输出: 4

  • 10

    您可以使用以下方法获取原始行计数 .

    HSSFSheet worksheet = workbook.getSheet("Role_Mapping");
    int rowsNum = worksheet.getPhysicalNumberOfRows();
    
  • 1

    我知道如何使用VBA解决您的问题,但我不确定如何从Apache POI接口获取等效信息 . 在VBA中,要获取工作表“Sheet1”中已使用单元格的范围,请使用:

    Worksheets("Sheet1").UsedRange
    

    这将返回 Range 对象,该对象具有提供更多信息的属性 . 例如,要获取此 Range 中的行数,请使用:

    Worksheets("Sheet1").UsedRange.Rows
    

    同样,我不确定这是否可以通过POI API访问,但如果没有,也许它提供了一种执行VBA任意片段的方法?

  • -2

    确切知道的唯一方法是测试行 . 这是我用于同一问题的解决方案:

    int lastRowIndex = -1;
    if( sheet.getPhysicalNumberOfRows() > 0 )
    {
        // getLastRowNum() actually returns an index, not a row number
        lastRowIndex = sheet.getLastRowNum();
    
        // now, start at end of spreadsheet and work our way backwards until we find a row having data
        for( ; lastRowIndex >= 0; lastRowIndex-- ){
            Row row = sheet.getRow( lastRowIndex );
            if( row != null ){
                break;
            }
        }
    }
    

    注意:这不会检查看似空但不是的行,例如其中包含空字符串的单元格 . 为此,您需要一个更完整的解决方案,例如:

    private int determineRowCount()
    {
        this.evaluator = workbook.getCreationHelper().createFormulaEvaluator();
        this.formatter = new DataFormatter( true );
    
        int lastRowIndex = -1;
        if( sheet.getPhysicalNumberOfRows() > 0 )
        {
            // getLastRowNum() actually returns an index, not a row number
            lastRowIndex = sheet.getLastRowNum();
    
            // now, start at end of spreadsheet and work our way backwards until we find a row having data
            for( ; lastRowIndex >= 0; lastRowIndex-- )
            {
                Row row = sheet.getRow( lastRowIndex );
                if( !isRowEmpty( row ) )
                {
                    break;
                }
            }
        }
        return lastRowIndex;
    }
    
    /**
     * Determine whether a row is effectively completely empty - i.e. all cells either contain an empty string or nothing.
     */
    private boolean isRowEmpty( Row row )
    {
        if( row == null ){
            return true;
        }
    
        int cellCount = row.getLastCellNum() + 1;
        for( int i = 0; i < cellCount; i++ ){
            String cellValue = getCellValue( row, i );
            if( cellValue != null && cellValue.length() > 0 ){
                return false;
            }
        }
        return true;
    }
    
    /**
     * Get the effective value of a cell, formatted according to the formatting of the cell.
     * If the cell contains a formula, it is evaluated first, then the result is formatted.
     * 
     * @param row the row
     * @param columnIndex the cell's column index
     * @return the cell's value
     */
    private String getCellValue( Row row, int columnIndex )
    {
        String cellValue;
        Cell cell = row.getCell( columnIndex );
        if( cell == null ){
            // no data in this cell
            cellValue = null;
        }
        else{
            if( cell.getCellType() != Cell.CELL_TYPE_FORMULA ){
                // cell has a value, so format it into a string
                cellValue = this.formatter.formatCellValue( cell );
            }
            else {
                // cell has a formula, so evaluate it
                cellValue = this.formatter.formatCellValue( cell, this.evaluator );
            }
        }
        return cellValue;
    }
    
  • 1

    我之前遇到过同样的问题 . 它可能是由已编辑然后在Excel中清空的Excel单元格引起的 . 一旦它们被触摸,它们就会被用作细胞 .

    我使用这个技巧来删除(不仅仅是空)这些单元格,并获得正确的返回行值:

    • 打开Excel文件并转到预期的工作表 .

    • 选择最后一行1.例如,您有12行数据,然后单击第13行 .

    • 选择整行[Shift] - [空格]

    • 选择工作表底部的所有行[Ctrl] - [Shift] - [向下箭头]

    • 删除所有选定的行[Ctrl] - [减号]

    • 保存工作簿

    • 重新运行代码并检查返回值 .

    这不是POI库的问题 .

  • 0

    您可以通过以下代码执行此操作:

    SVTableModel model = new SVTableModel(sheet);
    lastRowNum = model.getRowCount();
    

    但是,我试图在Apache POI 3.7中执行此操作,但在API中找不到 SVTableModel . 我想,自3.2以来已经删除了 .

  • 0

    对我来说,无论如何都没有用,因为它适用于HSSFWorkbook但不适用于XSSFWorkbook . 最后,在解决方法的帮助下,我能够解决这个问题 . 通过在工作表末尾合并两列或多行(在内容完成后) . 然后写下面的代码 . sheet.getMergedRegion(0).getLastRow() 这里0只是我合并的一种情况,但是如果你已经合并了单元格或行,那么相应地增加你的值 . 希望这会有所帮助 .

  • 5
    int total = sheet.getPhysicalNumberOfRows() - sheet.getLastRowNum();
    

相关问题