]> source.dussan.org Git - poi.git/commitdiff
improved XSSFSheet.shiftRows: 1. properly update cell references of the shifted cells...
authorYegor Kozlov <yegor@apache.org>
Sun, 8 Feb 2009 16:35:27 +0000 (16:35 +0000)
committerYegor Kozlov <yegor@apache.org>
Sun, 8 Feb 2009 16:35:27 +0000 (16:35 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@742126 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/changes.xml
src/documentation/content/xdocs/status.xml
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java
src/testcases/org/apache/poi/hssf/data/46536.xlsx [new file with mode: 0755]

index 9a22b181d39c7c553c8836f4317d1e5460aa3479..5908abf00cf0f35c760dcb09a5958c0dc0525141 100644 (file)
@@ -37,6 +37,8 @@
 
                <!-- Don't forget to update status.xml too! -->
         <release version="3.5-beta5" date="2008-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">46536 - When shifting rows, update formulas on that sheet to point to the new location of those rows</action>
+           <action dev="POI-DEVELOPERS" type="fix">46663 - Fixed XSSFSheet.shiftRows to properly update references of the shifted cells</action>
            <action dev="POI-DEVELOPERS" type="fix">46535 - Remove reference from calculation chain when a formula is deleted</action>
            <action dev="POI-DEVELOPERS" type="fix">46654 - HSSFRow/RowRecord to properly update cell boundary indexes</action>
            <action dev="POI-DEVELOPERS" type="fix">46643 - Fixed formula parser to encode range operator with tMemFunc</action>
index e44a128436d5b87a8ffb930f1ce5f547a133c499..4bb55ec3976af09831b606f8217f18b34cb47d8d 100644 (file)
@@ -34,6 +34,8 @@
        <!-- Don't forget to update changes.xml too! -->
     <changes>
         <release version="3.5-beta5" date="2008-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">46536 - When shifting rows, update formulas on that sheet to point to the new location of those rows</action>
+           <action dev="POI-DEVELOPERS" type="fix">46663 - Fixed XSSFSheet.shiftRows to properly update references of the shifted cells</action>
            <action dev="POI-DEVELOPERS" type="fix">46535 - Remove reference from calculation chain when a formula is deleted</action>
            <action dev="POI-DEVELOPERS" type="fix">46654 - HSSFRow/RowRecord to properly update cell boundary indexes</action>
            <action dev="POI-DEVELOPERS" type="fix">46643 - Fixed formula parser to encode range operator with tMemFunc</action>
index b7d2713f58115d97c8b452e2bec13424a1f991e8..26fb2dc8a51c314aa011ca62101c2d390d33ac4c 100644 (file)
@@ -826,17 +826,4 @@ public final class XSSFCell implements Cell {
         return cell;
     }
 
-    /**
-     * update cell reference when shifting rows
-     *
-     * @param row
-     */
-    protected void modifyCellReference(XSSFRow row) {
-        this.cell.setR(new CellReference(row.getRowNum(), cellNum).formatAsString());
-
-        CTCell[] ctCells = row.getCTRow().getCArray();
-        for (CTCell ctCell : ctCells) {
-            ctCell.setR(new CellReference(row.getRowNum(), cellNum).formatAsString());
-        }
-    }
 }
index 1011ecaf32a39453a4b01aae7a87ab7ab1873c92..88563ec268b887b243865ffefe014e8eaf55bfa1 100644 (file)
@@ -21,8 +21,16 @@ import java.util.*;
 
 import org.apache.poi.ss.usermodel.Cell;
 import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.ss.formula.FormulaParser;
+import org.apache.poi.ss.formula.FormulaType;
+import org.apache.poi.ss.formula.FormulaRenderer;
+import org.apache.poi.xssf.model.CalculationChain;
+import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.record.SharedFormulaRecord;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula;
 
 /**
  * High level representation of a row of a spreadsheet.
@@ -391,4 +399,61 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
     public String toString(){
         return row.toString();
     }
+
+    /**
+     * update cell references when shifting rows
+     *
+     * @param n the number of rows to move
+     */
+    protected void shift(int n) {
+        XSSFSheet sheet = getSheet();
+        CalculationChain calcChain = sheet.getWorkbook().getCalculationChain();
+        int rownum = getRowNum() + n;
+        for(Cell c : this){
+            XSSFCell cell = (XSSFCell)c;
+
+            //remove the reference in the calculation chain
+            if(calcChain != null) calcChain.removeItem((int)sheet.sheet.getSheetId(), cell.getReference());
+
+            CTCell ctCell = cell.getCTCell();
+            String r = new CellReference(rownum, cell.getColumnIndex()).formatAsString();
+            ctCell.setR(r);
+
+            if(ctCell.isSetF()){
+                CTCellFormula f = ctCell.getF();
+                String fmla = f.getStringValue();
+                if(fmla.length() > 0) {
+                    String shiftedFmla = shiftFormula(fmla, n);
+                    f.setStringValue(shiftedFmla);
+                }
+                if(f.isSetRef()){ //Range of cells which the formula applies to.
+                    String ref = f.getRef();
+                    String shiftedRef = shiftFormula(ref, n);
+                    f.setRef(shiftedRef);
+                }
+            }
+        }
+        setRowNum(rownum);
+    }
+
+    /**
+     * Shift a formula by the specified number of rows
+     * <p>
+     * Example: shiftFormula("A1+B1+C1", 3) will return "A4+B4+C4"
+     * </p>
+     *
+     * @param formula the formula to shift
+     * @param n the number of rows to shift
+     * @return the shifted formula
+     */
+    private String shiftFormula(String formula, int n){
+        XSSFSheet sheet = getSheet();
+        XSSFWorkbook wb = sheet.getWorkbook();
+        int sheetIndex = wb.getSheetIndex(sheet);
+        XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb);
+        Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex);
+        Ptg[] fmla = SharedFormulaRecord.convertSharedFormulas(ptgs, n, 0);
+        return FormulaRenderer.toFormulaString(fpb, fmla);
+    }
+
 }
index b1ed00935892956c2feaa83cf2fd669b7b860991..90f920c3e7ad093eaf53ac8d822cc0468deb2c9d 100644 (file)
@@ -24,14 +24,17 @@ import java.util.*;
 import javax.xml.namespace.QName;
 
 import org.apache.poi.hssf.util.PaneInformation;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.Footer;
-import org.apache.poi.ss.usermodel.Header;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.record.SharedFormulaRecord;
+import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.ss.util.AreaReference;
+import org.apache.poi.ss.formula.FormulaParser;
+import org.apache.poi.ss.formula.FormulaType;
+import org.apache.poi.ss.formula.FormulaRenderer;
 import org.apache.poi.xssf.model.CommentsTable;
+import org.apache.poi.xssf.model.CalculationChain;
 import org.apache.poi.xssf.usermodel.helpers.ColumnHelper;
 import org.apache.poi.POIXMLDocumentPart;
 import org.apache.poi.POIXMLException;
@@ -1438,7 +1441,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
      */
     public void shiftRows(int startRow, int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight) {
         for (Iterator<Row> it = rowIterator() ; it.hasNext() ; ) {
-            Row row = it.next();
+            XSSFRow row = (XSSFRow)it.next();
 
             if (!copyRowHeight) {
                 row.setHeight((short)-1);
@@ -1451,10 +1454,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
                 it.remove();
             }
             else if (row.getRowNum() >= startRow && row.getRowNum() <= endRow) {
-                row.setRowNum(row.getRowNum() + n);
-                if (row.getFirstCellNum() > -1) {
-                    modifyCellReference((XSSFRow) row);
-                }
+                row.shift(n);
             }
         }
         //rebuild the rows map
@@ -1463,16 +1463,6 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
         rows = map;
     }
 
-
-    private void modifyCellReference(XSSFRow row) {
-        for (int i = row.getFirstCellNum(); i <= row.getLastCellNum(); i++) {
-            XSSFCell c = row.getCell(i);
-            if (c != null) {
-                c.modifyCellReference(row);
-            }
-        }
-    }
-
     /**
      * Location of the top left visible cell Location of the top left visible cell in the bottom right
      * pane (when in Left-to-Right mode).
index 61a0b5e94d2d6fcd689ff613f4ca1ae20227d077..38ad08f64ed149444dece1a33ab2f57979de013b 100644 (file)
@@ -27,16 +27,11 @@ import org.apache.poi.ss.usermodel.Workbook;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.xssf.model.CommentsTable;
 import org.apache.poi.xssf.model.StylesTable;
+import org.apache.poi.xssf.model.CalculationChain;
 import org.apache.poi.xssf.usermodel.helpers.ColumnHelper;
 import org.apache.poi.xssf.XSSFTestDataSamples;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXf;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPane;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
 
 
 public class TestXSSFSheet extends TestCase {
@@ -608,7 +603,46 @@ public class TestXSSFSheet extends TestCase {
        assertNull(sheet6.getRow(7));
        assertEquals(8, sheet6.getPhysicalNumberOfRows());
     }
-    
+
+    /**
+     * When shifting rows, update formulas on that sheet to point to the new location of those rows
+     * (see bugzilla 46536)
+     */
+    public void testShiftRows_46536() {
+        XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("46536.xlsx");
+        CalculationChain calcChain = wb.getCalculationChain();
+        int numItems = calcChain.getCTCalcChain().getCArray().length;
+        assertEquals(3, numItems);
+
+        XSSFSheet sheet = wb.getSheet("Test");
+        XSSFRow row2 = sheet.getRow(1);
+        XSSFCell cell_A2 = row2.getCell(0);
+        assertEquals("A2", cell_A2.getReference());
+
+        XSSFRow row3 = sheet.getRow(2);
+        XSSFCell cell_B3 = row3.getCell(1);
+        assertEquals("B3", cell_B3.getReference());
+
+        XSSFCell cell_E2 = row2.getCell(4);
+        CTCellFormula f = cell_E2.getCTCell().getF();
+        assertEquals("B2+C2+D2", f.getStringValue());
+        assertEquals("E2:E3", f.getRef());
+
+        sheet.shiftRows(1, sheet.getLastRowNum(), 3, false, true);
+
+        assertEquals(4, row2.getRowNum());
+        assertEquals(5, row3.getRowNum());
+        assertEquals("A5", cell_A2.getReference());
+        assertEquals("B6", cell_B3.getReference());
+
+        assertEquals("B5+C5+D5", f.getStringValue());
+        assertEquals("E5:E6", f.getRef());
+
+        numItems = calcChain.getCTCalcChain().getCArray().length;
+        assertEquals(1, numItems);
+
+    }
+
     public void testGetCellComment() {
         XSSFWorkbook workbook = new XSSFWorkbook();
         XSSFSheet sheet = workbook.createSheet();
diff --git a/src/testcases/org/apache/poi/hssf/data/46536.xlsx b/src/testcases/org/apache/poi/hssf/data/46536.xlsx
new file mode 100755 (executable)
index 0000000..9b625bf
Binary files /dev/null and b/src/testcases/org/apache/poi/hssf/data/46536.xlsx differ