mirror of
https://github.com/apache/poi.git
synced 2026-02-27 20:40:08 +08:00
Bugzilla 69303: Fix RangeCopier's copyMergedRanges when copying withing the same sheet (#958)
* Bugzilla 69303: added failing test for case with same sheet RangeCopier for merged regions * Bugzilla 69303: fixed same sheet issue when enabling copy of merged ranges * Bugzilla 69303: added @since 6.0.0 to new public methods --------- Co-authored-by: Viktor Ozerov <vik.ozerov+git@gmail.com>
This commit is contained in:
parent
c953a8ff22
commit
006e49765c
@ -54,9 +54,11 @@ public abstract class RangeCopier {
|
||||
}
|
||||
|
||||
/** Uses input pattern to tile destination region, overwriting existing content. Works in following manner :
|
||||
* 1.Start from top-left of destination.
|
||||
* 2.Paste source but only inside of destination borders.
|
||||
* 3.If there is space left on right or bottom side of copy, process it as in step 2.
|
||||
* <ol>
|
||||
* <li>Start from top-left of destination.</li>
|
||||
* <li>Paste source but only inside of destination borders.</li>
|
||||
* <li>If there is space left on right or bottom side of copy, process it as in step 2.</li>
|
||||
* </ol>
|
||||
* @param tilePatternRange source range which should be copied in tiled manner
|
||||
* @param tileDestRange destination range, which should be overridden
|
||||
* @param copyStyles whether to copy the cell styles
|
||||
@ -90,7 +92,12 @@ public abstract class RangeCopier {
|
||||
} while (nextRowIndexToCopy <= tileDestRange.getLastRow());
|
||||
|
||||
if (copyMergedRanges) {
|
||||
sourceSheet.getMergedRegions().forEach((mergedRangeAddress) -> destSheet.addMergedRegion(mergedRangeAddress));
|
||||
int rowOffset = tileDestRange.getFirstRow() - tilePatternRange.getFirstRow();
|
||||
int columnOffset = tileDestRange.getFirstColumn() - tilePatternRange.getFirstColumn();
|
||||
sourceSheet.getMergedRegions().stream()
|
||||
.filter(tilePatternRange::contains)
|
||||
.map(sourceMergedRegion -> sourceMergedRegion.shift(rowOffset, columnOffset))
|
||||
.forEach(destSheet::addMergedRegion);
|
||||
}
|
||||
|
||||
int tempCopyIndex = sourceSheet.getWorkbook().getSheetIndex(sourceCopy);
|
||||
|
||||
@ -133,4 +133,18 @@ public class CellRangeAddress extends CellRangeAddressBase {
|
||||
}
|
||||
return new CellRangeAddress(a.getRow(), b.getRow(), a.getCol(), b.getCol());
|
||||
}
|
||||
|
||||
/**
|
||||
* Shifts cell range by specified number of rows and columns.
|
||||
*
|
||||
* @param rows rows to shift by.
|
||||
* @param columns columns to shift by.
|
||||
* @return copy of this {@link CellRangeAddress}, shifted by rows and columns.
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public CellRangeAddress shift(int rows, int columns) {
|
||||
return new CellRangeAddress(getFirstRow() + rows, getLastRow() + rows,
|
||||
getFirstColumn() + columns, getLastColumn() + columns);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -228,6 +228,21 @@ public abstract class CellRangeAddressBase implements Iterable<CellAddress>, Dup
|
||||
other._firstCol <= this._lastCol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether this CellRangeAddress fully contains CellRangeAddress.
|
||||
*
|
||||
* @param other a candidate cell range address to check if contained within this range
|
||||
* @return returns true if this range contains other range.
|
||||
* @see #isInRange(int, int) for checking if a single cell contains
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public boolean contains(CellRangeAddressBase other) {
|
||||
return this._firstRow <= other._firstRow &&
|
||||
this._lastRow >= other._lastRow &&
|
||||
this._firstCol <= other._firstCol &&
|
||||
this._lastCol >= other._lastCol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Useful for logic like table/range styling, where some elements apply based on relative position in a range.
|
||||
* @return set of {@link CellPosition}s occupied by the given coordinates. Empty if the coordinates are not in the range, never null.
|
||||
|
||||
@ -152,9 +152,27 @@ public abstract class BaseTestRangeCopier {
|
||||
transSheetRangeCopier.copyRange(tileRange, tileRange, false, true);
|
||||
assertEquals(cellContent, getCellContent(destSheet, "D6"));
|
||||
assertFalse(destSheet.getMergedRegions().isEmpty());
|
||||
destSheet.getMergedRegions().forEach((mergedRegion) -> {
|
||||
assertEquals(mergedRangeAddress, mergedRegion);
|
||||
});
|
||||
destSheet.getMergedRegions().forEach(mergedRegion ->
|
||||
assertEquals(mergedRangeAddress, mergedRegion)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSameSheetMergedRanges() {
|
||||
String cellContent = "D6 merged to E7";
|
||||
|
||||
// create cell merged from D6 to E7
|
||||
CellRangeAddress mergedRangeAddress = new CellRangeAddress(5,6,3,4);
|
||||
Cell cell = sheet1.createRow(5).createCell(3);
|
||||
cell.setCellValue(cellContent);
|
||||
sheet1.addMergedRegion(mergedRangeAddress);
|
||||
|
||||
CellRangeAddress tileRange = CellRangeAddress.valueOf("D6:E7");
|
||||
CellRangeAddress targetRange = CellRangeAddress.valueOf("D8:E9");
|
||||
rangeCopier.copyRange(tileRange, targetRange, false, true);
|
||||
assertEquals(cellContent, getCellContent(sheet1, "D8"));
|
||||
assertFalse(sheet1.getMergedRegions().isEmpty());
|
||||
assertTrue(sheet1.getMergedRegions().stream().anyMatch(targetRange::equals));
|
||||
}
|
||||
|
||||
protected static String getCellContent(Sheet sheet, String coordinates) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user