mirror of https://github.com/apache/poi.git
[github-179] add an option for RangeCopier.copyRange() to clone styles. Thanks to xjlin0. This closes #179
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1877792 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
237d55b3e3
commit
9bddb8729e
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package org.apache.poi.ss.usermodel;
|
package org.apache.poi.ss.usermodel;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.apache.poi.ss.formula.FormulaShifter;
|
import org.apache.poi.ss.formula.FormulaShifter;
|
||||||
import org.apache.poi.ss.formula.ptg.Ptg;
|
import org.apache.poi.ss.formula.ptg.Ptg;
|
||||||
|
@ -46,10 +47,25 @@ public abstract class RangeCopier {
|
||||||
* 2.Paste source but only inside of destination borders.
|
* 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.
|
* 3.If there is space left on right or bottom side of copy, process it as in step 2.
|
||||||
* @param tilePatternRange source range which should be copied in tiled manner
|
* @param tilePatternRange source range which should be copied in tiled manner
|
||||||
* @param tileDestRange destination range, which should be overridden
|
* @param tileDestRange destination range, which should be overridden
|
||||||
*/
|
*/
|
||||||
public void copyRange(CellRangeAddress tilePatternRange, CellRangeAddress tileDestRange) {
|
public void copyRange(CellRangeAddress tilePatternRange, CellRangeAddress tileDestRange) {
|
||||||
|
copyRange(tilePatternRange, tileDestRange, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 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.
|
||||||
|
* @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
|
||||||
|
* @param copyMergedRanges whether to copy merged ranges
|
||||||
|
* @since 4.1.3
|
||||||
|
*/
|
||||||
|
public void copyRange(CellRangeAddress tilePatternRange, CellRangeAddress tileDestRange, boolean copyStyles, boolean copyMergedRanges) {
|
||||||
Sheet sourceCopy = sourceSheet.getWorkbook().cloneSheet(sourceSheet.getWorkbook().getSheetIndex(sourceSheet));
|
Sheet sourceCopy = sourceSheet.getWorkbook().cloneSheet(sourceSheet.getWorkbook().getSheetIndex(sourceSheet));
|
||||||
|
Map<Integer, CellStyle> styleMap = copyStyles ? new HashMap<Integer, CellStyle>() {} : null;
|
||||||
int sourceWidthMinus1 = tilePatternRange.getLastColumn() - tilePatternRange.getFirstColumn();
|
int sourceWidthMinus1 = tilePatternRange.getLastColumn() - tilePatternRange.getFirstColumn();
|
||||||
int sourceHeightMinus1 = tilePatternRange.getLastRow() - tilePatternRange.getFirstRow();
|
int sourceHeightMinus1 = tilePatternRange.getLastRow() - tilePatternRange.getFirstRow();
|
||||||
int rightLimitToCopy;
|
int rightLimitToCopy;
|
||||||
|
@ -67,17 +83,21 @@ public abstract class RangeCopier {
|
||||||
tilePatternRange.getFirstRow(), bottomLimitToCopy,
|
tilePatternRange.getFirstRow(), bottomLimitToCopy,
|
||||||
tilePatternRange.getFirstColumn(), rightLimitToCopy
|
tilePatternRange.getFirstColumn(), rightLimitToCopy
|
||||||
);
|
);
|
||||||
copyRange(rangeToCopy, nextCellIndexInRowToCopy - rangeToCopy.getFirstColumn(), nextRowIndexToCopy - rangeToCopy.getFirstRow(), sourceCopy);
|
copyRange(rangeToCopy, nextCellIndexInRowToCopy - rangeToCopy.getFirstColumn(), nextRowIndexToCopy - rangeToCopy.getFirstRow(), sourceCopy, styleMap);
|
||||||
nextCellIndexInRowToCopy += widthToCopyMinus1 + 1;
|
nextCellIndexInRowToCopy += widthToCopyMinus1 + 1;
|
||||||
} while (nextCellIndexInRowToCopy <= tileDestRange.getLastColumn());
|
} while (nextCellIndexInRowToCopy <= tileDestRange.getLastColumn());
|
||||||
nextRowIndexToCopy += heightToCopyMinus1 + 1;
|
nextRowIndexToCopy += heightToCopyMinus1 + 1;
|
||||||
} while (nextRowIndexToCopy <= tileDestRange.getLastRow());
|
} while (nextRowIndexToCopy <= tileDestRange.getLastRow());
|
||||||
|
|
||||||
|
if (copyMergedRanges) {
|
||||||
|
sourceSheet.getMergedRegions().forEach((mergedRangeAddress) -> destSheet.addMergedRegion(mergedRangeAddress));
|
||||||
|
}
|
||||||
|
|
||||||
int tempCopyIndex = sourceSheet.getWorkbook().getSheetIndex(sourceCopy);
|
int tempCopyIndex = sourceSheet.getWorkbook().getSheetIndex(sourceCopy);
|
||||||
sourceSheet.getWorkbook().removeSheetAt(tempCopyIndex);
|
sourceSheet.getWorkbook().removeSheetAt(tempCopyIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void copyRange(CellRangeAddress sourceRange, int deltaX, int deltaY, Sheet sourceClone) { //NOSONAR, it's a bit complex but monolith method, does not make much sense to divide it
|
private void copyRange(CellRangeAddress sourceRange, int deltaX, int deltaY, Sheet sourceClone, Map<Integer, CellStyle> styleMap) { //NOSONAR, it's a bit complex but monolith method, does not make much sense to divide it
|
||||||
if(deltaX != 0)
|
if(deltaX != 0)
|
||||||
horizontalFormulaShifter = FormulaShifter.createForColumnCopy(sourceSheet.getWorkbook().getSheetIndex(sourceSheet),
|
horizontalFormulaShifter = FormulaShifter.createForColumnCopy(sourceSheet.getWorkbook().getSheetIndex(sourceSheet),
|
||||||
sourceSheet.getSheetName(), sourceRange.getFirstColumn(), sourceRange.getLastColumn(), deltaX, sourceSheet.getWorkbook().getSpreadsheetVersion());
|
sourceSheet.getSheetName(), sourceRange.getFirstColumn(), sourceRange.getLastColumn(), deltaX, sourceSheet.getWorkbook().getSpreadsheetVersion());
|
||||||
|
@ -105,7 +125,7 @@ public abstract class RangeCopier {
|
||||||
newCell = destRow.createCell(columnIndex + deltaX);
|
newCell = destRow.createCell(columnIndex + deltaX);
|
||||||
}
|
}
|
||||||
|
|
||||||
cloneCellContent(sourceCell, newCell, null);
|
cloneCellContent(sourceCell, newCell, styleMap);
|
||||||
if(newCell.getCellType() == CellType.FORMULA)
|
if(newCell.getCellType() == CellType.FORMULA)
|
||||||
adjustCellReferencesInsideFormula(newCell, destSheet, deltaX, deltaY);
|
adjustCellReferencesInsideFormula(newCell, destSheet, deltaX, deltaY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,14 +19,14 @@
|
||||||
|
|
||||||
package org.apache.poi.ss.usermodel;
|
package org.apache.poi.ss.usermodel;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.apache.poi.ss.ITestDataProvider;
|
import org.apache.poi.ss.ITestDataProvider;
|
||||||
import org.apache.poi.ss.util.CellRangeAddress;
|
import org.apache.poi.ss.util.CellRangeAddress;
|
||||||
import org.apache.poi.ss.util.CellReference;
|
import org.apache.poi.ss.util.CellReference;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
@Ignore
|
@Ignore
|
||||||
public abstract class TestRangeCopier {
|
public abstract class TestRangeCopier {
|
||||||
protected Sheet sheet1;
|
protected Sheet sheet1;
|
||||||
|
@ -116,13 +116,57 @@ public abstract class TestRangeCopier {
|
||||||
assertEquals("1.2", getCellContent(sheet1, "G24"));
|
assertEquals("1.2", getCellContent(sheet1, "G24"));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static String getCellContent(Sheet sheet, String coordinates) {
|
@Test
|
||||||
|
public void testCopyStyles() {
|
||||||
|
String cellContent = "D6 aligned to the right";
|
||||||
|
HorizontalAlignment toTheRight = HorizontalAlignment.RIGHT;
|
||||||
|
// create cell with content aligned to the right
|
||||||
|
CellStyle style = workbook.createCellStyle();
|
||||||
|
style.setAlignment(toTheRight);
|
||||||
|
Cell cell = sheet1.createRow(5).createCell(3);
|
||||||
|
cell.setCellValue(cellContent);
|
||||||
|
cell.setCellStyle(style);
|
||||||
|
|
||||||
|
Sheet destSheet = sheet2;
|
||||||
|
CellRangeAddress tileRange = CellRangeAddress.valueOf("D6:D6"); // on sheet1
|
||||||
|
CellRangeAddress destRange = CellRangeAddress.valueOf("J6:J6"); // on sheet2
|
||||||
|
transSheetRangeCopier.copyRange(tileRange, destRange, true, false);
|
||||||
|
assertEquals(cellContent, getCellContent(destSheet, "J6"));
|
||||||
|
assertEquals(toTheRight, getCell(destSheet, "J6").getCellStyle().getAlignment());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMergedRanges() {
|
||||||
|
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);
|
||||||
|
|
||||||
|
Sheet destSheet = sheet2;
|
||||||
|
CellRangeAddress tileRange = CellRangeAddress.valueOf("D6:E7"); // on sheet1
|
||||||
|
transSheetRangeCopier.copyRange(tileRange, tileRange, false, true);
|
||||||
|
assertEquals(cellContent, getCellContent(destSheet, "D6"));
|
||||||
|
assertFalse(destSheet.getMergedRegions().isEmpty());
|
||||||
|
destSheet.getMergedRegions().forEach((mergedRegion) -> {
|
||||||
|
assertTrue(mergedRegion.equals(mergedRangeAddress));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String getCellContent(Sheet sheet, String coordinates) {
|
||||||
|
Cell cell = getCell(sheet, coordinates);
|
||||||
|
return cell == null ? "" : cell.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Cell getCell(Sheet sheet, String coordinates) {
|
||||||
try {
|
try {
|
||||||
CellReference p = new CellReference(coordinates);
|
CellReference p = new CellReference(coordinates);
|
||||||
return sheet.getRow(p.getRow()).getCell(p.getCol()).toString();
|
return sheet.getRow(p.getRow()).getCell(p.getCol());
|
||||||
}
|
}
|
||||||
catch (NullPointerException e) { // row or cell does not exist
|
catch (NullPointerException e) { // row or cell does not exist
|
||||||
return "";
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue