You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by jo...@apache.org on 2008/09/16 22:17:31 UTC

svn commit: r696038 - in /poi/trunk/src: documentation/content/xdocs/ java/org/apache/poi/hssf/model/ java/org/apache/poi/hssf/record/ java/org/apache/poi/hssf/record/aggregates/ java/org/apache/poi/hssf/record/formula/ java/org/apache/poi/hssf/usermod...

Author: josh
Date: Tue Sep 16 13:17:30 2008
New Revision: 696038

URL: http://svn.apache.org/viewvc?rev=696038&view=rev
Log:
Fix for bug 45780 - update area refs during HSSFSheet.shiftRows()

Added:
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/ExternSheetNameResolver.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/FormulaShifter.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ref2DPtgBase.java
    poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/TestFormulaShifter.java
Modified:
    poi/trunk/src/documentation/content/xdocs/changes.xml
    poi/trunk/src/documentation/content/xdocs/status.xml
    poi/trunk/src/java/org/apache/poi/hssf/model/Sheet.java
    poi/trunk/src/java/org/apache/poi/hssf/record/NameRecord.java
    poi/trunk/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java
    poi/trunk/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/AreaErrPtg.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/DeletedArea3DPtg.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/DeletedRef3DPtg.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefErrorPtg.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefNPtg.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefPtg.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFName.java
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
    poi/trunk/src/testcases/org/apache/poi/hssf/data/ForShifting.xls
    poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/AllFormulaTests.java
    poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestFormulas.java
    poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestNamedRange.java
    poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestSheetShiftRows.java

Modified: poi/trunk/src/documentation/content/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/poi/trunk/src/documentation/content/xdocs/changes.xml?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/documentation/content/xdocs/changes.xml (original)
+++ poi/trunk/src/documentation/content/xdocs/changes.xml Tue Sep 16 13:17:30 2008
@@ -37,6 +37,7 @@
 
 		<!-- Don't forget to update status.xml too! -->
         <release version="3.2-alpha1" date="2008-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">45780 - Fixed HSSFSheet.shiftRows to also update Area refs</action>
            <action dev="POI-DEVELOPERS" type="fix">45804 - Update HSMF to handle Outlook 3.0 msg files, which have a different string chunk type</action>
            <action dev="POI-DEVELOPERS" type="add">Expose the name of Named Cell Styles via HSSFCellStyle (normally held on the parent style though)</action>
            <action dev="POI-DEVELOPERS" type="fix">45978 - Fixed IOOBE in Ref3DPtg.toFormulaString() due eager initialisation of SheetReferences</action>

Modified: poi/trunk/src/documentation/content/xdocs/status.xml
URL: http://svn.apache.org/viewvc/poi/trunk/src/documentation/content/xdocs/status.xml?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/documentation/content/xdocs/status.xml (original)
+++ poi/trunk/src/documentation/content/xdocs/status.xml Tue Sep 16 13:17:30 2008
@@ -34,6 +34,7 @@
 	<!-- Don't forget to update changes.xml too! -->
     <changes>
         <release version="3.2-alpha1" date="2008-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">45780 - Fixed HSSFSheet.shiftRows to also update Area refs</action>
            <action dev="POI-DEVELOPERS" type="fix">45804 - Update HSMF to handle Outlook 3.0 msg files, which have a different string chunk type</action>
            <action dev="POI-DEVELOPERS" type="add">Expose the name of Named Cell Styles via HSSFCellStyle (normally held on the parent style though)</action>
            <action dev="POI-DEVELOPERS" type="fix">45978 - Fixed IOOBE in Ref3DPtg.toFormulaString() due eager initialisation of SheetReferences</action>

Modified: poi/trunk/src/java/org/apache/poi/hssf/model/Sheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/model/Sheet.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/model/Sheet.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/model/Sheet.java Tue Sep 16 13:17:30 2008
@@ -62,7 +62,6 @@
 import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
 import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable;
 import org.apache.poi.hssf.record.aggregates.DataValidityTable;
-import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
 import org.apache.poi.hssf.record.aggregates.MergedCellsTable;
 import org.apache.poi.hssf.record.aggregates.PageSettingsBlock;
 import org.apache.poi.hssf.record.aggregates.RecordAggregate;
@@ -127,7 +126,8 @@
     /*package*/ColumnInfoRecordsAggregate _columnInfos;
     /** the DimensionsRecord is always present */
     private DimensionsRecord             _dimensions;
-    protected RowRecordsAggregate        _rowsAggregate              =     null;
+    /** always present */
+    protected RowRecordsAggregate        _rowsAggregate;
     private   DataValidityTable          _dataValidityTable=     null;
     private   ConditionalFormattingTable condFormatting;
 
@@ -329,10 +329,13 @@
         if (retval.windowTwo == null) {
             throw new RuntimeException("WINDOW2 was not found");
         }
+        if (retval._rowsAggregate == null) {
+        	retval._rowsAggregate = new RowRecordsAggregate();
+            records.add(retval.dimsloc + 1, retval._rowsAggregate);
+        }
         // put merged cells table in the right place (regardless of where the first MergedCellsRecord was found */
         RecordOrderer.addNewSheetRecord(records, retval._mergedCellsTable);
         retval.records = records;
-        retval.checkRows();
         if (log.check( POILogger.DEBUG ))
             log.log(POILogger.DEBUG, "sheet createSheet (existing file) exited");
         return retval;
@@ -441,6 +444,8 @@
         retval._dimensions = createDimensions();
         records.add(retval._dimensions);
         retval.dimsloc = records.size()-1;
+        retval._rowsAggregate = new RowRecordsAggregate();
+        records.add(retval._rowsAggregate);
         // 'Sheet View Settings'
         records.add(retval.windowTwo = retval.createWindowTwo());
         retval.selection = createSelection();
@@ -456,14 +461,10 @@
         return retval;
     }
 
-    private void checkRows()
-    {
-        if (_rowsAggregate == null)
-        {
-            _rowsAggregate = new RowRecordsAggregate();
-            records.add(dimsloc + 1, _rowsAggregate);
-        }
+    public RowRecordsAggregate getRowsAggregate() {
+    	return _rowsAggregate;
     }
+
     private MergedCellsTable getMergedRecords() {
         // always present
         return _mergedCellsTable;
@@ -624,13 +625,6 @@
     }
 
     /**
-     * Create a row record.  (does not add it to the records contained in this sheet)
-     */
-    private static RowRecord createRow(int row) {
-        return RowRecordsAggregate.createRow( row );
-    }
-
-    /**
      * Adds a value record to the sheet's contained binary records
      * (i.e. LabelSSTRecord or NumberRecord).
      * <P>
@@ -714,7 +708,6 @@
 
     public void addRow(RowRecord row)
     {
-        checkRows();
         if (log.check( POILogger.DEBUG ))
             log.log(POILogger.DEBUG, "addRow ");
         DimensionsRecord d = _dimensions;
@@ -748,7 +741,6 @@
      * @param row  the row record to remove
      */
     public void removeRow(RowRecord row) {
-        checkRows();
         _rowsAggregate.removeRow(row);
     }
 
@@ -1295,7 +1287,7 @@
     }
 
     /**
-     * Returns the first occurance of a record matching a particular sid.
+     * Returns the first occurrence of a record matching a particular sid.
      */
 
     public Record findFirstRecordBySid(short sid)
@@ -1781,13 +1773,12 @@
 
     public void groupRowRange(int fromRow, int toRow, boolean indent)
     {
-        checkRows();
         for (int rowNum = fromRow; rowNum <= toRow; rowNum++)
         {
             RowRecord row = getRow( rowNum );
             if (row == null)
             {
-                row = createRow( rowNum );
+                row = RowRecordsAggregate.createRow(rowNum);
                 addRow( row );
             }
             int level = row.getOutlineLevel();
@@ -1817,17 +1808,6 @@
         guts.setLeftRowGutter( (short) ( 29 + (12 * (maxLevel)) ) );
     }
 
-    public void setRowGroupCollapsed( int row, boolean collapse )
-    {
-        if (collapse)
-        {
-            _rowsAggregate.collapseRow( row );
-        }
-        else
-        {
-            _rowsAggregate.expandRow( row );
-        }
-    }
     public DataValidityTable getOrCreateDataValidityTable() {
         if (_dataValidityTable == null) {
             DataValidityTable result = new DataValidityTable();
@@ -1836,8 +1816,4 @@
         }
         return _dataValidityTable;
     }
-
-    public FormulaRecordAggregate createFormula(int row, int col) {
-        return _rowsAggregate.createFormula(row, col);
-    }
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/NameRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/NameRecord.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/NameRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/NameRecord.java Tue Sep 16 13:17:30 2008
@@ -537,9 +537,7 @@
 				temp.add(ptg);
 			}
 		} else {
-			Ptg ptg = new Ref3DPtg();
-			((Ref3DPtg) ptg).setExternSheetIndex(externSheetIndex);
-			((Ref3DPtg) ptg).setArea(ref);
+			Ref3DPtg ptg = new Ref3DPtg(ra.getFromCell(), externSheetIndex);
 			temp.add(ptg);
 		}
 		Ptg[] ptgs = new Ptg[temp.size()];

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java Tue Sep 16 13:17:30 2008
@@ -35,6 +35,7 @@
 import org.apache.poi.hssf.record.SharedFormulaRecord;
 import org.apache.poi.hssf.record.TableRecord;
 import org.apache.poi.hssf.record.UnknownRecord;
+import org.apache.poi.hssf.record.formula.FormulaShifter;
 
 /**
  *
@@ -507,4 +508,7 @@
         fr.setColumn((short) col);
         return new FormulaRecordAggregate(fr, null, _sharedValueManager);
     }
+    public void updateFormulasAfterRowShift(FormulaShifter formulaShifter, int currentExternSheetIndex) {
+        _valuesAgg.updateFormulasAfterRowShift(formulaShifter, currentExternSheetIndex);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java Tue Sep 16 13:17:30 2008
@@ -28,6 +28,8 @@
 import org.apache.poi.hssf.record.RecordBase;
 import org.apache.poi.hssf.record.StringRecord;
 import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
+import org.apache.poi.hssf.record.formula.FormulaShifter;
+import org.apache.poi.hssf.record.formula.Ptg;
 
 /**
  *
@@ -225,6 +227,25 @@
         }
     }
 
+    public void updateFormulasAfterRowShift(FormulaShifter shifter, int currentExternSheetIndex) {
+        for (int i = 0; i < records.length; i++) {
+            CellValueRecordInterface[] rowCells = records[i];
+            if (rowCells == null) {
+                continue;
+            }
+            for (int j = 0; j < rowCells.length; j++) {
+                CellValueRecordInterface cell = rowCells[j];
+                if (cell instanceof FormulaRecordAggregate) {
+                	FormulaRecord fr = ((FormulaRecordAggregate)cell).getFormulaRecord();
+                    Ptg[] ptgs = fr.getParsedExpression(); // needs clone() inside this getter?
+                    if (shifter.adjustFormula(ptgs, currentExternSheetIndex)) {
+                        fr.setParsedExpression(ptgs);
+                    }
+                }
+            }
+        }
+    }
+
     public CellValueRecordInterface[] getValueRecords() {
         List temp = new ArrayList();
 

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java Tue Sep 16 13:17:30 2008
@@ -88,24 +88,6 @@
 	 *  formulas. The sheet name will get properly delimited if required.
 	 */
 	public String toFormulaString(HSSFWorkbook book) {
-		// First do the sheet name
-		StringBuffer retval = new StringBuffer();
-		String sheetName = book.findSheetNameFromExternSheet(field_1_index_extern_sheet);
-		if(sheetName != null) {
-			if(sheetName.length() == 0) {
-				// What excel does if sheet has been deleted
-				sheetName = "#REF";
-				retval.append(sheetName);
-			} else {
-				// Normal
-				SheetNameFormatter.appendFormat(retval, sheetName);
-			}
-			retval.append( '!' );
-		}
-		
-		// Now the normal area bit
-		retval.append(formatReferenceAsString());
-		
-		return retval.toString();
+		return ExternSheetNameResolver.prependSheetName(book, field_1_index_extern_sheet, formatReferenceAsString());
 	}
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/AreaErrPtg.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/AreaErrPtg.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/AreaErrPtg.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/AreaErrPtg.java Tue Sep 16 13:17:30 2008
@@ -18,6 +18,7 @@
 package org.apache.poi.hssf.record.formula;
 
 import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 import org.apache.poi.util.LittleEndian;
 
@@ -27,23 +28,30 @@
  * @author Daniel Noll (daniel at nuix dot com dot au)
  */
 public final class AreaErrPtg extends OperandPtg {
-    public final static byte sid  = 0x2b;
+	public final static byte sid = 0x2B;
+	private final int unused1;
+	private final int unused2;
+
+	public AreaErrPtg() {
+		unused1 = 0;
+		unused2 = 0;
+	}
+
+	public AreaErrPtg(RecordInputStream in) {
+		// 8 bytes unused:
+		unused1 = in.readInt();
+		unused2 = in.readInt();
+	}
 
-    public AreaErrPtg(RecordInputStream in) {
-    	// 8 bytes unused:
-        in.readInt();
-        in.readInt();
-    }
-
-    public void writeBytes(byte [] array, int offset) {
-        array[offset] = (byte) (sid + getPtgClass());
-        LittleEndian.putInt(array, offset+1, 0);
-        LittleEndian.putInt(array, offset+5, 0);
-    }
-
-    public String toFormulaString(HSSFWorkbook book) {
-        return "#REF!";
-    }
+	public void writeBytes(byte[] array, int offset) {
+		LittleEndian.putByte(array, offset + 0, sid + getPtgClass());
+		LittleEndian.putInt(array, offset + 1, unused1);
+		LittleEndian.putInt(array, offset + 5, unused2);
+	}
+
+	public String toFormulaString(HSSFWorkbook book) {
+		return HSSFErrorConstants.getText(HSSFErrorConstants.ERROR_REF);
+	}
 
 	public byte getDefaultOperandClass() {
 		return Ptg.CLASS_REF;

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/DeletedArea3DPtg.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/DeletedArea3DPtg.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/DeletedArea3DPtg.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/DeletedArea3DPtg.java Tue Sep 16 13:17:30 2008
@@ -35,13 +35,20 @@
 	private final int unused1;
 	private final int unused2;
 
-	public DeletedArea3DPtg( RecordInputStream in) {
+	public DeletedArea3DPtg(int externSheetIndex) {
+		field_1_index_extern_sheet = externSheetIndex;
+		unused1 = 0;
+		unused2 = 0;
+	}
+	
+	public DeletedArea3DPtg(RecordInputStream in) {
 		field_1_index_extern_sheet = in.readUShort();
 		unused1 = in.readInt();
 		unused2 = in.readInt();
 	}
 	public String toFormulaString(HSSFWorkbook book) {
-		return HSSFErrorConstants.getText(HSSFErrorConstants.ERROR_REF);
+		return ExternSheetNameResolver.prependSheetName(book, field_1_index_extern_sheet, 
+				HSSFErrorConstants.getText(HSSFErrorConstants.ERROR_REF));
 	}
 	public byte getDefaultOperandClass() {
 		return Ptg.CLASS_REF;

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/DeletedRef3DPtg.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/DeletedRef3DPtg.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/DeletedRef3DPtg.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/DeletedRef3DPtg.java Tue Sep 16 13:17:30 2008
@@ -41,8 +41,14 @@
 		unused1 = in.readInt();
 	}
 
+	public DeletedRef3DPtg(int externSheetIndex) {
+		field_1_index_extern_sheet = externSheetIndex;
+		unused1 = 0;
+	}
+
 	public String toFormulaString(HSSFWorkbook book) {
-		return HSSFErrorConstants.getText(HSSFErrorConstants.ERROR_REF);
+		return ExternSheetNameResolver.prependSheetName(book, field_1_index_extern_sheet, 
+				HSSFErrorConstants.getText(HSSFErrorConstants.ERROR_REF));
 	}
 	public byte getDefaultOperandClass() {
 		return Ptg.CLASS_REF;

Added: poi/trunk/src/java/org/apache/poi/hssf/record/formula/ExternSheetNameResolver.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/ExternSheetNameResolver.java?rev=696038&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/ExternSheetNameResolver.java (added)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/ExternSheetNameResolver.java Tue Sep 16 13:17:30 2008
@@ -0,0 +1,45 @@
+/* ====================================================================
+   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.record.formula;
+
+import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+/**
+ * @author Josh Micich
+ */
+final class ExternSheetNameResolver {
+
+	private ExternSheetNameResolver() {
+		// no instances of this class
+	}
+
+	public static String prependSheetName(HSSFWorkbook book, int field_1_index_extern_sheet, String cellRefText) {
+		String sheetName = book.findSheetNameFromExternSheet(field_1_index_extern_sheet);
+		StringBuffer sb = new StringBuffer(sheetName.length() + cellRefText.length() + 4);
+		if (sheetName.length() < 1) {
+			// What excel does if sheet has been deleted
+			sb.append("#REF"); // note - '!' added just once below
+		} else {
+    		SheetNameFormatter.appendFormat(sb, sheetName);
+		}
+   		sb.append('!');
+		sb.append(cellRefText);
+		return sb.toString();
+	}
+}

Added: poi/trunk/src/java/org/apache/poi/hssf/record/formula/FormulaShifter.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/FormulaShifter.java?rev=696038&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/FormulaShifter.java (added)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/FormulaShifter.java Tue Sep 16 13:17:30 2008
@@ -0,0 +1,294 @@
+/* ====================================================================
+   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.record.formula;
+
+
+/**
+ * @author Josh Micich
+ */
+public final class FormulaShifter {
+
+	/**
+	 * Extern sheet index of sheet where moving is occurring
+	 */
+	private final int _externSheetIndex;
+	private final int _firstMovedIndex;
+	private final int _lastMovedIndex;
+	private final int _amountToMove;
+
+	private FormulaShifter(int externSheetIndex, int firstMovedIndex, int lastMovedIndex, int amountToMove) {
+		if (amountToMove == 0) {
+			throw new IllegalArgumentException("amountToMove must not be zero");
+		}
+		if (firstMovedIndex > lastMovedIndex) {
+			throw new IllegalArgumentException("firstMovedIndex, lastMovedIndex out of order");
+		}
+		_externSheetIndex = externSheetIndex;
+		_firstMovedIndex = firstMovedIndex;
+		_lastMovedIndex = lastMovedIndex;
+		_amountToMove = amountToMove;
+	}
+
+	public static FormulaShifter createForRowShift(int externSheetIndex, int firstMovedRowIndex, int lastMovedRowIndex, int numberOfRowsToMove) {
+		return new FormulaShifter(externSheetIndex, firstMovedRowIndex, lastMovedRowIndex, numberOfRowsToMove);
+	}
+
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+
+		sb.append(getClass().getName());
+		sb.append(" [");
+		sb.append(_firstMovedIndex);
+		sb.append(_lastMovedIndex);
+		sb.append(_amountToMove);
+		return sb.toString();
+	}
+
+	/**
+	 * @param ptgs - if necessary, will get modified by this method
+	 * @param currentExternSheetIx - the extern sheet index of the sheet that contains the formula being adjusted
+	 * @return <code>true</code> if a change was made to the formula tokens
+	 */
+	public boolean adjustFormula(Ptg[] ptgs, int currentExternSheetIx) {
+		boolean refsWereChanged = false;
+		for(int i=0; i<ptgs.length; i++) {
+			Ptg newPtg = adjustPtg(ptgs[i], currentExternSheetIx);
+			if (newPtg != null) {
+				refsWereChanged = true;
+				ptgs[i] = newPtg;
+			}
+		}
+		return refsWereChanged;
+	}
+
+	private Ptg adjustPtg(Ptg ptg, int currentExternSheetIx) {
+		return adjustPtgDueToRowMove(ptg, currentExternSheetIx);
+	}
+	/**
+	 * @return <code>true</code> if this Ptg needed to be changed
+	 */
+	private Ptg adjustPtgDueToRowMove(Ptg ptg, int currentExternSheetIx) {
+		if(ptg instanceof RefPtg) {
+			if (currentExternSheetIx != _externSheetIndex) {
+				// local refs on other sheets are unaffected
+				return null;
+			}
+			RefPtg rptg = (RefPtg)ptg;
+			return rowMoveRefPtg(rptg);
+		}
+		if(ptg instanceof Ref3DPtg) {
+			Ref3DPtg rptg = (Ref3DPtg)ptg;
+			if (_externSheetIndex != rptg.getExternSheetIndex()) {
+				// only move 3D refs that refer to the sheet with cells being moved
+				// (currentExternSheetIx is irrelevant)
+				return null;
+			}
+			return rowMoveRefPtg(rptg);
+		}
+		if(ptg instanceof Area2DPtgBase) {
+			if (currentExternSheetIx != _externSheetIndex) {
+				// local refs on other sheets are unaffected
+				return ptg;
+			}
+			return rowMoveAreaPtg((Area2DPtgBase)ptg);
+		}
+		if(ptg instanceof Area3DPtg) {
+			Area3DPtg aptg = (Area3DPtg)ptg;
+			if (_externSheetIndex != aptg.getExternSheetIndex()) {
+				// only move 3D refs that refer to the sheet with cells being moved
+				// (currentExternSheetIx is irrelevant)
+				return null;
+			}
+			return rowMoveAreaPtg(aptg);
+		}
+		return null;
+	}
+
+	private Ptg rowMoveRefPtg(RefPtgBase rptg) {
+		int refRow = rptg.getRow();
+		if (_firstMovedIndex <= refRow && refRow <= _lastMovedIndex) {
+			// Rows being moved completely enclose the ref.
+			// - move the area ref along with the rows regardless of destination
+			rptg.setRow(refRow + _amountToMove);
+			return rptg;
+		}
+		// else rules for adjusting area may also depend on the destination of the moved rows
+
+		int destFirstRowIndex = _firstMovedIndex + _amountToMove;
+		int destLastRowIndex = _lastMovedIndex + _amountToMove;
+
+		// ref is outside source rows
+		// check for clashes with destination
+
+		if (destLastRowIndex < refRow || refRow < destFirstRowIndex) {
+			// destination rows are completely outside ref
+			return null;
+		}
+
+		if (destFirstRowIndex <= refRow && refRow <= destLastRowIndex) {
+			// destination rows enclose the area (possibly exactly)
+			return createDeletedRef(rptg);
+		}
+		throw new IllegalStateException("Situation not covered: (" + _firstMovedIndex + ", " +
+					_lastMovedIndex + ", " + _amountToMove + ", " + refRow + ", " + refRow + ")");
+	}
+
+	private Ptg rowMoveAreaPtg(AreaPtgBase aptg) {
+		int aFirstRow = aptg.getFirstRow();
+		int aLastRow = aptg.getLastRow();
+		if (_firstMovedIndex <= aFirstRow && aLastRow <= _lastMovedIndex) {
+			// Rows being moved completely enclose the area ref.
+			// - move the area ref along with the rows regardless of destination
+			aptg.setFirstRow(aFirstRow + _amountToMove);
+			aptg.setLastRow(aLastRow + _amountToMove);
+			return aptg;
+		}
+		// else rules for adjusting area may also depend on the destination of the moved rows
+
+		int destFirstRowIndex = _firstMovedIndex + _amountToMove;
+		int destLastRowIndex = _lastMovedIndex + _amountToMove;
+
+		if (aFirstRow < _firstMovedIndex && _lastMovedIndex < aLastRow) {
+			// Rows moved were originally *completely* within the area ref
+
+			// If the destination of the rows overlaps either the top
+			// or bottom of the area ref there will be a change
+			if (destFirstRowIndex < aFirstRow && aFirstRow <= destLastRowIndex) {
+				// truncate the top of the area by the moved rows
+				aptg.setFirstRow(destLastRowIndex+1);
+				return aptg;
+			} else if (destFirstRowIndex <= aLastRow && aLastRow < destLastRowIndex) {
+				// truncate the bottom of the area by the moved rows
+				aptg.setLastRow(destFirstRowIndex-1);
+				return aptg;
+			}
+			// else - rows have moved completely outside the area ref,
+			// or still remain completely within the area ref
+			return null; // - no change to the area
+		}
+		if (_firstMovedIndex <= aFirstRow && aFirstRow <= _lastMovedIndex) {
+			// Rows moved include the first row of the area ref, but not the last row
+			// btw: (aLastRow > _lastMovedIndex)
+			if (_amountToMove < 0) {
+				// simple case - expand area by shifting top upward
+				aptg.setFirstRow(aFirstRow + _amountToMove);
+				return aptg;
+			}
+			if (destFirstRowIndex > aLastRow) {
+				// in this case, excel ignores the row move
+				return null;
+			}
+			int newFirstRowIx = aFirstRow + _amountToMove;
+			if (destLastRowIndex < aLastRow) {
+				// end of area is preserved (will remain exact same row)
+				// the top area row is moved simply
+				aptg.setFirstRow(newFirstRowIx);
+				return aptg;
+			}
+			// else - bottom area row has been replaced - both area top and bottom may move now
+			int areaRemainingTopRowIx = _lastMovedIndex + 1;
+			if (destFirstRowIndex > areaRemainingTopRowIx) {
+				// old top row of area has moved deep within the area, and exposed a new top row
+				newFirstRowIx = areaRemainingTopRowIx;
+			}
+			aptg.setFirstRow(newFirstRowIx);
+			aptg.setLastRow(Math.max(aLastRow, destLastRowIndex));
+			return aptg;
+		}
+		if (_firstMovedIndex <= aLastRow && aLastRow <= _lastMovedIndex) {
+			// Rows moved include the last row of the area ref, but not the first
+			// btw: (aFirstRow < _firstMovedIndex)
+			if (_amountToMove > 0) {
+				// simple case - expand area by shifting bottom downward
+				aptg.setLastRow(aLastRow + _amountToMove);
+				return aptg;
+			}
+			if (destLastRowIndex < aFirstRow) {
+				// in this case, excel ignores the row move
+				return null;
+			}
+			int newLastRowIx = aLastRow + _amountToMove;
+			if (destFirstRowIndex > aFirstRow) {
+				// top of area is preserved (will remain exact same row)
+				// the bottom area row is moved simply
+				aptg.setLastRow(newLastRowIx);
+				return aptg;
+			}
+			// else - top area row has been replaced - both area top and bottom may move now
+			int areaRemainingBottomRowIx = _firstMovedIndex - 1;
+			if (destLastRowIndex < areaRemainingBottomRowIx) {
+				// old bottom row of area has moved up deep within the area, and exposed a new bottom row
+				newLastRowIx = areaRemainingBottomRowIx;
+			}
+			aptg.setFirstRow(Math.min(aFirstRow, destFirstRowIndex));
+			aptg.setLastRow(newLastRowIx);
+			return aptg;
+		}
+		// else source rows include none of the rows of the area ref
+		// check for clashes with destination
+
+		if (destLastRowIndex < aFirstRow || aLastRow < destFirstRowIndex) {
+			// destination rows are completely outside area ref
+			return null;
+		}
+
+		if (destFirstRowIndex <= aFirstRow && aLastRow <= destLastRowIndex) {
+			// destination rows enclose the area (possibly exactly)
+			return createDeletedRef(aptg);
+		}
+
+		if (aFirstRow <= destFirstRowIndex && destLastRowIndex <= aLastRow) {
+			// destination rows are within area ref (possibly exact on top or bottom, but not both)
+			return null; // - no change to area
+		}
+
+		if (destFirstRowIndex < aFirstRow && aFirstRow <= destLastRowIndex) {
+			// dest rows overlap top of area
+			// - truncate the top
+			aptg.setFirstRow(destLastRowIndex+1);
+			return aptg;
+		}
+		if (destFirstRowIndex < aLastRow && aLastRow <= destLastRowIndex) {
+			// dest rows overlap bottom of area
+			// - truncate the bottom
+			aptg.setLastRow(destFirstRowIndex-1);
+			return aptg;
+		}
+		throw new IllegalStateException("Situation not covered: (" + _firstMovedIndex + ", " +
+					_lastMovedIndex + ", " + _amountToMove + ", " + aFirstRow + ", " + aLastRow + ")");
+	}
+
+	private static Ptg createDeletedRef(Ptg ptg) {
+		if (ptg instanceof RefPtg) {
+			return new RefErrorPtg();
+		}
+		if (ptg instanceof Ref3DPtg) {
+			Ref3DPtg rptg = (Ref3DPtg) ptg;
+			return new DeletedRef3DPtg(rptg.getExternSheetIndex());
+		}
+		if (ptg instanceof AreaPtg) {
+			return new AreaErrPtg();
+		}
+		if (ptg instanceof Area3DPtg) {
+			Area3DPtg area3DPtg = (Area3DPtg) ptg;
+			return new DeletedArea3DPtg(area3DPtg.getExternSheetIndex());
+		}
+
+		throw new IllegalArgumentException("Unexpected ref ptg class (" + ptg.getClass().getName() + ")");
+	}
+}

Added: poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ref2DPtgBase.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ref2DPtgBase.java?rev=696038&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ref2DPtgBase.java (added)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ref2DPtgBase.java Tue Sep 16 13:17:30 2008
@@ -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.record.formula;
+
+import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.util.LittleEndian;
+
+/**
+ * @author Josh Micich
+ */
+abstract class Ref2DPtgBase extends RefPtgBase {
+    private final static int SIZE = 5;
+
+    /**
+     * Takes in a String representation of a cell reference and fills out the
+     * numeric fields.
+     */
+    protected Ref2DPtgBase(String cellref) {
+    	super(cellref);
+    }
+
+    protected Ref2DPtgBase(int row, int column, boolean isRowRelative, boolean isColumnRelative) {
+      setRow(row);
+      setColumn(column);
+      setRowRelative(isRowRelative);
+      setColRelative(isColumnRelative);
+    }
+
+    protected Ref2DPtgBase(RecordInputStream in) {
+        readCoordinates(in);
+    }
+    public final void writeBytes(byte [] array, int offset) {
+    	LittleEndian.putByte(array, offset+0, getSid() + getPtgClass());
+    	writeCoordinates(array, offset+1);
+    }
+    public final String toFormulaString(HSSFWorkbook book) {
+    	return formatReferenceAsString();
+    }
+
+	protected abstract byte getSid();
+    public final int getSize() {
+        return SIZE;
+    }
+    public final String toString() {
+        StringBuffer sb = new StringBuffer();
+        sb.append(getClass().getName());
+        sb.append(" [");
+        sb.append(formatReferenceAsString());
+        sb.append("]");
+        return sb.toString();
+    }
+}

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java Tue Sep 16 13:17:30 2008
@@ -20,9 +20,6 @@
 import org.apache.poi.hssf.record.RecordInputStream;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 import org.apache.poi.hssf.util.CellReference;
-import org.apache.poi.hssf.util.RangeAddress;
-import org.apache.poi.util.BitField;
-import org.apache.poi.util.BitFieldFactory;
 import org.apache.poi.util.LittleEndian;
 
 /**
@@ -33,30 +30,18 @@
  * @author Jason Height (jheight at chariot dot net dot au)
  * @version 1.0-pre
  */
-public final class Ref3DPtg extends OperandPtg {
+public final class Ref3DPtg extends RefPtgBase {
     public final static byte sid  = 0x3a;
 
-    private static final BitField rowRelative = BitFieldFactory.getInstance(0x8000);
-    private static final BitField colRelative = BitFieldFactory.getInstance(0x4000);
-
     private final static int  SIZE = 7; // 6 + 1 for Ptg
     private int             field_1_index_extern_sheet;
-    /** The row index - zero based unsigned 16 bit value */
-    private int            field_2_row;
-    /** Field 2 
-     * - lower 8 bits is the zero based unsigned byte column index 
-     * - bit 16 - isRowRelative
-     * - bit 15 - isColumnRelative 
-     */
-    private int             field_3_column;
 
     /** Creates new AreaPtg */
     public Ref3DPtg() {}
 
     public Ref3DPtg(RecordInputStream in) {
         field_1_index_extern_sheet = in.readShort();
-        field_2_row          = in.readShort();
-        field_3_column        = in.readShort();
+        readCoordinates(in);
     }
     
     public Ref3DPtg(String cellref, short externIdx ) {
@@ -69,13 +54,12 @@
     }
 
     public String toString() {
-        CellReference cr = new CellReference(getRow(), getColumn(), !isRowRelative(),!isColRelative());
         StringBuffer sb = new StringBuffer();
         sb.append(getClass().getName());
         sb.append(" [");
         sb.append("sheetIx=").append(getExternSheetIndex());
         sb.append(" ! ");
-        sb.append(cr.formatAsString());
+        sb.append(formatReferenceAsString());
         sb.append("]");
         return sb.toString();
     }
@@ -83,8 +67,7 @@
     public void writeBytes(byte [] array, int offset) {
         array[ 0 + offset ] = (byte) (sid + getPtgClass());
         LittleEndian.putShort(array, 1 + offset , getExternSheetIndex());
-        LittleEndian.putShort(array, 3 + offset , (short)getRow());
-        LittleEndian.putShort(array, 5 + offset , (short)getColumnRaw());
+        writeCoordinates(array, offset+3);
     }
 
     public int getSize() {
@@ -99,83 +82,11 @@
         field_1_index_extern_sheet = index;
     }
 
-    public int getRow() {
-        return field_2_row;
-    }
-
-    public void setRow(int row) {
-        field_2_row = row;
-    }
-
-    public int getColumn() {
-        return field_3_column & 0xFF;
-    }
-
-    public int getColumnRaw() {
-        return field_3_column;
-    }
-
-     public boolean isRowRelative()
-    {
-        return rowRelative.isSet(field_3_column);
-    }
-    
-    public void setRowRelative(boolean rel) {
-        field_3_column=rowRelative.setBoolean(field_3_column,rel);
-    }
-    
-    public boolean isColRelative()
-    {
-        return colRelative.isSet(field_3_column);
-    }
-    
-    public void setColRelative(boolean rel) {
-        field_3_column=colRelative.setBoolean(field_3_column,rel);
-    }
-    public void setColumn(short column) {
-        field_3_column &= 0xFF00;
-        field_3_column |= column & 0xFF;
-    }
-
-    public void setColumnRaw(short column) {
-        field_3_column = column;
-    }
-
-   /* public String getArea(){
-        RangeAddress ra = new RangeAddress("");
-
-        String result = (ra.numTo26Sys(getColumn()) + (getRow() + 1));
-
-        return result;
-    }*/
-
-    public void setArea(String ref){
-        RangeAddress ra = new RangeAddress(ref);
-
-        String from = ra.getFromCell();
-
-        setColumn((short) (ra.getXPosition(from) -1));
-        setRow((short) (ra.getYPosition(from) -1));
-
-    }
-
     /**
      * @return text representation of this cell reference that can be used in text 
      * formulas. The sheet name will get properly delimited if required.
      */
-    public String toFormulaString(HSSFWorkbook book)
-    {
-        StringBuffer retval = new StringBuffer();
-        String sheetName = book.findSheetNameFromExternSheet(field_1_index_extern_sheet);
-        if(sheetName != null) {
-            SheetNameFormatter.appendFormat(retval, sheetName);
-            retval.append( '!' );
-        }
-        retval.append((new CellReference(getRow(),getColumn(),!isRowRelative(),!isColRelative())).formatAsString()); 
-        return retval.toString();
+    public String toFormulaString(HSSFWorkbook book) {
+		return ExternSheetNameResolver.prependSheetName(book, field_1_index_extern_sheet, formatReferenceAsString());
     }
-
-   public byte getDefaultOperandClass() {
-		return Ptg.CLASS_REF;
-	}
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefErrorPtg.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefErrorPtg.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefErrorPtg.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefErrorPtg.java Tue Sep 16 13:17:30 2008
@@ -18,6 +18,7 @@
 package org.apache.poi.hssf.record.formula;
 
 import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 import org.apache.poi.util.LittleEndian;
 
@@ -28,48 +29,32 @@
 public final class RefErrorPtg extends OperandPtg {
 
     private final static int SIZE = 5;
-    public final static byte sid  = 0x2a;
+    public final static byte sid  = 0x2A;
     private int              field_1_reserved;
 
-    public RefErrorPtg(RecordInputStream in)
-    {
+    public RefErrorPtg() {
+        field_1_reserved = 0;
+    }
+    public RefErrorPtg(RecordInputStream in) {
         field_1_reserved = in.readInt();
-
     }
 
-    public String toString()
-    {
-        StringBuffer buffer = new StringBuffer("[RefError]\n");
-
-        buffer.append("reserved = ").append(getReserved()).append("\n");
-        return buffer.toString();
+    public String toString() {
+        return getClass().getName();
     }
 
-    public void writeBytes(byte [] array, int offset)
-    {
-        array[offset] = (byte) (sid + getPtgClass());
+    public void writeBytes(byte [] array, int offset) {
+        LittleEndian.putByte(array, offset+0, sid + getPtgClass());
         LittleEndian.putInt(array,offset+1,field_1_reserved);
     }
 
-    public void setReserved(int reserved)
-    {
-        field_1_reserved = reserved;
-    }
-
-    public int getReserved()
-    {
-        return field_1_reserved;
-    }
-
     public int getSize()
     {
         return SIZE;
     }
 
-    public String toFormulaString(HSSFWorkbook book)
-    {
-        //TODO -- should we store a cellreference instance in this ptg?? but .. memory is an issue, i believe!
-        return "#REF!";
+    public String toFormulaString(HSSFWorkbook book) {
+        return HSSFErrorConstants.getText(HSSFErrorConstants.ERROR_REF);
     }
     
     public byte getDefaultOperandClass() {

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefNPtg.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefNPtg.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefNPtg.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefNPtg.java Tue Sep 16 13:17:30 2008
@@ -23,16 +23,14 @@
  * RefNPtg
  * @author Jason Height (jheight at apache dot com)
  */
-public final class RefNPtg extends RefPtgBase {
-    public final static byte sid  = 0x2C;
+public final class RefNPtg extends Ref2DPtgBase {
+	public final static byte sid = 0x2C;
 
-    /** Creates new ValueReferencePtg */
+	public RefNPtg(RecordInputStream in) {
+		super(in);
+	}
 
-    public RefNPtg(RecordInputStream in) {
-      super(in);
-    }
-    
-    protected byte getSid() {
-    	return sid;
-    }
+	protected byte getSid() {
+		return sid;
+	}
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefPtg.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefPtg.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefPtg.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefPtg.java Tue Sep 16 13:17:30 2008
@@ -24,30 +24,26 @@
  * @author  Andrew C. Oliver (acoliver@apache.org)
  * @author Jason Height (jheight at chariot dot net dot au)
  */
-public final class RefPtg extends RefPtgBase {
-    public final static byte sid  = 0x24;
+public final class RefPtg extends Ref2DPtgBase {
+	public final static byte sid = 0x24;
 
-    /**
-     * Takes in a String representation of a cell reference and fills out the
-     * numeric fields.
-     */
-    public RefPtg(String cellref) {
-    	super(cellref);
-    }
+	/**
+	 * Takes in a String representation of a cell reference and fills out the
+	 * numeric fields.
+	 */
+	public RefPtg(String cellref) {
+		super(cellref);
+	}
 
-    public RefPtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) {
-      setRow(row);
-      setColumn(column);
-      setRowRelative(isRowRelative);
-      setColRelative(isColumnRelative);
-    }
+	public RefPtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) {
+		super(row, column, isRowRelative, isColumnRelative);
+	}
 
-    public RefPtg(RecordInputStream in) {
-        super(in);
-    }
+	public RefPtg(RecordInputStream in) {
+		super(in);
+	}
 
 	protected byte getSid() {
 		return sid;
 	}
-    
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java Tue Sep 16 13:17:30 2008
@@ -17,13 +17,11 @@
 
 package org.apache.poi.hssf.record.formula;
 
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.hssf.util.CellReference;
 import org.apache.poi.util.BitField;
 import org.apache.poi.util.BitFieldFactory;
-
-import org.apache.poi.hssf.util.CellReference;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.util.LittleEndian;
 
 /**
  * ReferencePtgBase - handles references (such as A1, A2, IA4)
@@ -32,7 +30,6 @@
  */
 public abstract class RefPtgBase extends OperandPtg {
 
-    private final static int SIZE = 5;
     private final static int MAX_ROW_NUMBER = 65536;
 
    /** The row index - zero based unsigned 16 bit value */
@@ -70,29 +67,14 @@
       setColRelative(isColumnRelative);
     }
 
-    protected RefPtgBase(RecordInputStream in) {
+    protected final void readCoordinates(RecordInputStream in) {
         field_1_row = in.readUShort();
         field_2_col = in.readUShort();
     }
-
-    public final String toString() {
-        CellReference cr = new CellReference(getRow(), getColumn(), !isRowRelative(),!isColRelative());
-        StringBuffer sb = new StringBuffer();
-        sb.append(getClass().getName());
-        sb.append(" [");
-        sb.append(cr.formatAsString());
-        sb.append("]");
-        return sb.toString();
-    }
-
-    public final void writeBytes(byte [] array, int offset) {
-        array[offset] = (byte) (getSid() + getPtgClass());
-
-        LittleEndian.putShort(array, offset+1, (short)field_1_row);
-        LittleEndian.putShort(array, offset+3, (short)field_2_col);
+    protected final void writeCoordinates(byte[] array, int offset) {
+        LittleEndian.putUShort(array, offset + 0, field_1_row);
+        LittleEndian.putUShort(array, offset + 2, field_2_col);
     }
-    
-    protected abstract byte getSid();
 
     public final void setRow(int row) {
         if(row < 0 || row >= MAX_ROW_NUMBER) {
@@ -102,18 +84,11 @@
     }
 
     /**
-     * Returns the row number as a short, which will be
-     *  wrapped (negative) for values between 32769 and 65535
+     * @return the row number as an int, between 0 and 65535
      */
     public final int getRow(){
         return field_1_row;
     }
-    /**
-     * Returns the row number as an int, between 0 and 65535
-     */
-    public final int getRowAsInt() {
-        return field_1_row;
-    }
 
     public final boolean isRowRelative() {
         return rowRelative.isSet(field_2_col);
@@ -135,20 +110,16 @@
         if(col < 0 || col >= 0x100) {
             throw new IllegalArgumentException("Specified colIx (" + col + ") is out of range");
         }
-    	field_2_col = column.setValue(field_2_col, col);
+       field_2_col = column.setValue(field_2_col, col);
     }
 
     public final int getColumn() {
-    	return column.getValue(field_2_col);
-    }
-
-    public final int getSize() {
-        return SIZE;
+       return column.getValue(field_2_col);
     }
-
-    public final String toFormulaString(HSSFWorkbook book) {
-        //TODO -- should we store a cellreference instance in this ptg?? but .. memory is an issue, i believe!
-        return (new CellReference(getRowAsInt(),getColumn(),!isRowRelative(),!isColRelative())).formatAsString();
+    protected final String formatReferenceAsString() {
+        // Only make cell references as needed. Memory is an issue
+        CellReference cr = new CellReference(getRow(), getColumn(), !isRowRelative(), !isColRelative());
+        return cr.formatAsString();
     }
 
     public final byte getDefaultOperandClass() {

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java Tue Sep 16 13:17:30 2008
@@ -296,7 +296,7 @@
                 FormulaRecordAggregate frec;
 
                 if (cellType != this.cellType) {
-                    frec = sheet.getSheet().createFormula(row, col);
+                    frec = sheet.getSheet().getRowsAggregate().createFormula(row, col);
                 } else {
                     frec = (FormulaRecordAggregate) record;
                     frec.setRow(row);
@@ -592,12 +592,6 @@
         Ptg[] ptgs = FormulaParser.parse(formula, book);
         frec.setParsedExpression(ptgs);
     }
-    /* package */ void setFormulaOnly(Ptg[] ptgs) {
-        if (ptgs == null) {
-            throw new IllegalArgumentException("ptgs must not be null");
-        }
-        ((FormulaRecordAggregate)record).getFormulaRecord().setParsedExpression(ptgs);
-    }
 
     public String getCellFormula() {
         return FormulaParser.toFormulaString(book, ((FormulaRecordAggregate)record).getFormulaRecord().getParsedExpression());

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFName.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFName.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFName.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFName.java Tue Sep 16 13:17:30 2008
@@ -124,8 +124,16 @@
      * @return true if the name refers to a deleted cell, false otherwise
      */
     public boolean isDeleted(){
-        String ref = getReference();
-        return "#REF!".endsWith(ref);
+        String formulaText = getReference();
+        if (formulaText.startsWith("#REF!")) {
+        	// sheet deleted
+        	return true;
+        }
+        if (formulaText.endsWith("#REF!")) {
+        	// cell range deleted
+        	return true;
+        }
+        return false;
     }
     public boolean isFunctionName() {
         return _definedNameRec.isFunctionName();

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java Tue Sep 16 13:17:30 2008
@@ -31,7 +31,6 @@
 import java.util.TreeMap;
 
 import org.apache.poi.ddf.EscherRecord;
-import org.apache.poi.hssf.model.FormulaParser;
 import org.apache.poi.hssf.model.Sheet;
 import org.apache.poi.hssf.model.Workbook;
 import org.apache.poi.hssf.record.CellValueRecordInterface;
@@ -43,8 +42,7 @@
 import org.apache.poi.hssf.record.WSBoolRecord;
 import org.apache.poi.hssf.record.WindowTwoRecord;
 import org.apache.poi.hssf.record.aggregates.DataValidityTable;
-import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.hssf.record.formula.RefPtg;
+import org.apache.poi.hssf.record.formula.FormulaShifter;
 import org.apache.poi.hssf.util.CellRangeAddress;
 import org.apache.poi.hssf.util.PaneInformation;
 import org.apache.poi.hssf.util.Region;
@@ -1174,33 +1172,26 @@
      * @param resetOriginalRowHeight whether to set the original row's height to the default
      * @param moveComments whether to move comments at the same time as the cells they are attached to
      */
-    public void shiftRows( int startRow, int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight, boolean moveComments)
-    {
-        int s, e, inc;
-        if ( n < 0 )
-        {
+    public void shiftRows(int startRow, int endRow, int n, 
+            boolean copyRowHeight, boolean resetOriginalRowHeight, boolean moveComments) {
+        int s, inc;
+        if (n < 0) {
             s = startRow;
-            e = endRow;
             inc = 1;
-        }
-        else
-        {
+        } else {
             s = endRow;
-            e = startRow;
             inc = -1;
         }
 
         shiftMerged(startRow, endRow, n, true);
         sheet.getPageSettings().shiftRowBreaks(startRow, endRow, n);
 
-        for ( int rowNum = s; rowNum >= startRow && rowNum <= endRow && rowNum >= 0 && rowNum < 65536; rowNum += inc )
-        {
+        for ( int rowNum = s; rowNum >= startRow && rowNum <= endRow && rowNum >= 0 && rowNum < 65536; rowNum += inc ) {
             HSSFRow row = getRow( rowNum );
             HSSFRow row2Replace = getRow( rowNum + n );
             if ( row2Replace == null )
                 row2Replace = createRow( rowNum + n );
 
-            HSSFCell cell;
             
             // Remove all the old cells from the row we'll
             //  be writing too, before we start overwriting 
@@ -1230,7 +1221,7 @@
             // Copy each cell from the source row to
             //  the destination row
             for(Iterator cells = row.cellIterator(); cells.hasNext(); ) {
-                cell = (HSSFCell)cells.next();
+                HSSFCell cell = (HSSFCell)cells.next();
                 row.removeCell( cell );
                 CellValueRecordInterface cellRecord = cell.getCellValueRecord();
                 cellRecord.setRow( rowNum + n );
@@ -1257,49 +1248,21 @@
 
         // Update any formulas on this sheet that point to
         //  rows which have been moved
-        updateFormulasAfterShift(startRow, endRow, n);
-    }
-
-    /**
-     * Called by shiftRows to update formulas on this sheet
-     *  to point to the new location of moved rows
-     */
-    private void updateFormulasAfterShift(int startRow, int endRow, int n) {
-        // Need to look at every cell on the sheet
-        // Not just those that were moved
-        Iterator ri = rowIterator();
-        while(ri.hasNext()) {
-            HSSFRow r = (HSSFRow)ri.next();
-            Iterator ci = r.cellIterator();
-            while(ci.hasNext()) {
-                HSSFCell c = (HSSFCell)ci.next();
-                if(c.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
-                    // Since it's a formula cell, process the
-                    //  formula string, and look to see if
-                    //  it contains any references
-
-                    // Look for references, and update if needed
-                    Ptg[] ptgs = FormulaParser.parse(c.getCellFormula(), workbook);
-                    boolean changed = false;
-                    for(int i=0; i<ptgs.length; i++) {
-                        if(ptgs[i] instanceof RefPtg) {
-                            RefPtg rptg = (RefPtg)ptgs[i];
-                            if(startRow <= rptg.getRowAsInt() &&
-                                    rptg.getRowAsInt() <= endRow) {
-                                // References a row that moved
-                                rptg.setRow(rptg.getRowAsInt() + n);
-                                changed = true;
-                            }
-                        }
-                    }
-                    // If any references were changed, then
-                    //  re-create the formula string
-                    if(changed) {
-                        c.setFormulaOnly(ptgs);
-                    }
-                }
+        int sheetIndex = workbook.getSheetIndex(this);
+        short externSheetIndex = book.checkExternSheet(sheetIndex);
+        FormulaShifter shifter = FormulaShifter.createForRowShift(externSheetIndex, startRow, endRow, n);
+        sheet.getRowsAggregate().updateFormulasAfterRowShift(shifter, externSheetIndex);
+
+        int nSheets = workbook.getNumberOfSheets();
+        for(int i=0; i<nSheets; i++) {
+            Sheet otherSheet = workbook.getSheetAt(i).getSheet();
+            if (otherSheet == this.sheet) {
+                continue;
             }
+            short otherExtSheetIx = book.checkExternSheet(i);
+            otherSheet.getRowsAggregate().updateFormulasAfterRowShift(shifter, otherExtSheetIx);
         }
+        // TODO - adjust formulas in named ranges
     }
 
     protected void insertChartRecords( List records )
@@ -1646,9 +1609,12 @@
         sheet.groupRowRange( fromRow, toRow, false );
     }
 
-    public void setRowGroupCollapsed( int row, boolean collapse )
-    {
-        sheet.setRowGroupCollapsed( row, collapse );
+    public void setRowGroupCollapsed(int rowIndex, boolean collapse) {
+        if (collapse) {
+            sheet.getRowsAggregate().collapseRow(rowIndex);
+        } else {
+            sheet.getRowsAggregate().expandRow(rowIndex);
+        }
     }
 
     /**

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java Tue Sep 16 13:17:30 2008
@@ -677,10 +677,35 @@
      *  if needed.
      * Used by some of the more obscure formula and
      *  named range things.
+     * @deprecated for POI internal use only (formula parsing).  This method is likely to
+     * be removed in future versions of POI.
      */
     public short getExternalSheetIndex(int internalSheetIndex) {
         return workbook.checkExternSheet(internalSheetIndex);
     }
+    /**
+     * @deprecated for POI internal use only (formula rendering).  This method is likely to
+     * be removed in future versions of POI.
+     */
+    public String findSheetNameFromExternSheet(int externSheetIndex){
+        // TODO - don't expose internal ugliness like externSheet indexes to the user model API
+        return workbook.findSheetNameFromExternSheet(externSheetIndex);
+    }
+    /**
+     * @deprecated for POI internal use only (formula rendering).  This method is likely to
+     * be removed in future versions of POI.
+     * 
+     * @param refIndex Index to REF entry in EXTERNSHEET record in the Link Table
+     * @param definedNameIndex zero-based to DEFINEDNAME or EXTERNALNAME record
+     * @return the string representation of the defined or external name
+     */
+    public String resolveNameXText(int refIndex, int definedNameIndex) {
+        // TODO - make this less cryptic / move elsewhere
+        return workbook.resolveNameXText(refIndex, definedNameIndex);
+    }
+
+
+
 
     /**
      * create an HSSFSheet for this HSSFWorkbook, adds it to the sheets and returns
@@ -860,15 +885,6 @@
     }
 
     /**
-     * @deprecated for POI internal use only (formula rendering).  This method is likely to
-     * be removed in future versions of POI.
-     */
-    public String findSheetNameFromExternSheet(int externSheetIndex){
-        // TODO - don't expose internal ugliness like externSheet indexes to the user model API
-        return workbook.findSheetNameFromExternSheet(externSheetIndex);
-    }
-
-    /**
      * Removes sheet at the given index.<p/>
      *
      * Care must be taken if the removed sheet is the currently active or only selected sheet in
@@ -1376,20 +1392,6 @@
     }
 
     /**
-     * @deprecated for POI internal use only (formula rendering).  This method is likely to
-     * be removed in future versions of POI.
-     * 
-     * @param refIndex Index to REF entry in EXTERNSHEET record in the Link Table
-     * @param definedNameIndex zero-based to DEFINEDNAME or EXTERNALNAME record
-     * @return the string representation of the defined or external name
-     */
-    public String resolveNameXText(int refIndex, int definedNameIndex) {
-        // TODO - make this less cryptic / move elsewhere
-        return workbook.resolveNameXText(refIndex, definedNameIndex);
-    }
-
-
-    /**
      * Sets the printarea for the sheet provided
      * <p>
      * i.e. Reference = $A$1:$B$2

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/data/ForShifting.xls
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/data/ForShifting.xls?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
Binary files - no diff available.

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/AllFormulaTests.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/AllFormulaTests.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/AllFormulaTests.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/AllFormulaTests.java Tue Sep 16 13:17:30 2008
@@ -43,6 +43,7 @@
 		result.addTestSuite(TestArrayPtg.class);
 		result.addTestSuite(TestErrPtg.class);
 		result.addTestSuite(TestExternalFunctionFormulas.class);
+		result.addTestSuite(TestFormulaShifter.class);
 		result.addTestSuite(TestFuncPtg.class);
 		result.addTestSuite(TestFuncVarPtg.class);
 		result.addTestSuite(TestIntersectionPtg.class);

Added: poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/TestFormulaShifter.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/TestFormulaShifter.java?rev=696038&view=auto
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/TestFormulaShifter.java (added)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/TestFormulaShifter.java Tue Sep 16 13:17:30 2008
@@ -0,0 +1,115 @@
+/* ====================================================================
+   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.record.formula;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link FormulaShifter}.
+ *
+ * @author Josh Micich
+ */
+public final class TestFormulaShifter extends TestCase {
+	// Note - the expected result row coordinates here were determined/verified
+	// in Excel 2007 by manually testing.
+
+	/**
+	 * Tests what happens to area refs when a range of rows from inside, or overlapping are
+	 * moved
+	 */
+	public void testShiftAreasSourceRows() {
+
+		// all these operations are on an area ref spanning rows 10 to 20
+		AreaPtg aptg  = createAreaPtg(10, 20);
+
+		confirmAreaShift(aptg,  9, 21, 20, 30, 40);
+		confirmAreaShift(aptg, 10, 21, 20, 30, 40);
+		confirmAreaShift(aptg,  9, 20, 20, 30, 40);
+
+		confirmAreaShift(aptg, 8, 11,  -3, 7, 20); // simple expansion of top
+		// rows containing area top being shifted down:
+		confirmAreaShift(aptg, 8, 11,  3, 13, 20);
+		confirmAreaShift(aptg, 8, 11,  7, 17, 20);
+		confirmAreaShift(aptg, 8, 11,  8, 18, 20);
+		confirmAreaShift(aptg, 8, 11,  9, 12, 20); // note behaviour changes here
+		confirmAreaShift(aptg, 8, 11, 10, 12, 21);
+		confirmAreaShift(aptg, 8, 11, 12, 12, 23);
+		confirmAreaShift(aptg, 8, 11, 13, 10, 20);  // ignored
+
+		// rows from within being moved:
+		confirmAreaShift(aptg, 12, 16,  3, 10, 20);  // stay within - no change
+		confirmAreaShift(aptg, 11, 19, 20, 10, 20);  // move completely out - no change
+		confirmAreaShift(aptg, 16, 17, -6, 10, 20);  // moved exactly to top - no change
+		confirmAreaShift(aptg, 16, 17, -7, 11, 20);  // truncation at top
+		confirmAreaShift(aptg, 12, 16,  4, 10, 20);  // moved exactly to bottom - no change
+		confirmAreaShift(aptg, 12, 16,  6, 10, 17);  // truncation at bottom
+
+		// rows containing area bottom being shifted up:
+		confirmAreaShift(aptg, 18, 22, -1, 10, 19); // simple contraction at bottom
+		confirmAreaShift(aptg, 18, 22, -7, 10, 13); // simple contraction at bottom
+		confirmAreaShift(aptg, 18, 22, -8, 10, 17); // top calculated differently here
+		confirmAreaShift(aptg, 18, 22, -9,  9, 17);
+		confirmAreaShift(aptg, 18, 22,-15, 10, 20); // no change because range would be turned inside out
+		confirmAreaShift(aptg, 15, 19, -7, 13, 20); // dest truncates top (even though src is from inside range)
+		confirmAreaShift(aptg, 19, 23,-12,  7, 18); // complex: src encloses bottom, dest encloses top
+
+		confirmAreaShift(aptg, 18, 22,  5, 10, 25); // simple expansion at bottom
+	}
+	/**
+	 * Tests what happens to an area ref when some outside rows are moved to overlap
+	 * that area ref
+	 */
+	public void testShiftAreasDestRows() {
+		// all these operations are on an area ref spanning rows 20 to 25
+		AreaPtg aptg  = createAreaPtg(20, 25);
+
+		// no change because no overlap:
+		confirmAreaShift(aptg,  5, 10,  9, 20, 25);
+		confirmAreaShift(aptg,  5, 10, 21, 20, 25);
+
+		confirmAreaShift(aptg, 11, 14, 10, 20, 25);
+
+		confirmAreaShift(aptg,   7, 17, 10, -1, -1); // converted to DeletedAreaRef
+		confirmAreaShift(aptg,   5, 15,  7, 23, 25); // truncation at top
+		confirmAreaShift(aptg,  13, 16, 10, 20, 22); // truncation at bottom
+	}
+
+	private static void confirmAreaShift(AreaPtg aptg,
+			int firstRowMoved, int lastRowMoved, int numberRowsMoved,
+			int expectedAreaFirstRow, int expectedAreaLastRow) {
+
+		FormulaShifter fs = FormulaShifter.createForRowShift(0, firstRowMoved, lastRowMoved, numberRowsMoved);
+		boolean expectedChanged = aptg.getFirstRow() != expectedAreaFirstRow || aptg.getLastRow() != expectedAreaLastRow;
+
+		AreaPtg copyPtg = (AreaPtg) aptg.copy(); // clone so we can re-use aptg in calling method
+		Ptg[] ptgs = { copyPtg, };
+		boolean actualChanged = fs.adjustFormula(ptgs, 0);
+		if (expectedAreaFirstRow < 0) {
+			assertEquals(AreaErrPtg.class, ptgs[0].getClass());
+			return;
+		}
+		assertEquals(expectedChanged, actualChanged);
+		assertEquals(copyPtg, ptgs[0]);  // expected to change in place (although this is not a strict requirement)
+		assertEquals(expectedAreaFirstRow, copyPtg.getFirstRow());
+		assertEquals(expectedAreaLastRow, copyPtg.getLastRow());
+
+	}
+	private static AreaPtg createAreaPtg(int initialAreaFirstRow, int initialAreaLastRow) {
+		return new AreaPtg(initialAreaFirstRow, initialAreaLastRow, 2, 5, false, false, false, false);
+	}
+}

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestFormulas.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestFormulas.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestFormulas.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestFormulas.java Tue Sep 16 13:17:30 2008
@@ -1052,25 +1052,25 @@
          sb.write(new FileOutputStream(file));
     }
 
-    /*Unknown Ptg 3C*/
+    /** Unknown Ptg 3C*/
     public void test27272_1() throws Exception {
         HSSFWorkbook wb = openSample("27272_1.xls");
         wb.getSheetAt(0);
-        assertEquals("Reference for named range ", "#REF!",wb.getNameAt(0).getReference());
+        assertEquals("Reference for named range ", "Compliance!#REF!",wb.getNameAt(0).getReference());
         File outF = File.createTempFile("bug27272_1",".xls");
         wb.write(new FileOutputStream(outF));
         System.out.println("Open "+outF.getAbsolutePath()+" in Excel");
     }
-    /*Unknown Ptg 3D*/
+    /** Unknown Ptg 3D*/
     public void test27272_2() throws Exception {
         HSSFWorkbook wb = openSample("27272_2.xls");
-        assertEquals("Reference for named range ", "#REF!",wb.getNameAt(0).getReference());
+        assertEquals("Reference for named range ", "'LOAD.POD_HISTORIES'!#REF!",wb.getNameAt(0).getReference());
         File outF = File.createTempFile("bug27272_2",".xls");
         wb.write(new FileOutputStream(outF));
         System.out.println("Open "+outF.getAbsolutePath()+" in Excel");
     }
 
-    /* MissingArgPtg */
+    /** MissingArgPtg */
     public void testMissingArgPtg() throws Exception {
         HSSFWorkbook wb = new HSSFWorkbook();
         HSSFCell cell = wb.createSheet("Sheet1").createRow(4).createCell(0);

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestNamedRange.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestNamedRange.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestNamedRange.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestNamedRange.java Tue Sep 16 13:17:30 2008
@@ -476,7 +476,7 @@
 
 		HSSFName name2 = wb.getNameAt(1);
 		assertEquals("b", name2.getNameName());
-		assertEquals("#REF!", name2.getReference());
+		assertEquals("Sheet1!#REF!", name2.getReference());
 		assertTrue(name2.isDeleted());
 		try {
 			AreaReference ref2 = new AreaReference(name2.getReference());

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestSheetShiftRows.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestSheetShiftRows.java?rev=696038&r1=696037&r2=696038&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestSheetShiftRows.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestSheetShiftRows.java Tue Sep 16 13:17:30 2008
@@ -19,6 +19,10 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
 
 import junit.framework.TestCase;
 
@@ -201,36 +205,69 @@
         HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("ForShifting.xls");
 
         HSSFSheet sheet = wb.getSheet("Sheet1");
-        assertEquals(19, sheet.getLastRowNum());
-
-        assertEquals("cell B1 (ref)", sheet.getRow(0).getCell(3).getRichStringCellValue().toString());
-        assertEquals("CONCATENATE(B1,\" (ref)\")", sheet.getRow(0).getCell(3).getCellFormula());
-        assertEquals("cell B2 (ref)", sheet.getRow(1).getCell(3).getRichStringCellValue().toString());
-        assertEquals("CONCATENATE(B2,\" (ref)\")", sheet.getRow(1).getCell(3).getCellFormula());
-        assertEquals("cell B3 (ref)", sheet.getRow(2).getCell(3).getRichStringCellValue().toString());
-        assertEquals("CONCATENATE(B3,\" (ref)\")", sheet.getRow(2).getCell(3).getCellFormula());
-        assertEquals("cell B2 (ref)", sheet.getRow(6).getCell(1).getRichStringCellValue().toString());
-        assertEquals("CONCATENATE(B2,\" (ref)\")", sheet.getRow(6).getCell(1).getCellFormula());
-
+        assertEquals(20, sheet.getLastRowNum());
+        
+        confirmRow(sheet, 0, 1, 171, 1, "ROW(D1)", "100+B1", "COUNT(D1:E1)");
+        confirmRow(sheet, 1, 2, 172, 1, "ROW(D2)", "100+B2", "COUNT(D2:E2)");
+        confirmRow(sheet, 2, 3, 173, 1, "ROW(D3)", "100+B3", "COUNT(D3:E3)");
+        
+        confirmCell(sheet, 6, 1, 271, "200+B1");
+        confirmCell(sheet, 7, 1, 272, "200+B2");
+        confirmCell(sheet, 8, 1, 273, "200+B3");
+
+        confirmCell(sheet, 14, 0, 0.0, "A12"); // the cell referred to by this formula will be replaced
+        
+        // -----------
+        // Row index 1 -> 11 (row "2" -> row "12")
         sheet.shiftRows(1, 1, 10);
+        
+        // Now check what sheet looks like after move
 
-        // Row 1 => Row 11
-        // So strings on row 11 unchanged, but reference in formula is
-        assertEquals("cell B1 (ref)", sheet.getRow(0).getCell(3).getRichStringCellValue().toString());
-        assertEquals("CONCATENATE(B1,\" (ref)\")", sheet.getRow(0).getCell(3).getCellFormula());
+        // no changes on row "1"
+        confirmRow(sheet, 0, 1, 171, 1, "ROW(D1)", "100+B1", "COUNT(D1:E1)");
+        
+        // row "2" is now empty
         assertEquals(0, sheet.getRow(1).getPhysicalNumberOfCells());
 
-        // still save b2
-        assertEquals("cell B2 (ref)", sheet.getRow(11).getCell(3).getRichStringCellValue().toString());
-        // but points to b12
-        assertEquals("CONCATENATE(B12,\" (ref)\")", sheet.getRow(11).getCell(3).getCellFormula());
-
-        assertEquals("cell B3 (ref)", sheet.getRow(2).getCell(3).getRichStringCellValue().toString());
-        assertEquals("CONCATENATE(B3,\" (ref)\")", sheet.getRow(2).getCell(3).getCellFormula());
-
-        // one on a non-shifted row also updated
-        assertEquals("cell B2 (ref)", sheet.getRow(6).getCell(1).getRichStringCellValue().toString());
-        assertEquals("CONCATENATE(B12,\" (ref)\")", sheet.getRow(6).getCell(1).getCellFormula());
+        // Row "2" moved to row "12", and the formula has been updated.
+        // note however that the cached formula result (2) has not been updated. (POI differs from Excel here)
+        confirmRow(sheet, 11, 2, 172, 1, "ROW(D12)", "100+B12", "COUNT(D12:E12)");
+
+        // no changes on row "3"
+        confirmRow(sheet, 2, 3, 173, 1, "ROW(D3)", "100+B3", "COUNT(D3:E3)");
+
+        
+        confirmCell(sheet, 14, 0, 0.0, "#REF!");  
+        
+        
+        // Formulas on rows that weren't shifted:
+        confirmCell(sheet, 6, 1, 271, "200+B1");
+        confirmCell(sheet, 7, 1, 272, "200+B12"); // this one moved
+        confirmCell(sheet, 8, 1, 273, "200+B3");
+        
+        // check formulas on other sheets
+        HSSFSheet sheet2 = wb.getSheet("Sheet2");
+        confirmCell(sheet2,  0, 0, 371, "300+Sheet1!B1");
+        confirmCell(sheet2,  1, 0, 372, "300+Sheet1!B12");
+        confirmCell(sheet2,  2, 0, 373, "300+Sheet1!B3");
+        
+        confirmCell(sheet2, 11, 0, 300, "300+Sheet1!#REF!");
+        
+        
+        // Note - named ranges formulas have not been updated
+    }
+
+    private static void confirmRow(HSSFSheet sheet, int rowIx, double valA, double valB, double valC,
+                String formulaA, String formulaB, String formulaC) {
+        confirmCell(sheet, rowIx, 4, valA, formulaA);
+        confirmCell(sheet, rowIx, 5, valB, formulaB);
+        confirmCell(sheet, rowIx, 6, valC, formulaC);
+    }
+
+    private static void confirmCell(HSSFSheet sheet, int rowIx, int colIx, 
+            double expectedValue, String expectedFormula) {
+        HSSFCell cell = sheet.getRow(rowIx).getCell(colIx);
+        assertEquals(expectedValue, cell.getNumericCellValue(), 0.0);
+        assertEquals(expectedFormula, cell.getCellFormula());
     }
 }
-



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org