diff options
Diffstat (limited to 'src/java/org/apache/poi/ss')
3 files changed, 195 insertions, 3 deletions
diff --git a/src/java/org/apache/poi/ss/usermodel/helpers/BaseRowColShifter.java b/src/java/org/apache/poi/ss/usermodel/helpers/BaseRowColShifter.java new file mode 100644 index 0000000000..306e515220 --- /dev/null +++ b/src/java/org/apache/poi/ss/usermodel/helpers/BaseRowColShifter.java @@ -0,0 +1,54 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.usermodel.helpers; + + +import org.apache.poi.ss.formula.FormulaShifter; +import org.apache.poi.ss.formula.ptg.AreaErrPtg; +import org.apache.poi.ss.formula.ptg.AreaPtg; +import org.apache.poi.ss.formula.ptg.Ptg; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.util.Internal; + +/** + * Class for code common to {@link RowShifter} and {@link ColumnShifter} + * Helper for shifting rows up or down and columns left and right + */ +@Internal +public abstract class BaseRowColShifter { + + public static CellRangeAddress shiftRange(FormulaShifter formulaShifter, CellRangeAddress cra, int currentExternSheetIx) { + // FormulaShifter works well in terms of Ptgs - so convert CellRangeAddress to AreaPtg (and back) here + AreaPtg aptg = new AreaPtg(cra.getFirstRow(), cra.getLastRow(), cra.getFirstColumn(), cra.getLastColumn(), false, false, false, false); + Ptg[] ptgs = { aptg, }; + + if (!formulaShifter.adjustFormula(ptgs, currentExternSheetIx)) { + return cra; + } + Ptg ptg0 = ptgs[0]; + if (ptg0 instanceof AreaPtg) { + AreaPtg bptg = (AreaPtg) ptg0; + return new CellRangeAddress(bptg.getFirstRow(), bptg.getLastRow(), bptg.getFirstColumn(), bptg.getLastColumn()); + } + if (ptg0 instanceof AreaErrPtg) { + return null; + } + throw new IllegalStateException("Unexpected shifted ptg class (" + ptg0.getClass().getName() + ")"); + } + +} diff --git a/src/java/org/apache/poi/ss/usermodel/helpers/ColumnShifter.java b/src/java/org/apache/poi/ss/usermodel/helpers/ColumnShifter.java new file mode 100644 index 0000000000..7769f30c58 --- /dev/null +++ b/src/java/org/apache/poi/ss/usermodel/helpers/ColumnShifter.java @@ -0,0 +1,136 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.usermodel.helpers; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.poi.ss.formula.FormulaShifter; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.util.Beta; + +/** + * Helper for shifting columns up or down + */ +// non-Javadoc: This abstract class exists to consolidate duplicated code between XSSFColumnShifter and HSSFColumnShifter +// (currently methods sprinkled throughout HSSFSheet) +@Beta +public abstract class ColumnShifter extends BaseRowColShifter { + protected final Sheet sheet; + + public ColumnShifter(Sheet sh) { + sheet = sh; + } + + /** + * Shifts, grows, or shrinks the merged regions due to a column shift. + * Merged regions that are completely overlaid by shifting will be deleted. + * + * @param startColumn the column to start shifting + * @param endColumn the column to end shifting + * @param n the number of columns to shift + * @return an array of affected merged regions, doesn't contain deleted ones + */ + public List<CellRangeAddress> shiftMergedRegions(int startColumn, int endColumn, int n) { + List<CellRangeAddress> shiftedRegions = new ArrayList<>(); + Set<Integer> removedIndices = new HashSet<>(); + //move merged regions completely if they fall within the new region boundaries when they are shifted + int size = sheet.getNumMergedRegions(); + for (int i = 0; i < size; i++) { + CellRangeAddress merged = sheet.getMergedRegion(i); + + // remove merged region that are replaced by the shifting, + // i.e. where the area includes something in the overwritten area + if(removalNeeded(merged, startColumn, endColumn, n)) { + removedIndices.add(i); + continue; + } + + boolean inStart = (merged.getFirstColumn() >= startColumn || merged.getLastColumn() >= startColumn); + boolean inEnd = (merged.getFirstColumn() <= endColumn || merged.getLastColumn() <= endColumn); + + //don't check if it's not within the shifted area + if (!inStart || !inEnd) { + continue; + } + + //only shift if the region outside the shifted columns is not merged too + if (!merged.containsColumn(startColumn - 1) && !merged.containsColumn(endColumn + 1)) { + merged.setFirstColumn(merged.getFirstColumn() + n); + merged.setLastColumn(merged.getLastColumn() + n); + //have to remove/add it back + shiftedRegions.add(merged); + removedIndices.add(i); + } + } + + if(!removedIndices.isEmpty()) { + sheet.removeMergedRegions(removedIndices); + } + + //read so it doesn't get shifted again + for (CellRangeAddress region : shiftedRegions) { + sheet.addMergedRegion(region); + } + return shiftedRegions; + } + + private boolean removalNeeded(CellRangeAddress merged, int startColumn, int endColumn, int n) { + final int movedColumns = endColumn - startColumn + 1; + + // build a range of the columns that are overwritten, i.e. the target-area, but without + // columns that are moved along + final CellRangeAddress overwrite; + if(n > 0) { + // area is moved down => overwritten area is [endColumn + n - movedColumns, endColumn + n] + overwrite = new CellRangeAddress(Math.max(endColumn + 1, endColumn + n - movedColumns), endColumn + n, 0, 0); + } else { + // area is moved up => overwritten area is [startColumn + n, startColumn + n + movedColumns] + overwrite = new CellRangeAddress(startColumn + n, Math.min(startColumn - 1, startColumn + n + movedColumns), 0, 0); + } + + // if the merged-region and the overwritten area intersect, we need to remove it + return merged.intersects(overwrite); + } + + /** + * Updated named ranges + */ + public abstract void updateNamedRanges(FormulaShifter formulaShifter); + + /** + * Update formulas. + */ + public abstract void updateFormulas(FormulaShifter formulaShifter); + + + public abstract void updateConditionalFormatting(FormulaShifter formulaShifter); + + /** + * Shift the Hyperlink anchors (not the hyperlink text, even if the hyperlink + * is of type LINK_DOCUMENT and refers to a cell that was shifted). Hyperlinks + * do not track the content they point to. + * + * @param formulaShifter the formula shifting policy + */ + public abstract void updateHyperlinks(FormulaShifter formulaShifter); + +} diff --git a/src/java/org/apache/poi/ss/usermodel/helpers/RowShifter.java b/src/java/org/apache/poi/ss/usermodel/helpers/RowShifter.java index 19df59bd19..09566e4dcb 100644 --- a/src/java/org/apache/poi/ss/usermodel/helpers/RowShifter.java +++ b/src/java/org/apache/poi/ss/usermodel/helpers/RowShifter.java @@ -30,10 +30,12 @@ import org.apache.poi.util.Internal; /** * Helper for shifting rows up or down - * - * This abstract class exists to consolidate duplicated code between XSSFRowShifter and HSSFRowShifter (currently methods sprinkled throughout HSSFSheet) */ -public abstract class RowShifter { +// non-Javadoc: This abstract class exists to consolidate duplicated code between +// {@link org.apache.poi.hssf.usermodel.helpers.HSSFRowShifter} and +// {@link org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter} +// (currently methods sprinkled throughout HSSFSheet) +public abstract class RowShifter extends BaseRowColShifter { protected final Sheet sheet; public RowShifter(Sheet sh) { |