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
The ConcurrentModificationException
is thrown because Sheet.removeRow
tries to change a row while a Iterator
iterates over the rows of that sheet. This is not possible.
So instead of using Iterator
you need to get the rows another way. For example use for
loop using int r
and sheet.getRow(r)
to get the rows.
But Sheet.removeRow
has a misleading name. 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
had many bugs in former versions of apache poi
. So it only will work properly using current apache poi 5.0.0
.
But using Sheet.shiftRows
each shifting will influence the row numbers. 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.
The following code should work using current apache poi 5.0.0
and removing all rows containing cells having String toFind
as content.
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);
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.