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

时间:2010-04-15 13:18:40

标签: java excel apache-poi

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

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

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

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

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

9 个答案:

答案 0 :(得分:10)

我使用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

答案 1 :(得分:5)

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

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

答案 2 :(得分:1)

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

Worksheets("Sheet1").UsedRange

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

Worksheets("Sheet1").UsedRange.Rows

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

答案 3 :(得分:1)

唯一可以确定的方法是测试行。这是我用于同一问题的解决方案:

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

答案 4 :(得分:1)

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

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

  1. 打开Excel文件并转到预期的工作表。
  2. 选择最后一行+ 1.例如,您有12行数据,然后点击第13行。
  3. 选择整行[Shift] - [Space]
  4. 选择工作表底部的所有行[Ctrl] - [Shift] - [向下箭头]
  5. 删除所有选定的行[Ctrl] - [减号]
  6. 保存工作簿
  7. 重新运行代码并检查返回的值。
  8. 这不是POI库的问题。

答案 5 :(得分:0)

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

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

但是,我尝试在Apache POI 3.7中执行此操作,但在API中找不到SVTableModel。自从3.2以来,这已经被删除了。

答案 6 :(得分:0)

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

答案 7 :(得分:0)

使用迭代器不会返回null和未使用的行

           Iterator<Row> itr = sheet.iterator();    //iterating over excel file  
            

            while (itr.hasNext())                 
            {  
                Row row = itr.next();
                //your code here 
            }

答案 8 :(得分:-2)

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