1 回答
TA贡献1841条经验 获得超3个赞
如果一行在 List 中被双重包含,则会发生错误toRemove。AList允许重复条目。所以同一行可能会被双重添加到List. 如果然后Iterator得到该行的第一次出现,这将从工作表中正确删除。但是,如果稍后再次出现同一行,则row.getRowNum()失败,因为该行不再存在于工作表中。
这是重现该行为的完整代码:
import org.apache.poi.ss.usermodel.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.*;
public class ExcelRemoveRows {
public static void main(String[] args) throws Exception {
String filePath = "Excel.xlsx"; // must contain at least 5 filled rows
Workbook workbook = WorkbookFactory.create(new FileInputStream(filePath));
Sheet sheet = workbook.getSheetAt(0);
List<Row> toRemoveList = new ArrayList<Row>();
toRemoveList.add(sheet.getRow(0));
toRemoveList.add(sheet.getRow(2));
toRemoveList.add(sheet.getRow(4));
toRemoveList.add(sheet.getRow(2)); // this produces the error
System.out.println(toRemoveList); // contains row hawing index 2 (r="3") two times
for (Row row : toRemoveList) {
System.out.println(row.getRowNum()); // XmlValueDisconnectedException on second occurance of row index 2
sheet.removeRow(row);
}
FileOutputStream out = new FileOutputStream("Changed"+filePath);
workbook.write(out);
out.close();
workbook.close();
}
}
解决方案是避免List多次包含同一行。
我不会收集要在 a 中删除的行List<XSSFRow>,而是收集要在 a 中删除的行号Set<Integer>。这将避免重复,因为 aSet不允许重复的元素。然后要删除的行可以简单地通过sheet.getRow(rowNum).
代码:
...
Set<Integer> toRemoveSet = new HashSet<Integer>();
toRemoveSet.add(sheet.getRow(0).getRowNum());
toRemoveSet.add(sheet.getRow(2).getRowNum());
toRemoveSet.add(sheet.getRow(4).getRowNum());
toRemoveSet.add(sheet.getRow(2).getRowNum());
System.out.println(toRemoveSet); // does not contain the row index 2 two times
for (Integer rowNum : toRemoveSet) {
Row row = sheet.getRow(rowNum);
System.out.println(row.getRowNum());
sheet.removeRow(row);
}
...
添加回答
举报