由于poi中不支持整体行下移,或者通过复制的时候行下移样式丢失,所以找到一个整体下移的思路,并进行了一部分自己理解的简化
/**
* 整体行下移
* @param sheet 表
* @param rows 移动的行
*/
private void move(XSSFSheet sheet,Integer rows){
int beginRowNo = rows;
Row beginRow = sheet.getRow(beginRowNo);
int addNo = 1;
int moveBeginRow = beginRowNo+1;
//如果移动的开始行不存在,则创建一个空行,否则复制的时候会丢掉不存在的行
if(sheet.getRow(moveBeginRow)==null){
sheet.createRow(moveBeginRow);
}
int lastRowNo = sheet.getLastRowNum();
//计算移动的行数
int movedNo = lastRowNo-moveBeginRow+1;
//临时区的开始行
int tempBeginRowNo = lastRowNo+addNo+1;
//临时区的结束行
int tempLastRowNo = tempBeginRowNo+movedNo-1;
//末尾部分的最终开始行
int finalBeginRowNo = addNo+beginRowNo;
//移动开始行以后的行到临时的开始行
moveRows(sheet,moveBeginRow,lastRowNo,tempBeginRowNo);
//在空出位置插入新行并复制第一行的样式
for (int i = moveBeginRow; i <finalBeginRowNo; i++){
Row row = sheet.getRow(i);
if (row != null){
sheet.removeRow(row);
}
//创建空白的行
sheet.createRow(i);
if(beginRow!=null){
//复制第一行的样式到当前行
CellCopyPolicy cellCopyPolicy=new CellCopyPolicy();
cellCopyPolicy.setCopyRowHeight(DEFAULT_COPY_ROW_HEIGHT_POLICY);
sheet.copyRows(beginRowNo,beginRowNo, i, cellCopyPolicy);
}
}
//将移动的行从临时开始行回移新增好的行的末尾
/*
为什么不直接第一次移动的预期的末尾呢?是因为POX只支持Copy行的操作,而copy操作不是完整的区间覆盖。
如果源区间内带有格式,并且目的区间和源区间有重叠话,会导致无法copy后源区间和目的区间混合在一起,无法清理。
因此实现移动行区间的操作时,需要先将源行区间复制到一个临时的区域,然后清理掉源行区间的行和样式,再插入需要新增的行
,最后再将被移动的行区间移动回新的行末尾。
*/
moveRows(sheet,tempBeginRowNo,tempLastRowNo,finalBeginRowNo);
}
/**
* 移动行
* @param sheet
* @param srcBeginRow 临时区的开始行
* @param srcEndRow 临时区的结束行
* @param destBeginRow 末尾部分的最终开始行
*/
private static void moveRows(XSSFSheet sheet,int srcBeginRow,int srcEndRow,int destBeginRow){
//先复制到目的位置
CellCopyPolicy cellCopyPolicy=new CellCopyPolicy();
cellCopyPolicy.setCopyRowHeight(DEFAULT_COPY_ROW_HEIGHT_POLICY);
sheet.copyRows(srcBeginRow, srcEndRow, destBeginRow, cellCopyPolicy);
//清理之前残留的合并单元格
List<Integer> removeMergedRegion = new ArrayList<>();
for(int i=sheet.getMergedRegions().size()-1;i>=0;i--){
CellRangeAddress address = sheet.getMergedRegions().get(i);
//如果合并单元格在复制前的位置,则删除
if(address.getFirstRow() >= srcBeginRow && address.getFirstRow()<destBeginRow ){
removeMergedRegion.add(i);
}
};
//执行清理合并的单元格
for(Integer i:removeMergedRegion){
sheet.removeMergedRegion(i);
}
//删除移动后原地的行
for (int i = srcBeginRow; i <= srcEndRow; i++){
Row row = sheet.getRow(i);
if (row != null){
//删除复制后残留的行
sheet.removeRow(row);
}
}
}