}
final List<int[]> removePairs = new ArrayList<int[]>(); //column spans to be removed
final Set<XSSFCell> rowCells = new HashSet<XSSFCell>();
int expectColnum = startCol; //handle sparse columns which might override destination column
for (Iterator<XSSFCell> it = row.getCells().subMap(startCol, endCol+1).values().iterator(); it.hasNext(); ) {
XSSFCell cell = it.next();
int colnum = cell.getColumnIndex();
final int newColnum = colnum + n;
if (colnum > expectColnum) { //sparse column between expectColnum(inclusive) and current column(exclusive), to be removed
addRemovePair(removePairs, row, expectColnum + n, newColnum);
}
expectColnum = colnum + 1;
it.remove(); //remove cell from this row
final boolean inbound = 0 <= newColnum && newColnum <= maxcol;
if (!inbound) {
notifyCellShifting(cell);
continue;
}
rowCells.add(cell);
}
addRemovePair(removePairs, row, expectColnum + n, endCol + 1 + n);
//remove those not existing cells
for(int[] pair : removePairs) {
final int start = Math.max(0, pair[0]);
final int end = Math.min(maxcol + 1, pair[1]);
for(int j=start; j < end; ++j) {
Cell cell = row.getCell(j);
if (cell != null) {
row.removeCell(cell);
}
}
}
//update the cells
for(XSSFCell srcCell: rowCells) {
BookHelper.assignCell(srcCell, row.createCell(srcCell.getColumnIndex()+n));
}
//special case1: endCol < startCol
//special case2: (endCol - startCol + 1) < ABS(n)
if (n < 0) {
if (endCol < startCol) { //special case1
final int replacedStartCol = startCol + n;
for ( int colNum = replacedStartCol; colNum >= replacedStartCol && colNum <= endCol && colNum >= 0 && colNum <= maxcol; ++colNum) {
final XSSFCell cell = row.getCell(colNum, Row.RETURN_NULL_AND_BLANK);
if (cell != null) {
row.removeCell(cell);
}
}
} else if (clearRest) { //special case 2
final int replacedStartCol = endCol + n + 1;
if (replacedStartCol <= startCol) {
for ( int colNum = replacedStartCol; colNum >= replacedStartCol && colNum <= startCol && colNum >= 0 && colNum <= maxcol; ++colNum) {
final XSSFCell cell = row.getCell(colNum, Row.RETURN_NULL_AND_BLANK);
if (cell != null) {
row.removeCell(cell);
}
}
}