Поиск последней строки в таблице Excel - PullRequest
13 голосов
/ 15 апреля 2010

Я пытаюсь найти индекс последней строки в таблице Excel, используя Apache POI для Java.

Я думал, что это возможно с getLastRowNum() или getPhysicalNumberOfRows(), но они не дают правильных результатов. Например, у меня есть однострочная электронная таблица, и эти две функции возвращают значение 1140. Еще две двухстрочные электронные таблицы получают значение 1162.

Другая проблема заключается в том, что я не могу просто найти первую пустую строку, поскольку возможно наличие пустых строк между строками действительных данных.

Так есть ли способ найти индекс последней строки? Я полагаю, что мог бы сделать это требование не иметь пустых строк между данными, но я надеялся на лучшее решение.

Редактировать: Для записи использование итератора не помогло. Он просто перебрал предполагаемые строки 1140/1162.

Ответы [ 8 ]

10 голосов
/ 15 апреля 2010

Я получаю ожидаемый результат, используя 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

5 голосов
/ 11 июня 2013

Вы можете использовать следующий метод для получения исходного числа строк.

HSSFSheet worksheet = workbook.getSheet("Role_Mapping");
int rowsNum = worksheet.getPhysicalNumberOfRows();
1 голос
/ 11 октября 2017

У меня была такая же проблема раньше. Это может быть вызвано ячейками Excel, которые были отредактированы, а затем очищены в Excel. После того, как к ним прикоснулись, они отображаются как использованные клетки.

Я использую этот трюк, чтобы удалить (а не просто очистить) эти ячейки и получить правильное значение возвращаемой строки:

  1. Откройте файл Excel и перейдите на ожидаемый лист.
  2. Выберите последнюю строку + 1. Например, у вас есть 12 строк с данными, затем щелкните строку 13.
  3. Выберите всю строку [Shift] - [Пробел]
  4. Выберите все строки в нижней части листа [Ctrl] - [Shift] - [Стрелка вниз]
  5. Удалить все выделенные строки [Ctrl] - [Минус]
  6. Сохраните свою книгу
  7. Повторите код и проверьте возвращаемое значение.

Это не проблема библиотеки POI.

1 голос
/ 30 мая 2015

Единственный способ узнать наверняка - это проверить строки. Вот решение, которое я использую для той же проблемы:

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 голос
/ 15 апреля 2010

Я знаю, как решить вашу проблему с помощью VBA, но я не уверен, как получить эквивалентную информацию из интерфейса Apache POI. В VBA, чтобы получить диапазон используемых ячеек на листе «Лист1», используйте:

Worksheets("Sheet1").UsedRange

Возвращает объект Range, свойства которого предоставляют дополнительную информацию. Например, чтобы получить количество строк в этом Range, используйте:

Worksheets("Sheet1").UsedRange.Rows

Опять же, я не уверен, доступно ли это через API POI, но если нет, возможно, он предоставляет способ выполнения произвольных фрагментов VBA?

0 голосов
/ 27 февраля 2019

Для меня ничего не работало в любом случае, так как это работает для HSSFWorkbook, но не для XSSFWorkbook. Наконец, с помощью обходного пути я смог решить эту проблему. Путем слияния двух столбцов или строк (после завершения содержимого) в конце листа. Затем напишите ниже код. sheet.getMergedRegion(0).getLastRow() Здесь 0 - это только один случай, когда я слился, но если вы уже слили ячейки или строки, то соответственно увеличьте свое значение. Надеюсь, это поможет.

0 голосов
/ 15 июня 2015
int total = sheet.getPhysicalNumberOfRows() - sheet.getLastRowNum();
0 голосов
/ 20 октября 2011

Вы можете сделать это с помощью следующего кода:

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

Однако я пытаюсь сделать это в Apache POI 3.7, но не могу найти SVTableModel в API. Это было удалено с 3.2, я думаю.

...