简体   繁体   English

删除特定行 Apache Poi

[英]Remove Specific row Apache Poi

I need to remove row that contains word that user inputs.我需要删除包含用户输入的单词的行。 Here my code:这是我的代码:

        try {
            System.out.println("Write material that need to be removed: ");
            Scanner in = new Scanner(System.in);
            String toFind = in.nextLine();
            FileInputStream file = new FileInputStream(new File("solty.xls"));

            //Create Workbook instance holding reference to .xlsx file
            HSSFWorkbook workbook = new HSSFWorkbook(file);
            DataFormatter formatter = new DataFormatter();
            HSSFSheet sheet = workbook.getSheetAt(0);

            for (Row row : sheet) {
                for (Cell cell : row) {
                    Iterator<Row> rowIterator = sheet.iterator();

                    while (rowIterator.hasNext()) {
                        Row row3 = rowIterator.next();
                        CellReference cellRef = new CellReference(row3.getRowNum(), cell.getColumnIndex());
                        
                        String text = formatter.formatCellValue(cell);

                        // is it an exact match?
                        if (toFind.equals(text)) {
                            System.out.println("Text finded at " + cellRef.formatAsString());
                            System.out.println(cellRef.getRow());
                            int rowIndex = cellRef.getRow();
                            System.out.println(row.getCell(rowIndex));
                            HSSFRow row1 = sheet.getRow(rowIndex);
                            sheet.removeRow(row1);
                            file.close();
                            FileOutputStream outFile = new FileOutputStream(new File("solty.xls"));
                            workbook.write(outFile);
                            outFile.flush();
                            outFile.close();

                        }
                        // is it a partial match?
                        else if (text.contains(toFind)) {
                            System.out.println("Index is  " + cellRef.formatAsString());


                        }


                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

but the problem is that it deletes row consistently, not the row that contains user's word.但问题是它始终删除行,而不是包含用户单词的行。 Also even it works it has Exception: ConcurrentModificationException即使它有效,它也有异常:ConcurrentModificationException

The ConcurrentModificationException is thrown because Sheet.removeRow tries to change a row while a Iterator iterates over the rows of that sheet.抛出ConcurrentModificationException是因为Sheet.removeRow尝试更改行,而Iterator迭代该工作表的行。 This is not possible.这是不可能的。

So instead of using Iterator you need to get the rows another way.因此,您需要以另一种方式获取行,而不是使用Iterator For example use for loop using int r and sheet.getRow(r) to get the rows.例如,使用for循环使用int rsheet.getRow(r)来获取行。

But Sheet.removeRow has a misleading name.但是Sheet.removeRow有一个误导性的名称。 It does not really removing a row but only removes the row from the sheet's storage without shifting the rows below upwards.它并没有真正删除一行,而只是从工作表的存储中删除了该行,而不将下面的行向上移动。 So in fact it only totally empties the row.所以实际上它只是完全清空了行。 If you really wants removing the row, you need using Sheet.shiftRows .如果您真的想删除该行,则需要使用Sheet.shiftRows Sheet.shiftRows had many bugs in former versions of apache poi . Sheet.shiftRowsapache poi的旧版本中存在许多错误。 So it only will work properly using current apache poi 5.0.0 .所以它只能使用当前的apache poi 5.0.0才能正常工作。

But using Sheet.shiftRows each shifting will influence the row numbers.但是使用Sheet.shiftRows每次移动都会影响行号。 So the for loop using int r and sheet.getRow(r) to get the rows needs to loop backwards from bottom to top, else it will try to get row numbers which were removed already.因此,使用int rsheet.getRow(r)获取行的for循环需要从下到上向后循环,否则它将尝试获取已经删除的行号。

The following code should work using current apache poi 5.0.0 and removing all rows containing cells having String toFind as content.以下代码应使用当前的apache poi 5.0.0并删除所有包含以String toFind作为内容的单元格的行。

import java.io.FileOutputStream;
import java.io.FileInputStream;

import org.apache.poi.ss.usermodel.*;

class RemoveSpecificRows {

 public static void main(String[] args) throws Exception {
     
  System.out.println("Write material that need to be removed: ");
  java.util.Scanner in = new java.util.Scanner(System.in);
  String toFind = in.nextLine();

  try (Workbook workbook = WorkbookFactory.create(new FileInputStream("ExcelSource.xls")); 
       FileOutputStream fileout = new FileOutputStream("ExcelResult.xls") ) {

   DataFormatter formatter = new DataFormatter();
   
   Sheet sheet = workbook.getSheetAt(0);
   
   for (int r = sheet.getLastRowNum(); r >=0;  r--) {
    Row row = sheet.getRow(r);
    if (row != null) {
     for (int c = 0; c < row.getLastCellNum(); c++) {
      Cell cell = row.getCell(c);
      String value = formatter.formatCellValue(cell);
      if (toFind.equals(value)) {
       System.out.println("Text " + toFind + " found at " + cell.getAddress()); 
       //sheet.removeRow(row); //this only empties the row
       sheet.shiftRows(r + 1, sheet.getLastRowNum() + 2, -1); //shift row below up to last row once up
       break;
      }
     }
    }      
   }

   workbook.write(fileout);

  }

 }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM