diff options
author | Dominik Stadler <centic@apache.org> | 2020-04-26 08:23:04 +0000 |
---|---|---|
committer | Dominik Stadler <centic@apache.org> | 2020-04-26 08:23:04 +0000 |
commit | 979d1b48e7a057dbfd29af6bbe0dabad0adec65a (patch) | |
tree | 555d42111a61c5013d99ac3a6ee8f353b3eef272 /src/java/org/apache | |
parent | 6ae31c8a67aeca159f1f0f0eeb5a62a690b1ebba (diff) | |
download | poi-979d1b48e7a057dbfd29af6bbe0dabad0adec65a.tar.gz poi-979d1b48e7a057dbfd29af6bbe0dabad0adec65a.zip |
Github-177: Avoid NullPointerException if RangeCopier encounters empty/missing rows
Also expose one-parameter constructor and verify it in tests.
Closes #177
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1877010 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache')
-rw-r--r-- | src/java/org/apache/poi/hssf/usermodel/HSSFRangeCopier.java | 4 | ||||
-rw-r--r-- | src/java/org/apache/poi/ss/usermodel/RangeCopier.java | 117 |
2 files changed, 66 insertions, 55 deletions
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFRangeCopier.java b/src/java/org/apache/poi/hssf/usermodel/HSSFRangeCopier.java index f6d3fb3819..60b1a23417 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFRangeCopier.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFRangeCopier.java @@ -32,6 +32,10 @@ public class HSSFRangeCopier extends RangeCopier { super(sourceSheet, destSheet); } + public HSSFRangeCopier(Sheet sheet) { + super(sheet); + } + protected void adjustCellReferencesInsideFormula(Cell cell, Sheet destSheet, int deltaX, int deltaY) { FormulaRecordAggregate fra = (FormulaRecordAggregate)((HSSFCell)cell).getCellValueRecord(); int destSheetIndex = destSheet.getWorkbook().getSheetIndex(destSheet); diff --git a/src/java/org/apache/poi/ss/usermodel/RangeCopier.java b/src/java/org/apache/poi/ss/usermodel/RangeCopier.java index 6c73530b5c..8409accc72 100644 --- a/src/java/org/apache/poi/ss/usermodel/RangeCopier.java +++ b/src/java/org/apache/poi/ss/usermodel/RangeCopier.java @@ -36,13 +36,15 @@ public abstract class RangeCopier { this.sourceSheet = sourceSheet; this.destSheet = destSheet; } + public RangeCopier(Sheet sheet) { this(sheet, sheet); } - /** Uses input pattern to tile destination region, overwriting existing content. Works in following manner : + + /** 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. + * 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 */ @@ -50,49 +52,54 @@ public abstract class RangeCopier { Sheet sourceCopy = sourceSheet.getWorkbook().cloneSheet(sourceSheet.getWorkbook().getSheetIndex(sourceSheet)); int sourceWidthMinus1 = tilePatternRange.getLastColumn() - tilePatternRange.getFirstColumn(); int sourceHeightMinus1 = tilePatternRange.getLastRow() - tilePatternRange.getFirstRow(); - int rightLimitToCopy; + int rightLimitToCopy; int bottomLimitToCopy; int nextRowIndexToCopy = tileDestRange.getFirstRow(); - do { + do { int nextCellIndexInRowToCopy = tileDestRange.getFirstColumn(); int heightToCopyMinus1 = Math.min(sourceHeightMinus1, tileDestRange.getLastRow() - nextRowIndexToCopy); bottomLimitToCopy = tilePatternRange.getFirstRow() + heightToCopyMinus1; - do { + do { int widthToCopyMinus1 = Math.min(sourceWidthMinus1, tileDestRange.getLastColumn() - nextCellIndexInRowToCopy); rightLimitToCopy = tilePatternRange.getFirstColumn() + widthToCopyMinus1; CellRangeAddress rangeToCopy = new CellRangeAddress( tilePatternRange.getFirstRow(), bottomLimitToCopy, - tilePatternRange.getFirstColumn(), rightLimitToCopy + tilePatternRange.getFirstColumn(), rightLimitToCopy ); copyRange(rangeToCopy, nextCellIndexInRowToCopy - rangeToCopy.getFirstColumn(), nextRowIndexToCopy - rangeToCopy.getFirstRow(), sourceCopy); - nextCellIndexInRowToCopy += widthToCopyMinus1 + 1; + nextCellIndexInRowToCopy += widthToCopyMinus1 + 1; } while (nextCellIndexInRowToCopy <= tileDestRange.getLastColumn()); nextRowIndexToCopy += heightToCopyMinus1 + 1; } while (nextRowIndexToCopy <= tileDestRange.getLastRow()); - + 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 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()); if(deltaY != 0) - verticalFormulaShifter = FormulaShifter.createForRowCopy(sourceSheet.getWorkbook().getSheetIndex(sourceSheet), + verticalFormulaShifter = FormulaShifter.createForRowCopy(sourceSheet.getWorkbook().getSheetIndex(sourceSheet), sourceSheet.getSheetName(), sourceRange.getFirstRow(), sourceRange.getLastRow(), deltaY, sourceSheet.getWorkbook().getSpreadsheetVersion()); - - for(int rowNo = sourceRange.getFirstRow(); rowNo <= sourceRange.getLastRow(); rowNo++) { - Row sourceRow = sourceClone.getRow(rowNo); // copy from source copy, original source might be overridden in process! - for (int columnIndex = sourceRange.getFirstColumn(); columnIndex <= sourceRange.getLastColumn(); columnIndex++) { + + for(int rowNo = sourceRange.getFirstRow(); rowNo <= sourceRange.getLastRow(); rowNo++) { + // copy from source copy, original source might be overridden in process! + Row sourceRow = sourceClone.getRow(rowNo); + if(sourceRow == null) { + continue; + } + + for (int columnIndex = sourceRange.getFirstColumn(); columnIndex <= sourceRange.getLastColumn(); columnIndex++) { Cell sourceCell = sourceRow.getCell(columnIndex); if(sourceCell == null) continue; Row destRow = destSheet.getRow(rowNo + deltaY); if(destRow == null) destRow = destSheet.createRow(rowNo + deltaY); - + Cell newCell = destRow.getCell(columnIndex + deltaX); if(newCell == null) { newCell = destRow.createCell(columnIndex + deltaX); @@ -104,56 +111,56 @@ public abstract class RangeCopier { } } } - + protected abstract void adjustCellReferencesInsideFormula(Cell cell, Sheet destSheet, int deltaX, int deltaY); // this part is different for HSSF and XSSF - + protected boolean adjustInBothDirections(Ptg[] ptgs, int sheetIndex, int deltaX, int deltaY) { boolean adjustSucceeded = true; if(deltaY != 0) - adjustSucceeded = verticalFormulaShifter.adjustFormula(ptgs, sheetIndex); + adjustSucceeded = verticalFormulaShifter.adjustFormula(ptgs, sheetIndex); if(deltaX != 0) adjustSucceeded = adjustSucceeded && horizontalFormulaShifter.adjustFormula(ptgs, sheetIndex); return adjustSucceeded; } - - // TODO clone some more properties ? - public static void cloneCellContent(Cell srcCell, Cell destCell, Map<Integer, CellStyle> styleMap) { - if(styleMap != null) { - if(srcCell.getSheet().getWorkbook() == destCell.getSheet().getWorkbook()){ - destCell.setCellStyle(srcCell.getCellStyle()); + + // TODO clone some more properties ? + public static void cloneCellContent(Cell srcCell, Cell destCell, Map<Integer, CellStyle> styleMap) { + if(styleMap != null) { + if(srcCell.getSheet().getWorkbook() == destCell.getSheet().getWorkbook()){ + destCell.setCellStyle(srcCell.getCellStyle()); } else { - int stHashCode = srcCell.getCellStyle().hashCode(); - CellStyle newCellStyle = styleMap.get(stHashCode); - if(newCellStyle == null){ - newCellStyle = destCell.getSheet().getWorkbook().createCellStyle(); - newCellStyle.cloneStyleFrom(srcCell.getCellStyle()); - styleMap.put(stHashCode, newCellStyle); - } - destCell.setCellStyle(newCellStyle); - } - } - switch(srcCell.getCellType()) { - case STRING: - destCell.setCellValue(srcCell.getStringCellValue()); - break; + int stHashCode = srcCell.getCellStyle().hashCode(); + CellStyle newCellStyle = styleMap.get(stHashCode); + if(newCellStyle == null){ + newCellStyle = destCell.getSheet().getWorkbook().createCellStyle(); + newCellStyle.cloneStyleFrom(srcCell.getCellStyle()); + styleMap.put(stHashCode, newCellStyle); + } + destCell.setCellStyle(newCellStyle); + } + } + switch(srcCell.getCellType()) { + case STRING: + destCell.setCellValue(srcCell.getStringCellValue()); + break; case NUMERIC: - destCell.setCellValue(srcCell.getNumericCellValue()); - break; - case BLANK: + destCell.setCellValue(srcCell.getNumericCellValue()); + break; + case BLANK: destCell.setBlank(); - break; - case BOOLEAN: - destCell.setCellValue(srcCell.getBooleanCellValue()); - break; - case ERROR: - destCell.setCellErrorValue(srcCell.getErrorCellValue()); - break; - case FORMULA: + break; + case BOOLEAN: + destCell.setCellValue(srcCell.getBooleanCellValue()); + break; + case ERROR: + destCell.setCellErrorValue(srcCell.getErrorCellValue()); + break; + case FORMULA: String oldFormula = srcCell.getCellFormula(); - destCell.setCellFormula(oldFormula); - break; - default: - break; - } + destCell.setCellFormula(oldFormula); + break; + default: + break; + } } } |