true 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() + ")");
+ }
+}
diff --git a/src/java/org/apache/poi/hssf/record/formula/Ref2DPtgBase.java b/src/java/org/apache/poi/hssf/record/formula/Ref2DPtgBase.java
new file mode 100644
index 000000000..2fff41d6b
--- /dev/null
+++ b/src/java/org/apache/poi/hssf/record/formula/Ref2DPtgBase.java
@@ -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.ss.usermodel.Workbook;
+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(Workbook 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();
+ }
+}
diff --git a/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java b/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java
index e72cbbc30..308e9f0b5 100644
--- a/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java
+++ b/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java
@@ -18,12 +18,8 @@
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.record.RecordInputStream;
-import org.apache.poi.hssf.util.RangeAddress;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.ss.util.SheetReferences;
-import org.apache.poi.util.BitField;
-import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndian;
/**
@@ -34,49 +30,36 @@ import org.apache.poi.util.LittleEndian;
* @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 ) {
CellReference c= new CellReference(cellref);
setRow(c.getRow());
- setColumn((short)c.getCol());
+ setColumn(c.getCol());
setColRelative(!c.isColAbsolute());
setRowRelative(!c.isRowAbsolute());
setExternSheetIndex(externIdx);
}
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();
}
@@ -84,8 +67,7 @@ public final class Ref3DPtg extends OperandPtg {
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() {
@@ -100,83 +82,11 @@ public final class Ref3DPtg extends OperandPtg {
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(Workbook 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(Workbook book) {
+ return ExternSheetNameResolver.prependSheetName(book, field_1_index_extern_sheet, formatReferenceAsString());
}
-
- public byte getDefaultOperandClass() {
- return Ptg.CLASS_REF;
- }
}
diff --git a/src/java/org/apache/poi/hssf/record/formula/RefErrorPtg.java b/src/java/org/apache/poi/hssf/record/formula/RefErrorPtg.java
index 6adbe43c5..a3030e1bd 100755
--- a/src/java/org/apache/poi/hssf/record/formula/RefErrorPtg.java
+++ b/src/java/org/apache/poi/hssf/record/formula/RefErrorPtg.java
@@ -18,6 +18,7 @@
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.ss.usermodel.ErrorConstants;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.LittleEndian;
@@ -28,48 +29,32 @@ import org.apache.poi.util.LittleEndian;
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(Workbook book)
- {
- //TODO -- should we store a cellreference instance in this ptg?? but .. memory is an issue, i believe!
- return "#REF!";
+ public String toFormulaString(Workbook book) {
+ return ErrorConstants.getText(ErrorConstants.ERROR_REF);
}
public byte getDefaultOperandClass() {
diff --git a/src/java/org/apache/poi/hssf/record/formula/RefNPtg.java b/src/java/org/apache/poi/hssf/record/formula/RefNPtg.java
index 5ef4a413b..07114265d 100644
--- a/src/java/org/apache/poi/hssf/record/formula/RefNPtg.java
+++ b/src/java/org/apache/poi/hssf/record/formula/RefNPtg.java
@@ -23,16 +23,14 @@ import org.apache.poi.hssf.record.RecordInputStream;
* 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;
+ }
}
diff --git a/src/java/org/apache/poi/hssf/record/formula/RefPtg.java b/src/java/org/apache/poi/hssf/record/formula/RefPtg.java
index a324ce70f..94a1b3301 100644
--- a/src/java/org/apache/poi/hssf/record/formula/RefPtg.java
+++ b/src/java/org/apache/poi/hssf/record/formula/RefPtg.java
@@ -24,30 +24,26 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @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;
}
-
}
diff --git a/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java b/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java
index 33dff9ec0..f04ec0ac8 100644
--- a/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java
+++ b/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java
@@ -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.ss.util.CellReference;
-import org.apache.poi.ss.usermodel.Workbook;
-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 @@ import org.apache.poi.hssf.record.RecordInputStream;
*/
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,30 +67,15 @@ public abstract class RefPtgBase extends OperandPtg {
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();
+ protected final void writeCoordinates(byte[] array, int offset) {
+ LittleEndian.putUShort(array, offset + 0, field_1_row);
+ LittleEndian.putUShort(array, offset + 2, field_2_col);
}
- 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 abstract byte getSid();
-
public final void setRow(int row) {
if(row < 0 || row >= MAX_ROW_NUMBER) {
throw new IllegalArgumentException("The row number, when specified as an integer, must be between 0 and " + MAX_ROW_NUMBER);
@@ -102,18 +84,11 @@ public abstract class RefPtgBase extends OperandPtg {
}
/**
- * 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 @@ public abstract class RefPtgBase extends OperandPtg {
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);
+ return column.getValue(field_2_col);
}
-
- public final int getSize() {
- return SIZE;
- }
-
- public final String toFormulaString(Workbook 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() {
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
index 1f88cce2b..4fbedb874 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
@@ -300,7 +300,7 @@ public class HSSFCell implements Cell {
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);
@@ -600,12 +600,6 @@ public class HSSFCell implements Cell {
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());
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFName.java b/src/java/org/apache/poi/hssf/usermodel/HSSFName.java
index 4fde9e6cc..6de229379 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFName.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFName.java
@@ -126,8 +126,16 @@ public class HSSFName implements Name {
* @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();
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
index 4d6a1f725..231942f44 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
@@ -31,7 +31,6 @@ import java.util.List;
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.SCLRecord;
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.PaneInformation;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
@@ -1180,33 +1178,26 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
* @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
@@ -1236,7 +1227,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
// 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 );
@@ -1263,49 +1254,21 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
// Update any formulas on this sheet that point to
// rows which have been moved
- updateFormulasAfterShift(startRow, endRow, n);
- }
+ int sheetIndex = workbook.getSheetIndex(this);
+ short externSheetIndex = book.checkExternSheet(sheetIndex);
+ FormulaShifter shifter = FormulaShifter.createForRowShift(externSheetIndex, startRow, endRow, n);
+ sheet.getRowsAggregate().updateFormulasAfterRowShift(shifter, externSheetIndex);
- /**
- * 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
*
@@ -1384,20 +1400,6 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
return result;
}
- /**
- * @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
*
diff --git a/src/testcases/org/apache/poi/hssf/data/ForShifting.xls b/src/testcases/org/apache/poi/hssf/data/ForShifting.xls
index 13e5920e5..7cb3ebd7d 100755
Binary files a/src/testcases/org/apache/poi/hssf/data/ForShifting.xls and b/src/testcases/org/apache/poi/hssf/data/ForShifting.xls differ
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/AllFormulaTests.java b/src/testcases/org/apache/poi/hssf/record/formula/AllFormulaTests.java
index a685fd2cb..5f63f31a0 100644
--- a/src/testcases/org/apache/poi/hssf/record/formula/AllFormulaTests.java
+++ b/src/testcases/org/apache/poi/hssf/record/formula/AllFormulaTests.java
@@ -43,6 +43,7 @@ public final class AllFormulaTests {
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);
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/TestFormulaShifter.java b/src/testcases/org/apache/poi/hssf/record/formula/TestFormulaShifter.java
new file mode 100644
index 000000000..55f79e6df
--- /dev/null
+++ b/src/testcases/org/apache/poi/hssf/record/formula/TestFormulaShifter.java
@@ -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);
+ }
+}
diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestFormulas.java b/src/testcases/org/apache/poi/hssf/usermodel/TestFormulas.java
index 36eaf92f3..397c1e52c 100644
--- a/src/testcases/org/apache/poi/hssf/usermodel/TestFormulas.java
+++ b/src/testcases/org/apache/poi/hssf/usermodel/TestFormulas.java
@@ -1052,25 +1052,25 @@ public final class TestFormulas extends TestCase {
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);
diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestNamedRange.java b/src/testcases/org/apache/poi/hssf/usermodel/TestNamedRange.java
index f3430d8bc..b3afee5bf 100644
--- a/src/testcases/org/apache/poi/hssf/usermodel/TestNamedRange.java
+++ b/src/testcases/org/apache/poi/hssf/usermodel/TestNamedRange.java
@@ -476,7 +476,7 @@ public final class TestNamedRange extends TestCase {
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());
diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestSheetShiftRows.java b/src/testcases/org/apache/poi/hssf/usermodel/TestSheetShiftRows.java
index 101bd325d..ccd92298d 100755
--- a/src/testcases/org/apache/poi/hssf/usermodel/TestSheetShiftRows.java
+++ b/src/testcases/org/apache/poi/hssf/usermodel/TestSheetShiftRows.java
@@ -19,6 +19,10 @@ package org.apache.poi.hssf.usermodel;
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 @@ public final class TestSheetShiftRows extends TestCase {
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());
+ // 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)");
- assertEquals("cell B3 (ref)", sheet.getRow(2).getCell(3).getRichStringCellValue().toString());
- assertEquals("CONCATENATE(B3,\" (ref)\")", sheet.getRow(2).getCell(3).getCellFormula());
+ // no changes on row "3"
+ confirmRow(sheet, 2, 3, 173, 1, "ROW(D3)", "100+B3", "COUNT(D3:E3)");
- // 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());
+
+ 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());
}
}
-