如何使用 apache poi 删除行

问题描述 投票:0回答:1

在下面显示的表格中,我已成功完成

worksheet.removeRow(row)
清除不需要的行。

这就是我删除不需要的行的方法

 public void removeRow(XSSFSheet worksheet, List<Row> toBeRemovedRows) {
    for (Row row : toBeRemovedRows) {
        worksheet.removeRow(row);
    }
 }

toBeRemovedRows 包含除第 9、14 和 18 行之外的所有行。

据我所知,

worksheet.shiftRows(startRow, endRow, -n);
确实物理删除了这些不需要的行。根据上面的表,我需要删除第 5-8、10-13 和 15-17 行(我想保留前 4 个标题相关行)

我想根据 toBeRemovedRows 列表动态移动这些行。

我如何实现这一目标?预先感谢

java apache-poi
1个回答
0
投票

当您在迭代该集合时从集合中删除并且不使用迭代器本身进行删除时,您的

public void removeRow(XSSFSheet worksheet, List<Row> toBeRemovedRows)
可能会遇到并发修改异常。此外,要删除一个应该从下往上而不是从上往下运行,以避免项目索引出现问题。例如,如果您有第 1,2,3 行并删除了第 2 行,那么之前的 ro 3 将成为第 2 行,并且不再有第 3 行。这在这里不是问题,因为
Sheet.removeRow
并没有真正删除行,而只是删除行中的所有内容。不过,我建议始终从下到上删除项目。

运行

Sheet.removeRow
后,所有“删除”的行都完全为空,并且不再位于工作表内部文件存储中。如果尝试使用
Sheet.getRow
获取此类行,则会得到
null
。知道这一点后,我们可以简单地从下到上遍历工作表的所有行,以获取所有填充行的行索引,计算此填充行与上一个找到的填充行之间的差异。然后将该填充行向上移动与计算出的差异一样多的行。之后,只有填充的行才应出现在工作表中。为了避免丢失标题部分中可能的空行,可以在给定的第一个剩余行中结束此过程。

示例:

 void removeEmptyRows(Sheet sheet, int firstRemainingRow) {
  int previousFilledRow = sheet.getLastRowNum();
  for (int i = sheet.getLastRowNum(); i >= firstRemainingRow; i--) {
   Row row = sheet.getRow(i);
   if (row != null) {
    int thisFilledRow = row.getRowNum();
    int shift = thisFilledRow - previousFilledRow + 1;
    System.out.println("this: " + thisFilledRow);
    System.out.println("previous: " + previousFilledRow);
    System.out.println("shift: " + shift);
    if (shift < 0) {
     sheet.shiftRows(previousFilledRow, sheet.getLastRowNum(), shift);   
    }
    previousFilledRow = thisFilledRow;
   }
  }
 }

完整的测试示例:

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

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

import java.util.List;
import java.util.ArrayList;

class ExcelReadShiftRowsAndWrite {
    
 static List<Row> getToBeRemovedRows(Sheet sheet, DataFormatter dataFormatter, int columnIdx, String criteria) {
  List<Row> result = new ArrayList<Row>();
  for (Row row : sheet) {
   String foundCriteria = dataFormatter.formatCellValue(row.getCell(columnIdx));
   if (foundCriteria.equals(criteria)) {
    result.add(row);
   }       
  }
  return result;
 }   

 static void removeRows(Sheet sheet, List<Row> toBeRemovedRows) {
  for (int i = toBeRemovedRows.size() - 1; i >= 0; i--) {
   sheet.removeRow(toBeRemovedRows.get(i));
  }
 }

 static void removeEmptyRows(Sheet sheet, int firstRemainingRow) {
  int previousFilledRow = sheet.getLastRowNum();
  for (int i = sheet.getLastRowNum(); i >= firstRemainingRow; i--) {
   Row row = sheet.getRow(i);
   if (row != null) {
    int thisFilledRow = row.getRowNum();
    int shift = thisFilledRow - previousFilledRow + 1;
    System.out.println("this: " + thisFilledRow);
    System.out.println("previous: " + previousFilledRow);
    System.out.println("shift: " + shift);
    if (shift < 0) {
     sheet.shiftRows(previousFilledRow, sheet.getLastRowNum(), shift);   
    }
    previousFilledRow = thisFilledRow;
   }
  }
 }
 
 public static void main(String[] args) throws Exception {
  //String fileIn= "./TestIn.xls"; String fileOut= "./TestOut.xls";
  String fileIn= "./TestIn.xlsx"; String fileOut= "./TestOut.xlsx";

  try (Workbook workbook = WorkbookFactory.create(new FileInputStream(fileIn));
       FileOutputStream out = new FileOutputStream(fileOut)) {
           
   DataFormatter dataFormatter = new DataFormatter();
   dataFormatter.setUseCachedValuesForFormulaCells(true);
  
   Sheet sheet = workbook.getSheet("Sheet1");
   
   List<Row> toBeRemovedRows = getToBeRemovedRows(sheet, dataFormatter, 4, "x");

   removeRows(sheet, toBeRemovedRows);
   
   removeEmptyRows(sheet, 3);

   workbook.write(out);
  } 
 }
}

TestIn.xlsx
看起来像:

结果

TestOut.xlsx
看起来像:

© www.soinside.com 2019 - 2024. All rights reserved.