删除特定行apache poi

pgvzfuti  于 2021-07-12  发布在  Java
关注(0)|答案(1)|浏览(437)

我需要删除包含用户输入的单词的行。这是我的密码:

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();
        }
    }
}

但问题是它会一致地删除行,而不是包含用户单词的行。即使它工作,它也有例外:concurrentmodificationexception

ltskdhd1

ltskdhd11#

这个 ConcurrentModificationException 是因为 Sheet.removeRow 尝试更改行,而 Iterator 迭代该工作表的行。这是不可能的。
所以不用 Iterator 你需要换一种方式来排。例如使用 for 循环使用 int r 以及 sheet.getRow(r) 去弄一排。
但是 Sheet.removeRow 名字有误导性。它实际上并不删除行,而是只从图纸的存储中删除行,而不向上移动下面的行。所以事实上它只会完全清空这一行。如果确实要删除行,则需要使用 Sheet.shiftRows . Sheet.shiftRows 在以前的版本中有很多bug apache poi . 所以它只能用电流正常工作 apache poi 5.0.0 .
但是使用 Sheet.shiftRows 每次移动都会影响行号。所以 for 循环使用 int r 以及 sheet.getRow(r) 要获取行,需要从下到上循环,否则它将尝试获取已经删除的行号。
下面的代码应该使用current 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);

  }

 }
}

相关问题