]> source.dussan.org Git - poi.git/commitdiff
Bug 58746: Fix missing adjustment of formulas when sheet-ordering is changed.
authorDominik Stadler <centic@apache.org>
Wed, 30 Dec 2015 20:31:44 +0000 (20:31 +0000)
committerDominik Stadler <centic@apache.org>
Wed, 30 Dec 2015 20:31:44 +0000 (20:31 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1722410 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/ss/formula/FormulaShifter.java
src/ooxml/testcases/org/apache/poi/xssf/eventusermodel/TestXSSFReader.java
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java
src/testcases/org/apache/poi/ss/formula/TestFormulaShifter.java

index a74cc51e49f24f56f10a854645c5988df3459d5d..1e79b1dfc9364103f81c43d9c4b4035e6d8d9b30 100644 (file)
@@ -283,18 +283,42 @@ public final class FormulaShifter {
 
 
     private Ptg adjustPtgDueToSheetMove(Ptg ptg) {
-        Ptg updatedPtg = null;
         if(ptg instanceof Ref3DPtg) {
             Ref3DPtg ref = (Ref3DPtg)ptg;
-            if(ref.getExternSheetIndex() == _srcSheetIndex){
+            int oldSheetIndex = ref.getExternSheetIndex();
+            
+            // we have to handle a few cases here
+            
+            // 1. sheet is outside moved sheets, no change necessary
+            if(oldSheetIndex < _srcSheetIndex &&
+                    oldSheetIndex < _dstSheetIndex) {
+                return null;
+            }
+            if(oldSheetIndex > _srcSheetIndex &&
+                    oldSheetIndex > _dstSheetIndex) {
+                return null;
+            }
+            
+            // 2. ptg refers to the moved sheet
+            if(oldSheetIndex == _srcSheetIndex) {
                 ref.setExternSheetIndex(_dstSheetIndex);
-                updatedPtg = ref;
-            } else if (ref.getExternSheetIndex() == _dstSheetIndex){
-                ref.setExternSheetIndex(_srcSheetIndex);
-                updatedPtg = ref;
+                return ref;
+            }
+
+            // 3. new index is lower than old one => sheets get moved up
+            if (_dstSheetIndex < _srcSheetIndex) {
+                ref.setExternSheetIndex(oldSheetIndex+1);
+                return ref;
+            }
+
+            // 4. new index is higher than old one => sheets get moved down
+            if (_dstSheetIndex > _srcSheetIndex) {
+                ref.setExternSheetIndex(oldSheetIndex-1);
+                return ref;
             }
         }
-        return updatedPtg;
+
+        return null;
     }
 
     private Ptg rowMoveRefPtg(RefPtgBase rptg) {
index 0eebf89ffb643e61403cb212718886de902c1c69..c67447377cf129b475b9e6fc0fd18b7b30b70c3c 100644 (file)
@@ -205,8 +205,10 @@ public final class TestXSSFReader extends TestCase {
    public void test58747() throws Exception {
        OPCPackage pkg =  XSSFTestDataSamples.openSamplePackage("58747.xlsx");
        ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(pkg);
+       assertNotNull(strings);
        XSSFReader reader = new XSSFReader(pkg);
        StylesTable styles = reader.getStylesTable();
+       assertNotNull(styles);
        
        XSSFReader.SheetIterator iter = (XSSFReader.SheetIterator) reader.getSheetsData();
        assertEquals(true, iter.hasNext());
index 8d64bf14f9258255d38eb248411ae72beb53391d..71436195a8f46ab3c4c2cab930ec3e14b32a27c7 100644 (file)
@@ -1193,4 +1193,33 @@ public final class TestHSSFSheet extends BaseTestSheet {
         assertNotNull(record);
         wb.close();
     }
+    
+    @Test
+    public void test58746() throws IOException {
+        HSSFWorkbook wb = new HSSFWorkbook();
+        
+        HSSFSheet first = wb.createSheet("first");
+        first.createRow(0).createCell(0).setCellValue(1);
+        
+        HSSFSheet second = wb.createSheet("second");
+        second.createRow(0).createCell(0).setCellValue(2);
+        
+        HSSFSheet third = wb.createSheet("third");
+        HSSFRow row = third.createRow(0);
+        row.createCell(0).setCellFormula("first!A1");
+        row.createCell(1).setCellFormula("second!A1");
+
+        // re-order for sheet "third"
+        wb.setSheetOrder("third", 0);
+        
+        // verify results
+        assertEquals("third", wb.getSheetAt(0).getSheetName());
+        assertEquals("first", wb.getSheetAt(1).getSheetName());
+        assertEquals("second", wb.getSheetAt(2).getSheetName());
+        
+        assertEquals("first!A1", wb.getSheetAt(0).getRow(0).getCell(0).getCellFormula());
+        assertEquals("second!A1", wb.getSheetAt(0).getRow(0).getCell(1).getCellFormula());
+        
+        wb.close();
+    }
 }
index c7e017ae097def197db48fa3548a9fbf52a1b94e..501df6a3477ff0ff4138abe4f5bbd966ee6b6c20 100644 (file)
 
 package org.apache.poi.ss.formula;
 
-import junit.framework.TestCase;
-
 import org.apache.poi.ss.SpreadsheetVersion;
 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.formula.ptg.Ref3DPtg;
+import org.apache.poi.ss.util.CellReference;
+
+import junit.framework.TestCase;
 
 /**
  * Tests for {@link FormulaShifter}.
@@ -196,4 +198,50 @@ public final class TestFormulaShifter extends TestCase {
        private static AreaPtg createAreaPtg(int initialAreaFirstRow, int initialAreaLastRow, boolean firstRowRelative, boolean lastRowRelative) {
                return new AreaPtg(initialAreaFirstRow, initialAreaLastRow, 2, 5, firstRowRelative, lastRowRelative, false, false);
        }
+
+       public void testShiftSheet() {
+           // 4 sheets, move a sheet from pos 2 to pos 0, i.e. current 0 becomes 1, current 1 becomes pos 2 
+        FormulaShifter shifter = FormulaShifter.createForSheetShift(2, 0);
+        
+        Ptg[] ptgs = new Ptg[] {
+          new Ref3DPtg(new CellReference("first", 0, 0, true, true), 0),
+          new Ref3DPtg(new CellReference("second", 0, 0, true, true), 1),
+          new Ref3DPtg(new CellReference("third", 0, 0, true, true), 2),
+          new Ref3DPtg(new CellReference("fourth", 0, 0, true, true), 3),
+        };
+        
+        shifter.adjustFormula(ptgs, -1);
+        
+        assertEquals("formula previously pointing to sheet 0 should now point to sheet 1", 
+                1, ((Ref3DPtg)ptgs[0]).getExternSheetIndex());
+        assertEquals("formula previously pointing to sheet 1 should now point to sheet 2", 
+                2, ((Ref3DPtg)ptgs[1]).getExternSheetIndex());
+        assertEquals("formula previously pointing to sheet 2 should now point to sheet 0", 
+                0, ((Ref3DPtg)ptgs[2]).getExternSheetIndex());
+        assertEquals("formula previously pointing to sheet 3 should be unchanged", 
+                3, ((Ref3DPtg)ptgs[3]).getExternSheetIndex());
+       }
+
+    public void testShiftSheet2() {
+        // 4 sheets, move a sheet from pos 1 to pos 2, i.e. current 2 becomes 1, current 1 becomes pos 2 
+        FormulaShifter shifter = FormulaShifter.createForSheetShift(1, 2);
+        
+        Ptg[] ptgs = new Ptg[] {
+          new Ref3DPtg(new CellReference("first", 0, 0, true, true), 0),
+          new Ref3DPtg(new CellReference("second", 0, 0, true, true), 1),
+          new Ref3DPtg(new CellReference("third", 0, 0, true, true), 2),
+          new Ref3DPtg(new CellReference("fourth", 0, 0, true, true), 3),
+        };
+
+        shifter.adjustFormula(ptgs, -1);
+        
+        assertEquals("formula previously pointing to sheet 0 should be unchanged", 
+                0, ((Ref3DPtg)ptgs[0]).getExternSheetIndex());
+        assertEquals("formula previously pointing to sheet 1 should now point to sheet 2", 
+                2, ((Ref3DPtg)ptgs[1]).getExternSheetIndex());
+        assertEquals("formula previously pointing to sheet 2 should now point to sheet 1", 
+                1, ((Ref3DPtg)ptgs[2]).getExternSheetIndex());
+        assertEquals("formula previously pointing to sheet 3 should be unchanged", 
+                3, ((Ref3DPtg)ptgs[3]).getExternSheetIndex());
+    }
 }