]> source.dussan.org Git - poi.git/commitdiff
bug 61474, github #81: add ColumnShifter interface; deduplicate some code in RowShift...
authorJaven O'Neal <onealj@apache.org>
Sat, 4 Nov 2017 07:17:44 +0000 (07:17 +0000)
committerJaven O'Neal <onealj@apache.org>
Sat, 4 Nov 2017 07:17:44 +0000 (07:17 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1814256 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java
src/java/org/apache/poi/hssf/usermodel/helpers/HSSFColumnShifter.java [new file with mode: 0644]
src/java/org/apache/poi/hssf/usermodel/helpers/HSSFRowShifter.java
src/java/org/apache/poi/ss/usermodel/helpers/BaseRowColShifter.java [new file with mode: 0644]
src/java/org/apache/poi/ss/usermodel/helpers/ColumnShifter.java [new file with mode: 0644]
src/java/org/apache/poi/ss/usermodel/helpers/RowShifter.java
src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFColumnShifter.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowColShifter.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java

index 87cb834633c5be6729ee7c4724815764cc371cf3..afd69c48a20f950ebce7322a0fabdf48d0b28168 100644 (file)
@@ -29,9 +29,8 @@ import org.apache.poi.hssf.record.CFRuleBase;
 import org.apache.poi.hssf.record.CFRuleRecord;
 import org.apache.poi.hssf.record.Record;
 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.usermodel.helpers.BaseRowColShifter;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
@@ -223,7 +222,7 @@ public final class CFRecordsAggregate extends RecordAggregate {
         boolean changed = false;
         List<CellRangeAddress> temp = new ArrayList<>();
         for (CellRangeAddress craOld : cellRanges) {
-            CellRangeAddress craNew = shiftRange(shifter, craOld, currentExternSheetIx);
+            CellRangeAddress craNew = BaseRowColShifter.shiftRange(shifter, craOld, currentExternSheetIx);
             if (craNew == null) {
                 changed = true;
                 continue;
@@ -264,23 +263,4 @@ public final class CFRecordsAggregate extends RecordAggregate {
         }
         return true;
     }
-
-    private static CellRangeAddress shiftRange(FormulaShifter shifter, 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 (!shifter.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/hssf/usermodel/helpers/HSSFColumnShifter.java b/src/java/org/apache/poi/hssf/usermodel/helpers/HSSFColumnShifter.java
new file mode 100644 (file)
index 0000000..051e24a
--- /dev/null
@@ -0,0 +1,66 @@
+/* ====================================================================
+   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.hssf.usermodel.helpers;
+
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.ss.formula.FormulaShifter;
+import org.apache.poi.ss.formula.eval.NotImplementedException;
+import org.apache.poi.ss.usermodel.helpers.ColumnShifter;
+import org.apache.poi.util.Beta;
+import org.apache.poi.util.NotImplemented;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+
+/**
+ * Helper for shifting columns up or down
+ */
+// non-Javadoc: When possible, code should be implemented in the ColumnShifter abstract class to avoid duplication with
+// {@link org.apache.poi.xssf.usermodel.helpers.XSSFColumnShifter}
+@Beta
+public final class HSSFColumnShifter extends ColumnShifter {
+    private static final POILogger logger = POILogFactory.getLogger(HSSFColumnShifter.class);
+
+    public HSSFColumnShifter(HSSFSheet sh) {
+        super(sh);
+    }
+
+    @Override
+    @NotImplemented
+    public void updateNamedRanges(FormulaShifter formulaShifter) {
+        throw new NotImplementedException("HSSFColumnShifter.updateNamedRanges");
+    }
+
+    @Override
+    @NotImplemented
+    public void updateFormulas(FormulaShifter formulaShifter) {
+        throw new NotImplementedException("updateFormulas");
+    }
+
+    @Override
+    @NotImplemented
+    public void updateConditionalFormatting(FormulaShifter formulaShifter) {
+        throw new NotImplementedException("updateConditionalFormatting");
+    }
+
+    @Override
+    @NotImplemented
+    public void updateHyperlinks(FormulaShifter formulaShifter) {
+        throw new NotImplementedException("updateHyperlinks");
+    }
+
+}
index 1c57e5b1dc2428d50e8a38abb8cd6d28c64dfcc3..0e8a5b43ae7ad0ca4700c4683f85fb333c12f8f4 100644 (file)
@@ -29,9 +29,9 @@ import org.apache.poi.util.POILogger;
 
 /**
  * Helper for shifting rows up or down
- * 
- * When possible, code should be implemented in the RowShifter abstract class to avoid duplication with {@link org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter}
  */
+// non-Javadoc: When possible, code should be implemented in the RowShifter abstract class to avoid duplication with
+// {@link org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter}
 public final class HSSFRowShifter extends RowShifter {
     private static final POILogger logger = POILogFactory.getLogger(HSSFRowShifter.class);
 
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 (file)
index 0000000..306e515
--- /dev/null
@@ -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 (file)
index 0000000..7769f30
--- /dev/null
@@ -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);
+
+}
index 19df59bd190f386e4f9f4dd16984bb436484f30b..09566e4dcb4166c2ac0ddd300dff398791558559 100644 (file)
@@ -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) {
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFColumnShifter.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFColumnShifter.java
new file mode 100644 (file)
index 0000000..de51707
--- /dev/null
@@ -0,0 +1,83 @@
+/* ====================================================================
+   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.xssf.usermodel.helpers;
+
+import org.apache.poi.ss.formula.*;
+import org.apache.poi.ss.formula.eval.NotImplementedException;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.usermodel.helpers.ColumnShifter;
+import org.apache.poi.util.Beta;
+import org.apache.poi.util.NotImplemented;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+import org.apache.poi.xssf.usermodel.*;
+
+/**
+ * Helper for shifting columns up or down
+ */
+// non-Javadoc: When possible, code should be implemented in the ColumnShifter abstract class to avoid duplication with
+// {@link org.apache.poi.hssf.usermodel.helpers.HSSFColumnShifter}
+@Beta
+public final class XSSFColumnShifter extends ColumnShifter {
+    private static final POILogger logger = POILogFactory.getLogger(XSSFColumnShifter.class);
+
+    public XSSFColumnShifter(XSSFSheet sh) {
+        super(sh);
+    }
+
+    /**
+     * Updated named ranges
+     */
+    @NotImplemented
+    @Override
+    public void updateNamedRanges(FormulaShifter formulaShifter) {
+        throw new NotImplementedException("updateNamedRanges");
+    }
+
+    /**
+     * Update formulas.
+     */
+    @NotImplemented
+    @Override
+    public void updateFormulas(FormulaShifter formulaShifter) {
+        throw new NotImplementedException("updateFormulas");
+    }
+
+    private void updateSheetFormulas(Sheet sh, FormulaShifter formulaShifter) {
+        throw new NotImplementedException("updateSheetFormulas");
+    }
+
+    @NotImplemented
+    @Override
+    public void updateConditionalFormatting(FormulaShifter formulaShifter) {
+        throw new NotImplementedException("updateConditionalformatting");
+    }
+    
+    /**
+     * 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
+     */
+    @Override
+    public void updateHyperlinks(FormulaShifter formulaShifter) {
+        XSSFRowColShifter.updateHyperlinks(sheet, formulaShifter);
+    }
+
+}
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowColShifter.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowColShifter.java
new file mode 100644 (file)
index 0000000..ef450a1
--- /dev/null
@@ -0,0 +1,59 @@
+/* ====================================================================
+   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.xssf.usermodel.helpers;
+
+import org.apache.poi.ss.formula.*;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.usermodel.helpers.BaseRowColShifter;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.util.Internal;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+import org.apache.poi.xssf.usermodel.*;
+
+import java.util.List;
+
+/**
+ * Class for code common to {@link XSSFRowShifter} and {@link XSSFColumnShifter}
+ */
+@Internal
+/*private*/ final class XSSFRowColShifter extends BaseRowColShifter {
+    private static final POILogger logger = POILogFactory.getLogger(XSSFRowColShifter.class);
+
+    private XSSFRowColShifter() { /*no instances for static classes*/}
+
+    /*package*/ static void updateHyperlinks(Sheet sheet, FormulaShifter formulaShifter) {
+        int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet);
+        List<? extends Hyperlink> hyperlinkList = sheet.getHyperlinkList();
+
+        for (Hyperlink hyperlink : hyperlinkList) {
+            XSSFHyperlink xhyperlink = (XSSFHyperlink) hyperlink;
+            String cellRef = xhyperlink.getCellRef();
+            CellRangeAddress cra = CellRangeAddress.valueOf(cellRef);
+            CellRangeAddress shiftedRange = shiftRange(formulaShifter, cra, sheetIndex);
+            if (shiftedRange != null && shiftedRange != cra) {
+                // shiftedRange should not be null. If shiftedRange is null, that means
+                // that a hyperlink wasn't deleted at the beginning of shiftRows when
+                // identifying rows that should be removed because they will be overwritten
+                xhyperlink.setCellReference(shiftedRange.formatAsString());
+            }
+        }
+    }
+
+
+}
index 04257917d8ca9629a43bdb4c6e1d170c8ba70f15..7ef0b3f4752358c91d91acd868bfd7742e8a8ee3 100644 (file)
@@ -25,11 +25,8 @@ import org.apache.poi.ss.formula.FormulaParser;
 import org.apache.poi.ss.formula.FormulaRenderer;
 import org.apache.poi.ss.formula.FormulaShifter;
 import org.apache.poi.ss.formula.FormulaType;
-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.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Hyperlink;
 import org.apache.poi.ss.usermodel.Name;
 import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
@@ -41,7 +38,6 @@ import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
 import org.apache.poi.xssf.usermodel.XSSFCell;
 import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook;
-import org.apache.poi.xssf.usermodel.XSSFHyperlink;
 import org.apache.poi.xssf.usermodel.XSSFRow;
 import org.apache.poi.xssf.usermodel.XSSFSheet;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
@@ -54,9 +50,9 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType;
 
 /**
  * Helper for shifting rows up or down
- * 
- * When possible, code should be implemented in the RowShifter abstract class to avoid duplication with {@link org.apache.poi.hssf.usermodel.helpers.HSSFRowShifter}
  */
+// non-Javadoc: When possible, code should be implemented in the RowShifter abstract class to avoid duplication with
+// {@link org.apache.poi.hssf.usermodel.helpers.HSSFRowShifter}
 public final class XSSFRowShifter extends RowShifter {
     private static final POILogger logger = POILogFactory.getLogger(XSSFRowShifter.class);
 
@@ -253,40 +249,8 @@ public final class XSSFRowShifter extends RowShifter {
      */
     @Override
     public void updateHyperlinks(FormulaShifter formulaShifter) {
-        int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet);
-        List<? extends Hyperlink> hyperlinkList = sheet.getHyperlinkList();
-        
-        for (Hyperlink hyperlink : hyperlinkList) {
-            XSSFHyperlink xhyperlink = (XSSFHyperlink) hyperlink;
-            String cellRef = xhyperlink.getCellRef();
-            CellRangeAddress cra = CellRangeAddress.valueOf(cellRef);
-            CellRangeAddress shiftedRange = shiftRange(formulaShifter, cra, sheetIndex);
-            if (shiftedRange != null && shiftedRange != cra) {
-                // shiftedRange should not be null. If shiftedRange is null, that means
-                // that a hyperlink wasn't deleted at the beginning of shiftRows when
-                // identifying rows that should be removed because they will be overwritten
-                xhyperlink.setCellReference(shiftedRange.formatAsString());
-            }
-        }
+        XSSFRowColShifter.updateHyperlinks(sheet, formulaShifter);
     }
 
-    private 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() + ")");
-    }
 
 }