原因就是因为shiftRows这个方法并不是真正的删除单元行! 而是通过移动下面的单元行中的内容上来,覆盖原先的内容,以此来做到类似于删除单元行的样子,但是并不会对合并单元格有影响。 如果你想要删除的单元行与它下面一行的单元格具备不同的合并单元格,那么就会出现影响。
网上找了半天也没有解决办法。 只能自己想法子解决,
解决思路。 让想要删除的单元行与下一行中的单元格格式相同。
首先取得下面一行单元格的格式。(如果下一行中不具备合并单元格,则不需要这一步也可以,如果要删除多行,只要去要删除的最后一行,下面一行的格式即可)
private List<Map<Integer, Integer>> reginMapList(Row row, int columnIndex) { //第一个integer代表起始列数,第二个integer 代表结束列数 //保存指定行的 全部合并单元格的格式,非合并单元格不包存 List<Map<Integer, Integer>> mapList = new ArrayList<>(); Sheet sheet = row.getSheet(); int numMergedRegions = sheet.getNumMergedRegions(); int rowIndex = row.getRowNum(); int firstC; int lastC; int firstR; int lastR; //POI中取得所有的合并单元格 ,顺序是乱的,而不是冲上到下 for (i = 0; i < numMergedRegions; i++) { CellRangeAddress cellRangeAddress = sheet.getMergedRegion(i); // 获得合并单元格的起始行, 结束行, 起始列, 结束列 firstC = cellRangeAddress.getFirstColumn(); lastC = cellRangeAddress.getLastColumn(); firstR = cellRangeAddress.getFirstRow(); lastR = cellRangeAddress.getLastRow(); //当合并单元格行数与指定行相同 ,且指定列数大于或等于单元格起始列时 while (firstR == rowIndex && columnIndex <= firstC) { //判断是否属于合并单元格 if (columnIndex <= lastC && columnIndex >= firstC && rowIndex <= lastR && rowIndex >= firstR) { Map<Integer, Integer> map = new HashMap<>(); map.put(firstC, lastC); mapList.add(map); columnIndex = 1; break; } else { columnIndex++; } } } return mapList; }之后删除需要删除的单元行的合并单元格格式
private void deleteRegion(Sheet sheet, int begRow, int endRow, int begCol, int endCol) { //如果指定位置是合并单元格则删除(仅删除一个) //这里是针对我自己的情况 //如果要删除一行多个合并单元格,还需要自己去修改 int count = sheet.getNumMergedRegions(); for (int i = 0; i < count; i++) { CellRangeAddress rangeAddress = sheet.getMergedRegion(i); if (rangeAddress == null) { continue; } int fistRow = rangeAddress.getFirstRow(); int lastRow = rangeAddress.getLastRow(); int fistCol = rangeAddress.getFirstColumn(); int lastCol = rangeAddress.getLastColumn(); if (fistRow >= begRow && lastRow <= endRow && fistCol >= begCol && lastCol <= endCol) { sheet.removeMergedRegion(i); } } }然后将已经恢复到不具备合并单元格的这行 按照下面一行的格式进行单元格合并,方便删除。
private void cellRegin(Sheet sheet, Row mainRow, List<Map<Integer, Integer>> mapList) { //mainRow 进行合并单元格的行 sheet.removeRow(mainRow);//先把内容删了,防止之后多出数据 if (mapList.size() > 0) { for (Map<Integer, Integer> map : mapList) { for (Integer begCol : map.keySet()) { mergedRegion(sheet, new TableRegion(mainRow.getRowNum(), mainRow.getRowNum(), begCol, map.get(begCol))); } } } }最后就可以对该行进行删除
sheet.shiftRows(mainRowNum +1, sheet.getLastRowNum(), - 1);//从下行到最后一行 全部上移一行,覆盖该行的内容这个解决方法比较复杂,但目前也没想到什么其他方法,主要是POI中本身也没有提供删除单元行内容的办法