关于Java:使用Apache POI HSSF从Excel工作表中删除一行

Removing a row from an Excel sheet with Apache POI HSSF

我正在使用Apache POi HSSF库将信息导入到我的应用程序中。 问题在于文件具有一些多余的/空的行,需要在分析之前先将其删除。

没有HSSFSheet.removeRow( int rowNum )方法。 仅removeRow( HSSFRow row )。 问题在于无法删除空行。 例如:

1
sheet.removeRow( sheet.getRow(rowNum) );

在空行上给出NullPointerException,因为getRow()返回null。
另外,正如我在论坛上阅读的那样,removeRow()仅会擦除单元格内容,但该行仍然作为空行存在。

有没有一种方法可以删除行(为空或不为空),而无需创建没有要删除的行的全新表?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 /**
 * Remove a row by its index
 * @param sheet a Excel sheet
 * @param rowIndex a 0 based index of removing row
 */

public static void removeRow(HSSFSheet sheet, int rowIndex) {
    int lastRowNum=sheet.getLastRowNum();
    if(rowIndex>=0&&rowIndex<lastRowNum){
        sheet.shiftRows(rowIndex+1,lastRowNum, -1);
    }
    if(rowIndex==lastRowNum){
        HSSFRow removingRow=sheet.getRow(rowIndex);
        if(removingRow!=null){
            sheet.removeRow(removingRow);
        }
    }
}


我知道,这是一个已有3年历史的问题,但是最近我不得不解决相同的问题,而且我必须使用C#来解决。这是我与NPOI,.Net 4.0一起使用的功能

1
2
3
4
5
6
7
8
9
10
11
12
13
    public static void DeleteRow(this ISheet sheet, IRow row)
    {
        sheet.RemoveRow(row);   // this only deletes all the cell values

        int rowIndex = row.RowNum;

        int lastRowNum = sheet.LastRowNum;

        if (rowIndex >= 0 && rowIndex < lastRowNum)
        {
            sheet.ShiftRows(rowIndex + 1, lastRowNum, -1);
        }
    }


遵循以下原则

1
2
3
4
5
int newrownum=0;
for (int i=0; i<=sheet.getLastRowNum(); i++) {
  HSSFRow row=sheet.getRow(i);
  if (row) row.setRowNum(newrownum++);
}

应该可以。


HSSFRow具有称为setRowNum(int rowIndex)的方法。

当您必须"删除"一行时,可以将该索引放在List中。然后,当您到达非空的下一行时,从该列表中获取一个索引并将其设置为调用setRowNum(),然后从该列表中删除该索引。 (或者您可以使用队列)


此答案是对AndreAY答案的扩展,它为您提供了删除行的完整功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public boolean deleteRow(String sheetName, String excelPath, int rowNo) throws IOException {

    XSSFWorkbook workbook = null;
    XSSFSheet sheet = null;

    try {
        FileInputStream file = new FileInputStream(new File(excelPath));
        workbook = new XSSFWorkbook(file);
        sheet = workbook.getSheet(sheetName);
        if (sheet == null) {
            return false;
        }
        int lastRowNum = sheet.getLastRowNum();
        if (rowNo >= 0 && rowNo < lastRowNum) {
            sheet.shiftRows(rowNo + 1, lastRowNum, -1);
        }
        if (rowNo == lastRowNum) {
            XSSFRow removingRow=sheet.getRow(rowNo);
            if(removingRow != null) {
                sheet.removeRow(removingRow);
            }
        }
        file.close();
        FileOutputStream outFile = new FileOutputStream(new File(excelPath));
        workbook.write(outFile);
        outFile.close();


    } catch(Exception e) {
        throw e;
    } finally {
        if(workbook != null)
            workbook.close();
    }
    return false;
}


我的特殊情况(对我有用):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    //Various times to delete all the rows without units
    for (int j=0;j<7;j++) {
      //Follow all the rows to delete lines without units (and look for the TOTAL row)
      for (int i=1;i<sheet.getLastRowNum();i++) {
        //Starting on the 2nd row, ignoring first one
        row = sheet.getRow(i);
        cell = row.getCell(garMACode);
        if (cell != null)
        {
          //Ignore empty rows (they have a"." on first column)
          if (cell.getStringCellValue().compareTo(".") != 0) {  
            if (cell.getStringCellValue().compareTo("TOTAL") == 0) {
              cell = row.getCell(garMAUnits+1);
              cell.setCellType(HSSFCell.CELL_TYPE_FORMULA);
              cell.setCellFormula("SUM(BB1" +":BB" + (i - 1) +")");
            } else {
              cell = row.getCell(garMAUnits);
              if (cell != null) {
                int valor = (int)(cell.getNumericCellValue());
                if (valor == 0 ) {
                  //sheet.removeRow(row);
                  removeRow(sheet,i);
                }
              }
            }
          }
        }
      }
    }


从一两年前开始,我试图深入我的大脑以获得与POI相关的经验,但是我的第一个问题是:为什么在解析之前需要删除这些行?为什么不直接从sheet.getRow(rowNum)调用中获取空结果并继续前进呢?