删除特定行 Apache Poi
Remove Specific row Apache Poi
我需要删除包含用户输入的单词的行。这是我的代码:
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
ConcurrentModificationException
被抛出是因为 Sheet.removeRow
试图更改一行,而 Iterator
遍历 sheet 的行。这是不可能的。
因此,您需要以其他方式获取行,而不是使用 Iterator
。例如,使用 for
循环使用 int r
和 sheet.getRow(r)
来获取行。
但是 Sheet.removeRow
有一个误导性的名字。它并没有真正删除一行,而只是从 sheet 的存储中删除该行,而不向上移动下面的行。所以实际上它只会完全清空该行。如果你真的想删除该行,你需要使用 Sheet.shiftRows
。 Sheet.shiftRows
在 apache poi
的旧版本中有很多错误。所以它只能使用当前 apache poi 5.0.0
.
正常工作
但是使用Sheet.shiftRows
每次移动都会影响行号。所以 for
循环使用 int r
和 sheet.getRow(r)
来获取行需要从下到上向后循环,否则它将尝试获取已经删除的行号。
以下代码应该使用当前 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);
}
}
}
我需要删除包含用户输入的单词的行。这是我的代码:
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
ConcurrentModificationException
被抛出是因为 Sheet.removeRow
试图更改一行,而 Iterator
遍历 sheet 的行。这是不可能的。
因此,您需要以其他方式获取行,而不是使用 Iterator
。例如,使用 for
循环使用 int r
和 sheet.getRow(r)
来获取行。
但是 Sheet.removeRow
有一个误导性的名字。它并没有真正删除一行,而只是从 sheet 的存储中删除该行,而不向上移动下面的行。所以实际上它只会完全清空该行。如果你真的想删除该行,你需要使用 Sheet.shiftRows
。 Sheet.shiftRows
在 apache poi
的旧版本中有很多错误。所以它只能使用当前 apache poi 5.0.0
.
但是使用Sheet.shiftRows
每次移动都会影响行号。所以 for
循环使用 int r
和 sheet.getRow(r)
来获取行需要从下到上向后循环,否则它将尝试获取已经删除的行号。
以下代码应该使用当前 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);
}
}
}