首页 > 解决方案 > sheet.getRow(rowIndex) 返回 NULL - APACHE POI

问题描述

我正在使用 APACHE POI 库来读取 xlsx 格式的 excel 文件。

我的问题是我想从这个excel的每张表中删除最后一行,我找到了一种方法来找到要删除的最后一行,但它返回一个int。方法 sheet.removeRow(Row var1); 会解决我的问题。

好吧,拥有我要删除的行号和删除该行的方法。我只需要将 lastRow (int) 转换为 Row 类型,这样我就可以使用 sheet.removeRow 方法。

为此,我使用了以下代码: Row a = sheet.getRow(lastRow) 此方法应返回具有该索引的 Row。但相反,它返回 NULL。

知道我做错了什么或如何将要删除的行号转换为 Row 类型吗?

感谢你的帮助!

这是读取我的excel文件的代码摘录

    public static List<Measure> excelToMeasures(InputStream is, ProjectMeasureFile projectMeasureFile) throws IOException {

    List<Measure> measures = new ArrayList<>();

    try (Workbook workbook = new XSSFWorkbook(is)) {

        for (int i = 0; i < 3; i++) {
            Sheet sheet = workbook.getSheetAt(i);

            int lastRow = sheet.getPhysicalNumberOfRows() -1;

            removeRow(sheet, lastRow);

            int rowNumber = 0;
            for (Row row : sheet) {

                // skip header
                if (rowNumber == 0) {
                    rowNumber++;
                    continue;
                }

                Iterator<Cell> cellIterator = row.iterator();
                List<Cell> cellObject = new ArrayList<>();

                while (cellIterator.hasNext()) {
                    cellObject.add(cellIterator.next());
                }

                if (cellObject.size() > 0) {
                    Measure measure = new Measure();
                    measure.setArea(sheet.getSheetName());
                    measure.setCode(convertStringCell(cellObject.get(0)));
                    measure.setBehavior(convertStringCell(cellObject.get(1)));

                    measure.setHumanDependencyFactor(convertNumericCell(cellObject.get(2)));
                    Double measureType = convertToPercentage(measure.getHumanDependencyFactor());
                    measure.setHumanDependencyFactor(measureType);

                    measure.setMeasurementResults(convertNumericCell(cellObject.get(3)));
                    Double value = convertToPercentage(measure.getMeasurementResults());
                    measure.setMeasurementResults(value);

                    measure.setProjectMeasureFile(projectMeasureFile);
                    measures.add(measure);
                }

                rowNumber++;
            }
        }

    } catch (Exception e) {
        log.error("An error occurred when trying to parse the file.");
        e.printStackTrace();
    }

    return measures;
}

这是删除行的方法:

  public static void removeRow(Sheet sheet, int rowIndex) {
    int lastRowNum = sheet.getPhysicalNumberOfRows() -1;

    if (rowIndex == lastRowNum) {
        Row removingRow = sheet.getRow(rowIndex);
        sheet.getRow(rowIndex);
        Row a = sheet.getRow(rowIndex);
        if (removingRow != null) {

           
            System.out.println(sheet.getRow(lastRowNum).getCell(0).toString());
           
            sheet.removeRow(removingRow); 
        }
    }
}

标签: javaexcelapache-poi

解决方案


首先是您问题的标题:Sheet.getRow将按NULL设计返回。NULL如果行索引后面的行未存储在工作表中,则返回。所以你总是需要检查NULLafter Sheet.getRow。对于未存储在行中的单元格的设计Row.getCell返回也是如此。NULL

并且Sheet.getPhysicalNumberOfRows不是获取工作表最后一行的正确方法。

工作表仅在Excel物理上包含具有存储在其中的单元格的行。完全为空的行没有物理存储。因此,如果工作表仅包含第 1、2、5、6 和 7 行中的数据,Sheet.getPhysicalNumberOfRows则将返回 5,但最后一行为 7。

Sheet.getLastRowNum获取工作表中的最后一个行号(从 0 开始)。所以这将在上面的示例中返回 6 并sheet.getRow(6)得到最后一行而不是NULL

但是还有另一个问题需要考虑。行中Excel可能不完全为空,但仅包含空白的单元格。空白单元格可能会被存储,因为它们具有单元格格式或之前有内容。Sheet.getLastRowNum获取最后存储的行,即使该行仅包含空白单元格。Sheet.getLastRowNum因此,您需要通过遍历单元格来检查后面的行是否仅包含空白单元格,并检查CellType.BLANK是否需要最后填充的行。

以下方法获取工作表中最后填充的行。NULL如果没有找到填充的行,则返回。

 Row getLastFilledRow(Sheet sheet) {
  int lastStoredRowNum = sheet.getLastRowNum();
  for (int r = lastStoredRowNum; r >= 0; r--) {
   Row row = sheet.getRow(r);
   if (row != null) {
    for (Cell cell : row) {
     if (cell.getCellType() != CellType.BLANK) return row;  
    }
   }       
  }
  return null;  
 }

推荐阅读