Java Excel POI - 删除具有空单元格异常的行

时间:2016-05-18 09:02:39

标签: apache-poi

我正在使用java和Apache POI Library编写接口。我在删除空行时遇到问题。我的代码是:

public class ExcelDeleteRowsCols {
    final short ROW_START = 0;
    final short COL_START = 0;

    public void deleteRows() {
        try {
            // Open file
            FileInputStream inf = new FileInputStream("in.xls");
            Workbook wb = WorkbookFactory.create(inf);

            // Loop every sheets of workbook
            for (Sheet sheet : wb){

                // Loop every rows of this sheet
                int lastIndex = sheet.getLastRowNum();

                for (int i = ROW_START; i <= lastIndex; i++) {
                    if (sheet.getRow(i) == null || sheet.getRow(i).getCell(COL_START) == null || sheet.getRow(i).getCell(COL_START).toString().equals("")){ 
                        sheet.removeRow(sheet.getRow(i));   //sheet.shiftRows(i, lastIndex, 2);
                    }
                }
            }
            // Save as in another file
            FileOutputStream fileOut = new FileOutputStream("out.xls");
            wb.write(fileOut);
            fileOut.flush();
            fileOut.close();

            System.out.println("Finished!");

        } catch (IOException ioe) {
            System.out.println(ioe);
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

问题在于,在具有空单元格的行中显示异常消息java.lang.NullPointerException。我不明白。 Excel示例:

“空单元格” 2号线 3号线 4号线 5号线 “空单元” Line7 Line8 Line9 Line10 Line11 Line12 Line13

如果没有空单元格,代码工作正常......

请你能帮帮我吗?

提前致谢。

3 个答案:

答案 0 :(得分:2)

当然你不能使用

sheet.removeRow(row)

当你的行为空时

正如我在您的代码中看到的那样,您只想在&#34; in.xls&#34;中保留非空行。将文件写入&#34; out.xls&#34; ,所以我建议你这样改变算法:

Workbook wbOut = new HSSFWorkbook(); // or whatever workbook you'd like to use
for (Sheet sheet : wb){
            Sheet newSheet = wbOut.createSheet();
            int newI = 0;
            // Loop every rows of this sheet
            int lastIndex = sheet.getLastRowNum();

            for (int i = ROW_START; i <= lastIndex; i++) {
                // the exact opposite condition
                if (sheet.getRow(i) != null && 
                    sheet.getRow(i).getCell(COL_START) != null && 
                   !sheet.getRow(i).getCell(COL_START).toString().equals("")){ 
                     // row is not null so you can copy it to a new sheet
                    Row newRow = newSheet.createRow(newI++);
                    newRow = sheet.getRow(i);
                }
            }
        }
      // Save as in another file
        FileOutputStream fileOut = new FileOutputStream("out.xls");
        wbOut.write(fileOut);
        fileOut.flush();
        fileOut.close();

因此,您只将非空行复制到最终可以编写的新工作簿中。

答案 1 :(得分:0)

因此,您真的想要关闭电子表格中的空行,而不是删除行。也就是说,移动包含数据的行,以便中间没有空行。

我完全改变了这个答案,考虑到这一点。

FileInputStream inf = new FileInputStream("Row_Delete_Test.xlsx");

Workbook wb = WorkbookFactory.create(inf);

for (Sheet sh : wb) {
    int previousIndex = sh.getFirstRowNum();
    if (previousIndex > 0) {
        sh.shiftRows(px, sh.getLastRowNum(), -px);
        previousIndex = 0;
    }

    for (Row row : sh) {
        boolean deleteRow = true;
        for (Cell cell : row) {
            if (!cell.toString().trim().equals("")) {
                deleteRow = false;
                break;
            }
        }

        int currentIndex = row.getRowNum();
        if (deleteRow) {
            sh.removeRow(row);
        } else {
            if (currentIndex > previousIndex + 1) {
                sh.shiftRows(row.getRowNum(), sh.getLastRowNum(), previousIndex - currentIndex + 1);
                currentIndex = previousIndex + 1;
            }
            previousIndex = currentIndex;
        }
    }
}

FileOutputStream fileOut = new FileOutputStream("Row_Delete_Test.xlsx");
wb.write(fileOut);
wb.close();
fileOut.close();

这会产生&#34;删除&#34;电子表格中的行。

注意:Excel电子表格实际上只包含带有单元格的行,并且只包含带有数据的单元格。这些数据几乎可以是任何东西,包括空白,所以如果你也想要删除&#34;在唯一的单元格值为空的行中,则必须搜索该行。

以下是一些示例数据(请注意,这是来自sheet1.xml文件中的Row_Delete_Test.xlsx

<sheetData>
    <row r="2" spans="2:3" x14ac:dyDescent="0.25">
        <c r="B2" t="s">
            <v>0</v>
        </c>
    </row>
    <row r="5" spans="2:3" x14ac:dyDescent="0.25">
        <c r="B5" t="s">
            <v>1</v>
        </c>
    </row>
    <row r="6" spans="2:3" x14ac:dyDescent="0.25">
        <c r="C6" t="s">
            <v>4</v>
        </c>
    </row>
    <row r="7" spans="2:3" x14ac:dyDescent="0.25">
        <c r="B7" t="s">
            <v>2</v>
        </c>
    </row>
    <row r="8" spans="2:3" x14ac:dyDescent="0.25">
        <c r="B8" t="s">
            <v>3</v>
        </c>
    </row>
    <row r="9" spans="2:3" x14ac:dyDescent="0.25">
        <c r="C9" t="s">
            <v>4</v>
        </c>
    </row>
</sheetData>

我将告诉你,因为除了查看共享字符串表之外你无法知道,<v>4</v>指定的共享字符串4只是一个空白值。其他共享字符串值为<v>0</v> =&#39;第1行&#39;,<v>1</v> =&#39;第2行&#39;,<v>2</v> =&#39;第3行& #39;和<v>3</v> =&#39;第4行和第39行。因此,这里填充了行2和5到9,每行都有一个单元格,其中包含数据。第6行和第9行各自在C列中有一个空白值的单元格。

运行上面的代码后,sheetData看起来像这样

<sheetData>
    <row r="1" spans="2:3" x14ac:dyDescent="0.25">
        <c r="B1" t="s">
            <v>0</v>
        </c>
    </row>
    <row r="2" spans="2:3" x14ac:dyDescent="0.25">
        <c r="B2" t="s">
            <v>1</v>
        </c>
    </row>
    <row r="3" spans="2:3" x14ac:dyDescent="0.25">
        <c r="B3" t="s">
            <v>2</v>
        </c>
    </row>
    <row r="4" spans="2:3" x14ac:dyDescent="0.25">
        <c r="B4" t="s">
            <v>3</v>
        </c>
    </row>
</sheetData>

现在只有1-4行在电子表格中。第2行已移至第1行,第5行,第2行,第7行至第3行以及第8行至第4行。

答案 2 :(得分:0)

我有这个xls文件:

enter image description here

我的目标是删除每一个空行,对于这个问题,我认为最好的选择是Java中的OPI。代码是:

public class ExcelDeleteRowsCols {
    final short ROW_START = 0;
    final short COL_START = 0;

    public void deleteRows() {
        try {
            // Open file
            FileInputStream inf = new FileInputStream("in.xls");
            Workbook wb = WorkbookFactory.create(inf);

            // Loop every sheets of workbook
            for (Sheet sheet : wb){

                // Loop every rows of this sheet
                int lastIndex = sheet.getLastRowNum();

                for (int i = ROW_START; i <= lastIndex; i++) {
                    if (sheet.getRow(i) == null || sheet.getRow(i).getCell(COL_START) == null || sheet.getRow(i).getCell(COL_START).toString().equals("")){ 
                        sheet.removeRow(sheet.getRow(i));   
                    }
                }
            }
            // Save as in another file
            FileOutputStream fileOut = new FileOutputStream("out.xls");
            wb.write(fileOut);
            fileOut.flush();
            fileOut.close();

            System.out.println("Finished!");

        } catch (IOException ioe) {
            System.out.println(ioe);
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

当行为空时,代码工作正常,但问题是当行为空时( sheet.getRow(i)== null )。例如,在xls第2行,第12行,第15行和第16行中,您的值为null,然后它不会被删除,因为命令 sheet.removeRow(sheet.getRow(i)); 通过NullPointer抛出和异常

有没有办法删除值为null的行?