]> source.dussan.org Git - poi.git/commitdiff
bug 59731: start migrating methods relating to row-shifting in HSSFSheet to HSSFRowSh...
authorJaven O'Neal <onealj@apache.org>
Mon, 20 Jun 2016 04:16:32 +0000 (04:16 +0000)
committerJaven O'Neal <onealj@apache.org>
Mon, 20 Jun 2016 04:16:32 +0000 (04:16 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1749262 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
src/java/org/apache/poi/hssf/usermodel/helpers/HSSFRowShifter.java [new file with mode: 0644]
src/java/org/apache/poi/ss/usermodel/helpers/RowShifter.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java

index 9b10b70afdfc809a204ea98eb97114d7ed5a7c59..89b3c9e997de9212210c305739602c6ea3b0cec8 100644 (file)
@@ -50,6 +50,7 @@ import org.apache.poi.hssf.record.aggregates.DataValidityTable;
 import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
 import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
 import org.apache.poi.hssf.record.aggregates.WorksheetProtectionBlock;
+import org.apache.poi.hssf.usermodel.helpers.HSSFRowShifter;
 import org.apache.poi.hssf.util.PaneInformation;
 import org.apache.poi.ss.SpreadsheetVersion;
 import org.apache.poi.ss.formula.FormulaShifter;
@@ -64,6 +65,7 @@ import org.apache.poi.ss.usermodel.CellStyle;
 import org.apache.poi.ss.usermodel.DataValidation;
 import org.apache.poi.ss.usermodel.DataValidationHelper;
 import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.helpers.RowShifter;
 import org.apache.poi.ss.util.CellAddress;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.ss.util.CellRangeAddressList;
@@ -1485,50 +1487,11 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
      * @param endRow the end-index of the rows to shift, zero-based
      * @param n how far to shift, negative to shift up
      * @param isRow unused, kept for backwards compatibility
-     * @deprecated POI 3.15 beta 2. This will be made private in future releases.
+     * @deprecated POI 3.15 beta 2. Use {@link HSSFRowShifter#shiftMergedRegions(int, int, int)}.
      */
     protected void shiftMerged(int startRow, int endRow, int n, boolean isRow) {
-        shiftMerged(startRow, endRow, n);
-    }
-
-    /**
-     * Shifts, grows, or shrinks the merged regions due to a row shift
-     *  
-     * @param startRow the start-index of the rows to shift, zero-based
-     * @param endRow the end-index of the rows to shift, zero-based
-     * @param n how far to shift, negative to shift up
-     * This should be kept in sync with {@link org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter#shiftMerged(int, int, int)}
-     */
-    private void shiftMerged(int startRow, int endRow, int n) {
-        List<CellRangeAddress> shiftedRegions = new ArrayList<CellRangeAddress>();
-        //move merged regions completely if they fall within the new region boundaries when they are shifted
-        for (int i = 0; i < getNumMergedRegions(); i++) {
-            CellRangeAddress merged = getMergedRegion(i);
-
-            boolean inStart = (merged.getFirstRow() >= startRow || merged.getLastRow() >= startRow);
-            boolean inEnd = (merged.getFirstRow() <= endRow || merged.getLastRow() <= endRow);
-
-            //don't check if it's not within the shifted area
-            if (!inStart || !inEnd) {
-                continue;
-            }
-
-            //only shift if the region outside the shifted rows is not merged too
-            if (!merged.containsRow(startRow - 1) &&
-                    !merged.containsRow(endRow + 1)) {
-                merged.setFirstRow(merged.getFirstRow() + n);
-                merged.setLastRow(merged.getLastRow() + n);
-                //have to remove/add it back
-                shiftedRegions.add(merged);
-                removeMergedRegion(i);
-                i = i - 1; // we have to back up now since we removed one
-            }
-        }
-
-        //read so it doesn't get shifted again
-        for (CellRangeAddress region : shiftedRegions) {
-            this.addMergedRegion(region);
-        }
+        RowShifter rowShifter = new HSSFRowShifter(this);
+        rowShifter.shiftMergedRegions(startRow, endRow, n);
     }
 
     /**
@@ -1607,6 +1570,8 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
             // Nothing to do
             return;
         }
+        
+        RowShifter rowShifter = new HSSFRowShifter(this);
 
         // Shift comments
         if (moveComments) {
@@ -1614,7 +1579,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
         }
 
         // Shift Merged Regions
-        shiftMerged(startRow, endRow, n);
+        rowShifter.shiftMergedRegions(startRow, endRow, n);
         
         // Shift Row Breaks
         _sheet.getPageSettings().shiftRowBreaks(startRow, endRow, n);
diff --git a/src/java/org/apache/poi/hssf/usermodel/helpers/HSSFRowShifter.java b/src/java/org/apache/poi/hssf/usermodel/helpers/HSSFRowShifter.java
new file mode 100644 (file)
index 0000000..88a6f9b
--- /dev/null
@@ -0,0 +1,68 @@
+/* ====================================================================
+   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.Row;
+import org.apache.poi.ss.usermodel.helpers.RowShifter;
+import org.apache.poi.util.Internal;
+import org.apache.poi.util.NotImplemented;
+import org.apache.poi.util.POILogFactory;
+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}
+ */
+public final class HSSFRowShifter extends RowShifter {
+    private static final POILogger logger = POILogFactory.getLogger(HSSFRowShifter.class);
+
+    public HSSFRowShifter(HSSFSheet sh) {
+        super(sh);
+    }
+
+    @NotImplemented
+    public void updateNamedRanges(FormulaShifter shifter) {
+        throw new NotImplementedException("HSSFRowShifter.updateNamedRanges");
+    }
+
+    @NotImplemented
+    public void updateFormulas(FormulaShifter shifter) {
+        throw new NotImplementedException("updateFormulas");
+    }
+
+    @Internal
+    @NotImplemented
+    public void updateRowFormulas(Row row, FormulaShifter shifter) {
+        throw new NotImplementedException("updateRowFormulas");
+    }
+
+    @NotImplemented
+    public void updateConditionalFormatting(FormulaShifter shifter) {
+        throw new NotImplementedException("updateConditionalFormatting");
+    }
+    
+    @NotImplemented
+    public void updateHyperlinks(FormulaShifter shifter) {
+        throw new NotImplementedException("updateHyperlinks");
+    }
+
+}
diff --git a/src/java/org/apache/poi/ss/usermodel/helpers/RowShifter.java b/src/java/org/apache/poi/ss/usermodel/helpers/RowShifter.java
new file mode 100644 (file)
index 0000000..a168080
--- /dev/null
@@ -0,0 +1,121 @@
+/* ====================================================================
+   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.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+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;
+
+/**
+ * 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 {
+    private static final POILogger logger = POILogFactory.getLogger(RowShifter.class);
+    protected final Sheet sheet;
+
+    public RowShifter(Sheet sh) {
+        sheet = sh;
+    }
+
+    /**
+     * Shifts, grows, or shrinks the merged regions due to a row shift
+     *
+     * @param startRow the row to start shifting
+     * @param endRow   the row to end shifting
+     * @param n        the number of rows to shift
+     * @return an array of affected merged regions
+     */
+    public List<CellRangeAddress> shiftMergedRegions(int startRow, int endRow, int n) {
+        List<CellRangeAddress> shiftedRegions = new ArrayList<CellRangeAddress>();
+        Set<Integer> removedIndices = new HashSet<Integer>();
+        //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);
+
+            boolean inStart = (merged.getFirstRow() >= startRow || merged.getLastRow() >= startRow);
+            boolean inEnd = (merged.getFirstRow() <= endRow || merged.getLastRow() <= endRow);
+
+            //don't check if it's not within the shifted area
+            if (!inStart || !inEnd) {
+                continue;
+            }
+
+            //only shift if the region outside the shifted rows is not merged too
+            if (!merged.containsRow(startRow - 1) && !merged.containsRow(endRow + 1)) {
+                merged.setFirstRow(merged.getFirstRow() + n);
+                merged.setLastRow(merged.getLastRow() + 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;
+    }
+
+    /**
+     * Updated named ranges
+     */
+    public abstract void updateNamedRanges(FormulaShifter shifter);
+
+    /**
+     * Update formulas.
+     */
+    public abstract void updateFormulas(FormulaShifter shifter);
+
+    /**
+     * Update the formulas in specified row using the formula shifting policy specified by shifter
+     *
+     * @param row the row to update the formulas on
+     * @param shifter the formula shifting policy
+     */
+    @Internal
+    public abstract void updateRowFormulas(Row row, FormulaShifter shifter);
+
+    public abstract void updateConditionalFormatting(FormulaShifter shifter);
+    
+    /**
+     * 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 shifter
+     */
+    public abstract void updateHyperlinks(FormulaShifter shifter);
+
+}
index f8be5b0efb9d82e7c30d57840e9424204f220029..8df7b42a6e2f0a9e0ec1570315069af116d425e8 100644 (file)
@@ -3042,7 +3042,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
 
         rowShifter.updateNamedRanges(shifter);
         rowShifter.updateFormulas(shifter);
-        rowShifter.shiftMerged(startRow, endRow, n);
+        rowShifter.shiftMergedRegions(startRow, endRow, n);
         rowShifter.updateConditionalFormatting(shifter);
         rowShifter.updateHyperlinks(shifter);
 
index 923af2a63fe9d9dd71b4d973bd3286d184252f93..6f6d06d3c5aee60cdd54d5a4d4b7e99848a43ef5 100644 (file)
@@ -31,8 +31,12 @@ 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;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.helpers.RowShifter;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.util.Internal;
 import org.apache.poi.util.POILogFactory;
@@ -40,7 +44,6 @@ 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.XSSFName;
 import org.apache.poi.xssf.usermodel.XSSFRow;
 import org.apache.poi.xssf.usermodel.XSSFSheet;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
@@ -53,87 +56,37 @@ 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}
  */
-public final class XSSFRowShifter {
-    private static POILogger logger = POILogFactory.getLogger(XSSFRowShifter.class);
-    private final XSSFSheet sheet;
+public final class XSSFRowShifter extends RowShifter {
+    private static final POILogger logger = POILogFactory.getLogger(XSSFRowShifter.class);
 
     public XSSFRowShifter(XSSFSheet sh) {
-        sheet = sh;
+        super(sh);
     }
-
+    
     /**
      * Shift merged regions
-     *
+     * 
      * @param startRow the row to start shifting
      * @param endRow   the row to end shifting
      * @param n        the number of rows to shift
-     * @return an array of affected cell regions
-     * 
-     * This should be kept in sync with {@link org.apache.poi.hssf.usermodel.HSSFSheet#shiftMerged(int, int, int)}
+     * @return an array of merged cell regions
+     * @deprecated POI 3.15 beta 2. Use {@link #shiftMergedRegions(int, int, int)} instead.
      */
     public List<CellRangeAddress> shiftMerged(int startRow, int endRow, int n) {
-        List<CellRangeAddress> shiftedRegions = new ArrayList<CellRangeAddress>();
-        Set<Integer> removedIndices = new HashSet<Integer>();
-        //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);
-
-            boolean inStart = (merged.getFirstRow() >= startRow || merged.getLastRow() >= startRow);
-            boolean inEnd = (merged.getFirstRow() <= endRow || merged.getLastRow() <= endRow);
-
-            //don't check if it's not within the shifted area
-            if (!inStart || !inEnd) {
-                continue;
-            }
-
-            //only shift if the region outside the shifted rows is not merged too
-            if (!merged.containsRow(startRow - 1) && !merged.containsRow(endRow + 1)) {
-                merged.setFirstRow(merged.getFirstRow() + n);
-                merged.setLastRow(merged.getLastRow() + 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;
-    }
-
-    /**
-     * Check if the  row and column are in the specified cell range
-     *
-     * @param cr    the cell range to check in
-     * @param rowIx the row to check
-     * @param colIx the column to check
-     * @return true if the range contains the cell [rowIx,colIx]
-     */
-    private static boolean containsCell(CellRangeAddress cr, int rowIx, int colIx) {
-        if (cr.getFirstRow() <= rowIx && cr.getLastRow() >= rowIx
-                && cr.getFirstColumn() <= colIx && cr.getLastColumn() >= colIx) {
-            return true;
-        }
-        return false;
+        return shiftMergedRegions(startRow, endRow, n);
     }
 
     /**
      * Updated named ranges
      */
-    @SuppressWarnings("resource")
     public void updateNamedRanges(FormulaShifter shifter) {
-        XSSFWorkbook wb = sheet.getWorkbook();
-        XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb);
+        Workbook wb = sheet.getWorkbook();
+        XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create((XSSFWorkbook) wb);
         for (int i = 0; i < wb.getNumberOfNames(); i++) {
-            XSSFName name = wb.getNameAt(i);
+            Name name = wb.getNameAt(i);
             String formula = name.getRefersToFormula();
             int sheetIndex = name.getSheetIndex();
             final int rowIndex = -1; //don't care, named ranges are not allowed to include structured references
@@ -149,13 +102,12 @@ public final class XSSFRowShifter {
     /**
      * Update formulas.
      */
-    @SuppressWarnings("resource")
     public void updateFormulas(FormulaShifter shifter) {
         //update formulas on the parent sheet
         updateSheetFormulas(sheet, shifter);
 
         //update formulas on other sheets
-        XSSFWorkbook wb = sheet.getWorkbook();
+        Workbook wb = sheet.getWorkbook();
         for (Sheet sh : wb) {
             if (sheet == sh) continue;
             updateSheetFormulas(sh, shifter);
@@ -176,7 +128,8 @@ public final class XSSFRowShifter {
      * @param shifter the formula shifting policy
      */
     @Internal
-    public void updateRowFormulas(XSSFRow row, FormulaShifter shifter) {
+    public void updateRowFormulas(Row row, FormulaShifter shifter) {
+        XSSFSheet sheet = (XSSFSheet) row.getSheet();
         for (Cell c : row) {
             XSSFCell cell = (XSSFCell) c;
 
@@ -190,7 +143,7 @@ public final class XSSFRowShifter {
                         f.setStringValue(shiftedFormula);
                         if(f.getT() == STCellFormulaType.SHARED){
                             int si = (int)f.getSi();
-                            CTCellFormula sf = row.getSheet().getSharedFormula(si);
+                            CTCellFormula sf = sheet.getSharedFormula(si);
                             sf.setStringValue(shiftedFormula);
                         }
                     }
@@ -216,13 +169,12 @@ public final class XSSFRowShifter {
      * @return the shifted formula if the formula was changed,
      *         <code>null</code> if the formula wasn't modified
      */
-    @SuppressWarnings("resource")
-    private static String shiftFormula(XSSFRow row, String formula, FormulaShifter shifter) {
-        XSSFSheet sheet = row.getSheet();
-        XSSFWorkbook wb = sheet.getWorkbook();
+    private static String shiftFormula(Row row, String formula, FormulaShifter shifter) {
+        Sheet sheet = row.getSheet();
+        Workbook wb = sheet.getWorkbook();
         int sheetIndex = wb.getSheetIndex(sheet);
         final int rowIndex = row.getRowNum();
-        XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb);
+        XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create((XSSFWorkbook) wb);
         
         try {
             Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex, rowIndex);
@@ -238,14 +190,14 @@ public final class XSSFRowShifter {
         }
     }
 
-    @SuppressWarnings("resource")
     public void updateConditionalFormatting(FormulaShifter shifter) {
-        XSSFWorkbook wb = sheet.getWorkbook();
+        XSSFSheet xsheet = (XSSFSheet) sheet;
+        XSSFWorkbook wb = xsheet.getWorkbook();
         int sheetIndex = wb.getSheetIndex(sheet);
         final int rowIndex = -1; //don't care, structured references not allowed in conditional formatting
 
         XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb);
-        CTWorksheet ctWorksheet = sheet.getCTWorksheet();
+        CTWorksheet ctWorksheet = xsheet.getCTWorksheet();
         CTConditionalFormatting[] conditionalFormattingArray = ctWorksheet.getConditionalFormattingArray();
         // iterate backwards due to possible calls to ctWorksheet.removeConditionalFormatting(j)
         for (int j = conditionalFormattingArray.length - 1; j >= 0; j--) {
@@ -307,17 +259,18 @@ public final class XSSFRowShifter {
      */
     public void updateHyperlinks(FormulaShifter shifter) {
         int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet);
-        List<XSSFHyperlink> hyperlinkList = sheet.getHyperlinkList();
+        List<? extends Hyperlink> hyperlinkList = sheet.getHyperlinkList();
         
-        for (XSSFHyperlink hyperlink : hyperlinkList) {
-            String cellRef = hyperlink.getCellRef();
+        for (Hyperlink hyperlink : hyperlinkList) {
+            XSSFHyperlink xhyperlink = (XSSFHyperlink) hyperlink;
+            String cellRef = xhyperlink.getCellRef();
             CellRangeAddress cra = CellRangeAddress.valueOf(cellRef);
             CellRangeAddress shiftedRange = shiftRange(shifter, 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
-                hyperlink.setCellReference(shiftedRange.formatAsString());
+                xhyperlink.setCellReference(shiftedRange.formatAsString());
             }
         }
     }