diff options
Diffstat (limited to 'src/java/org/apache/poi/ss/usermodel/helpers/ColumnShifter.java')
-rw-r--r-- | src/java/org/apache/poi/ss/usermodel/helpers/ColumnShifter.java | 136 |
1 files changed, 136 insertions, 0 deletions
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); + +} |