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/26 06:49:21 UTC

svn commit: r699178 - in /poi/trunk/src: java/org/apache/poi/hssf/record/formula/ java/org/apache/poi/hssf/record/formula/eval/ java/org/apache/poi/hssf/usermodel/ java/org/apache/poi/ss/formula/ testcases/org/apache/poi/hssf/ testcases/org/apache/poi/...

Author: josh
Date: Thu Sep 25 21:49:20 2008
New Revision: 699178

URL: http://svn.apache.org/viewvc?rev=699178&view=rev
Log:
Changed HSSFEvaluationWorkbook to avoid re-parsing cell formulas during execution. (working towards fix for bug 45865)

Added:
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/RangeEval.java
    poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/TestRangeEval.java
    poi/trunk/src/testcases/org/apache/poi/ss/formula/AllSSFormulaTests.java
    poi/trunk/src/testcases/org/apache/poi/ss/formula/TestWorkbookEvaluator.java
Modified:
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/AreaI.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java
    poi/trunk/src/java/org/apache/poi/ss/formula/OperationEvaluatorFactory.java
    poi/trunk/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java
    poi/trunk/src/testcases/org/apache/poi/hssf/HSSFTests.java
    poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/AllFormulaEvalTests.java

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/AreaI.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/AreaI.java?rev=699178&r1=699177&r2=699178&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/AreaI.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/AreaI.java Thu Sep 25 21:49:20 2008
@@ -50,10 +50,10 @@
 
 		public OffsetArea(int baseRow, int baseColumn, int relFirstRowIx, int relLastRowIx,
 				int relFirstColIx, int relLastColIx) {
-			_firstRow = baseRow + relFirstRowIx;
-			_lastRow = baseRow + relLastRowIx;
-			_firstColumn = baseColumn + relFirstColIx;
-			_lastColumn = baseColumn + relLastColIx;
+			_firstRow = baseRow + Math.min(relFirstRowIx, relLastRowIx);
+			_lastRow = baseRow + Math.max(relFirstRowIx, relLastRowIx);
+			_firstColumn = baseColumn + Math.min(relFirstColIx, relLastColIx);
+			_lastColumn = baseColumn + Math.max(relFirstColIx, relLastColIx);
 		}
 
 		public int getFirstColumn() {
@@ -72,5 +72,4 @@
 			return _lastRow;
 		}
 	}
-
 }
\ No newline at end of file

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java?rev=699178&r1=699177&r2=699178&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java Thu Sep 25 21:49:20 2008
@@ -34,13 +34,13 @@
     private final static int  SIZE = 4;
     private byte              field_1_options;
     private short             field_2_data;
-    
+
     /** only used for tAttrChoose: table of offsets to starts of args */
     private final int[] _jumpTable;
     /** only used for tAttrChoose: offset to the tFuncVar for CHOOSE() */
     private final int   _chooseFuncOffset;
-    
-    // flags 'volatile' and 'space', can be combined.  
+
+    // flags 'volatile' and 'space', can be combined.
     // OOO spec says other combinations are theoretically possible but not likely to occur.
     private static final BitField semiVolatile = BitFieldFactory.getInstance(0x01);
     private static final BitField optiIf       = BitFieldFactory.getInstance(0x02);
@@ -49,12 +49,14 @@
     private static final BitField sum          = BitFieldFactory.getInstance(0x10);
     private static final BitField baxcel       = BitFieldFactory.getInstance(0x20); // 'assignment-style formula in a macro sheet'
     private static final BitField space        = BitFieldFactory.getInstance(0x40);
-    
+
+    public static final AttrPtg SUM = new AttrPtg(0x0010, 0, null, -1);
+
     public static final class SpaceType {
         private SpaceType() {
             // no instances of this class
         }
-        
+
         /** 00H = Spaces before the next token (not allowed before tParen token) */
         public static final int SPACE_BEFORE = 0x00;
         /** 01H = Carriage returns before the next token (not allowed before tParen token) */
@@ -75,7 +77,7 @@
         _jumpTable = null;
         _chooseFuncOffset = -1;
     }
-    
+
     public AttrPtg(RecordInputStream in)
     {
         field_1_options = in.readByte();
@@ -92,7 +94,7 @@
             _jumpTable = null;
             _chooseFuncOffset = -1;
         }
-        
+
     }
     private AttrPtg(int options, int data, int[] jt, int chooseFuncOffset) {
         field_1_options = (byte) options;
@@ -100,7 +102,7 @@
         _jumpTable = jt;
         _chooseFuncOffset = chooseFuncOffset;
     }
-    
+
     /**
      * @param type a constant from <tt>SpaceType</tt>
      * @param count the number of space characters
@@ -145,7 +147,7 @@
     {
         return sum.isSet(getOptions());
     }
-    
+
     public void setSum(boolean bsum) {
         field_1_options=sum.setByteBoolean(field_1_options,bsum);
     }
@@ -155,13 +157,13 @@
     }
 
     /**
-     * Flags this ptg as a goto/jump 
+     * Flags this ptg as a goto/jump
      * @param isGoto
      */
     public void setGoto(boolean isGoto) {
         field_1_options=optGoto.setByteBoolean(field_1_options, isGoto);
     }
-    
+
     // lets hope no one uses this anymore
     public boolean isBaxcel()
     {
@@ -201,7 +203,7 @@
         } else if(isOptimizedChoose()) {
             sb.append("choose nCases=").append(getData());
         } else if(isGoto()) {
-            sb.append("skip dist=").append(getData()); 
+            sb.append("skip dist=").append(getData());
         } else if(isSum()) {
             sb.append("sum ");
         } else if(isBaxcel()) {
@@ -218,7 +220,7 @@
         LittleEndian.putShort(array,offset+2, field_2_data);
         int[] jt = _jumpTable;
         if (jt != null) {
-            int joff = offset+4; 
+            int joff = offset+4;
             LittleEndian.putUShort(array, joff, _chooseFuncOffset);
             joff+=2;
             for (int i = 0; i < jt.length; i++) {
@@ -227,7 +229,7 @@
             }
             LittleEndian.putUShort(array, joff, _chooseFuncOffset);
         }
-        
+
     }
 
     public int getSize()
@@ -249,7 +251,7 @@
             return toFormulaString() + "(" + operands[ 0 ] + ")";
         }
     }
-  
+
 
     public int getNumberOfOperands()
     {
@@ -260,7 +262,7 @@
     {
         return -1;
     }
-        
+
    public String toFormulaString() {
       if(semiVolatile.isSet(field_1_options)) {
         return "ATTR(semiVolatile)";

Added: poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/RangeEval.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/RangeEval.java?rev=699178&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/RangeEval.java (added)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/RangeEval.java Thu Sep 25 21:49:20 2008
@@ -0,0 +1,71 @@
+/* ====================================================================
+   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.eval;
+
+
+/**
+ * 
+ * @author Josh Micich 
+ */
+public final class RangeEval implements OperationEval {
+
+	public static final OperationEval instance = new RangeEval();
+	
+	private RangeEval() {
+	}
+
+	public Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
+		if(args.length != 2) {
+			return ErrorEval.VALUE_INVALID;
+		}
+
+		try {
+			RefEval reA = evaluateRef(args[0]);
+			RefEval reB = evaluateRef(args[1]);
+			return resolveRange(reA, reB);
+		} catch (EvaluationException e) {
+			return e.getErrorEval();
+		}
+	}
+
+	private static AreaEval resolveRange(RefEval reA, RefEval reB) {
+		
+		int height = reB.getRow() - reA.getRow();
+		int width = reB.getColumn() - reA.getColumn();
+		
+		return reA.offset(0, height, 0, width);
+	}
+
+	private static RefEval evaluateRef(Eval arg) throws EvaluationException {
+		if (arg instanceof RefEval) {
+			return (RefEval) arg;
+		}
+		if (arg instanceof ErrorEval) {
+			throw new EvaluationException((ErrorEval)arg);
+		}
+		throw new IllegalArgumentException("Unexpected ref arg class (" + arg.getClass().getName() + ")");
+	}
+
+	public int getNumberOfOperands() {
+		return 2;
+	}
+
+	public int getType() {
+		throw new RuntimeException("obsolete code should not be called");
+	}
+}

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java?rev=699178&r1=699177&r2=699178&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java Thu Sep 25 21:49:20 2008
@@ -2,7 +2,9 @@
 
 import org.apache.poi.hssf.model.HSSFFormulaParser;
 import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.record.FormulaRecord;
 import org.apache.poi.hssf.record.NameRecord;
+import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
 import org.apache.poi.hssf.record.formula.NamePtg;
 import org.apache.poi.hssf.record.formula.NameXPtg;
 import org.apache.poi.hssf.record.formula.Ptg;
@@ -94,7 +96,14 @@
 		return new Name(_iBook.getNameRecord(ix), ix);
 	}
 	public Ptg[] getFormulaTokens(HSSFCell cell) {
-		return HSSFFormulaParser.parse(cell.getCellFormula(), _uBook);
+		if (false) {
+			// re-parsing the formula text also works, but is a waste of time
+			// It is useful from time to time to run all unit tests with this code
+			// to make sure that all formulas POI can evaluate can also be parsed.
+			return HSSFFormulaParser.parse(cell.getCellFormula(), _uBook);
+		}
+		FormulaRecord fr = ((FormulaRecordAggregate) cell.getCellValueRecord()).getFormulaRecord();
+		return fr.getParsedExpression();
 	}
 
 	private static final class Name implements EvaluationName {

Modified: poi/trunk/src/java/org/apache/poi/ss/formula/OperationEvaluatorFactory.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/formula/OperationEvaluatorFactory.java?rev=699178&r1=699177&r2=699178&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/formula/OperationEvaluatorFactory.java (original)
+++ poi/trunk/src/java/org/apache/poi/ss/formula/OperationEvaluatorFactory.java Thu Sep 25 21:49:20 2008
@@ -40,6 +40,7 @@
 import org.apache.poi.hssf.record.formula.PercentPtg;
 import org.apache.poi.hssf.record.formula.PowerPtg;
 import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.record.formula.RangePtg;
 import org.apache.poi.hssf.record.formula.SubtractPtg;
 import org.apache.poi.hssf.record.formula.UnaryMinusPtg;
 import org.apache.poi.hssf.record.formula.UnaryPlusPtg;
@@ -57,6 +58,7 @@
 import org.apache.poi.hssf.record.formula.eval.OperationEval;
 import org.apache.poi.hssf.record.formula.eval.PercentEval;
 import org.apache.poi.hssf.record.formula.eval.PowerEval;
+import org.apache.poi.hssf.record.formula.eval.RangeEval;
 import org.apache.poi.hssf.record.formula.eval.SubtractEval;
 import org.apache.poi.hssf.record.formula.eval.UnaryMinusEval;
 import org.apache.poi.hssf.record.formula.eval.UnaryPlusEval;
@@ -101,6 +103,7 @@
 		add(m, SubtractPtg.class, SubtractEval.instance);
 		add(m, UnaryMinusPtg.class, UnaryMinusEval.instance);
 		add(m, UnaryPlusPtg.class, UnaryPlusEval.instance);
+		add(m, RangePtg.class, RangeEval.instance);
 		return m;
 	}
 

Modified: poi/trunk/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java?rev=699178&r1=699177&r2=699178&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java (original)
+++ poi/trunk/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java Thu Sep 25 21:49:20 2008
@@ -22,12 +22,18 @@
 import java.util.Stack;
 
 import org.apache.poi.hssf.record.formula.Area3DPtg;
+import org.apache.poi.hssf.record.formula.AreaErrPtg;
 import org.apache.poi.hssf.record.formula.AreaPtg;
+import org.apache.poi.hssf.record.formula.AttrPtg;
 import org.apache.poi.hssf.record.formula.BoolPtg;
 import org.apache.poi.hssf.record.formula.ControlPtg;
+import org.apache.poi.hssf.record.formula.DeletedArea3DPtg;
+import org.apache.poi.hssf.record.formula.DeletedRef3DPtg;
 import org.apache.poi.hssf.record.formula.ErrPtg;
+import org.apache.poi.hssf.record.formula.FuncVarPtg;
 import org.apache.poi.hssf.record.formula.IntPtg;
 import org.apache.poi.hssf.record.formula.MemErrPtg;
+import org.apache.poi.hssf.record.formula.MemFuncPtg;
 import org.apache.poi.hssf.record.formula.MissingArgPtg;
 import org.apache.poi.hssf.record.formula.NamePtg;
 import org.apache.poi.hssf.record.formula.NameXPtg;
@@ -35,6 +41,7 @@
 import org.apache.poi.hssf.record.formula.OperationPtg;
 import org.apache.poi.hssf.record.formula.Ptg;
 import org.apache.poi.hssf.record.formula.Ref3DPtg;
+import org.apache.poi.hssf.record.formula.RefErrorPtg;
 import org.apache.poi.hssf.record.formula.RefPtg;
 import org.apache.poi.hssf.record.formula.StringPtg;
 import org.apache.poi.hssf.record.formula.UnionPtg;
@@ -181,10 +188,10 @@
 				isPlainFormulaCell = false;
 				Ptg[] ptgs = _workbook.getFormulaTokens(srcCell);
 				if(evalListener == null) {
-					result = evaluateCell(sheetIndex, rowIndex, (short)columnIndex, ptgs, tracker);
+					result = evaluateFormula(sheetIndex, rowIndex, (short)columnIndex, ptgs, tracker);
 				} else {
 					evalListener.onStartEvaluate(sheetIndex, rowIndex, columnIndex, ptgs);
-					result = evaluateCell(sheetIndex, rowIndex, (short)columnIndex, ptgs, tracker);
+					result = evaluateFormula(sheetIndex, rowIndex, (short)columnIndex, ptgs, tracker);
 					evalListener.onEndEvaluate(sheetIndex, rowIndex, columnIndex, result);
 				}
 			}
@@ -225,17 +232,31 @@
 		}
 		throw new RuntimeException("Unexpected cell type (" + cellType + ")");
 	}
-	private ValueEval evaluateCell(int sheetIndex, int srcRowNum, short srcColNum, Ptg[] ptgs, EvaluationTracker tracker) {
+	// visibility raised for testing
+	/* package */ ValueEval evaluateFormula(int sheetIndex, int srcRowNum, int srcColNum, Ptg[] ptgs, EvaluationTracker tracker) {
 
 		Stack stack = new Stack();
 		for (int i = 0, iSize = ptgs.length; i < iSize; i++) {
 
 			// since we don't know how to handle these yet :(
 			Ptg ptg = ptgs[i];
+			if (ptg instanceof AttrPtg) {
+				AttrPtg attrPtg = (AttrPtg) ptg;
+				if (attrPtg.isSum()) {
+					// Excel prefers to encode 'SUM()' as a tAttr token, but this evaluator
+					// expects the equivalent function token
+					byte nArgs = 1;  // tAttrSum always has 1 parameter
+					ptg = new FuncVarPtg("SUM", nArgs); 
+				}
+			}
 			if (ptg instanceof ControlPtg) {
 				// skip Parentheses, Attr, etc
 				continue;
 			}
+			if (ptg instanceof MemFuncPtg) {
+				// can ignore, rest of tokens for this expression are in OK RPN order
+				continue;
+			}
 			if (ptg instanceof MemErrPtg) { continue; }
 			if (ptg instanceof MissingArgPtg) {
 				// TODO - might need to push BlankEval or MissingArgEval
@@ -289,7 +310,7 @@
 	 * @return a <tt>NumberEval</tt>, <tt>StringEval</tt>, <tt>BoolEval</tt>,
 	 *  <tt>BlankEval</tt> or <tt>ErrorEval</tt>. Never <code>null</code>.
 	 */
-	private static ValueEval dereferenceValue(ValueEval evaluationResult, int srcRowNum, short srcColNum) {
+	private static ValueEval dereferenceValue(ValueEval evaluationResult, int srcRowNum, int srcColNum) {
 		if (evaluationResult instanceof RefEval) {
 			RefEval rv = (RefEval) evaluationResult;
 			return rv.getInnerValueEval();
@@ -361,6 +382,10 @@
 		if (ptg instanceof ErrPtg) {
 			return ErrorEval.valueOf(((ErrPtg) ptg).getErrorCode());
 		}
+		if (ptg instanceof AreaErrPtg ||ptg instanceof RefErrorPtg 
+				|| ptg instanceof DeletedArea3DPtg || ptg instanceof DeletedRef3DPtg) {
+				return ErrorEval.REF_INVALID;
+		}
 		if (ptg instanceof Ref3DPtg) {
 			Ref3DPtg refPtg = (Ref3DPtg) ptg;
 			int otherSheetIndex = _workbook.convertFromExternSheetIndex(refPtg.getExternSheetIndex());

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/HSSFTests.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/HSSFTests.java?rev=699178&r1=699177&r2=699178&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/HSSFTests.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/HSSFTests.java Thu Sep 25 21:49:20 2008
@@ -28,7 +28,7 @@
 import org.apache.poi.hssf.record.AllRecordTests;
 import org.apache.poi.hssf.usermodel.AllUserModelTests;
 import org.apache.poi.hssf.util.AllHSSFUtilTests;
-import org.apache.poi.ss.formula.TestEvaluationCache;
+import org.apache.poi.ss.formula.AllSSFormulaTests;
 
 /**
  * Test Suite for all sub-packages of org.apache.poi.hssf<br/>
@@ -53,7 +53,7 @@
         }
         suite.addTest(new TestSuite(TestEventRecordFactory.class));
         suite.addTest(new TestSuite(TestModelFactory.class));
-        suite.addTest(new TestSuite(TestEvaluationCache.class));
+        suite.addTest(AllSSFormulaTests.suite());
         return suite;
     }
 }

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/AllFormulaEvalTests.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/AllFormulaEvalTests.java?rev=699178&r1=699177&r2=699178&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/AllFormulaEvalTests.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/AllFormulaEvalTests.java Thu Sep 25 21:49:20 2008
@@ -37,6 +37,7 @@
 		result.addTestSuite(TestFormulaBugs.class);
 		result.addTestSuite(TestFormulasFromSpreadsheet.class);
 		result.addTestSuite(TestPercentEval.class);
+		result.addTestSuite(TestRangeEval.class);
 		result.addTestSuite(TestUnaryPlusEval.class);
 		return result;
 	}

Added: poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/TestRangeEval.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/TestRangeEval.java?rev=699178&view=auto
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/TestRangeEval.java (added)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/TestRangeEval.java Thu Sep 25 21:49:20 2008
@@ -0,0 +1,95 @@
+/* ====================================================================
+   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.eval;
+
+import org.apache.poi.hssf.record.formula.AreaI;
+import org.apache.poi.hssf.record.formula.AreaI.OffsetArea;
+import org.apache.poi.hssf.util.AreaReference;
+import org.apache.poi.hssf.util.CellReference;
+
+import junit.framework.TestCase;
+
+/**
+ * Test for unary plus operator evaluator.
+ *
+ * @author Josh Micich
+ */
+public final class TestRangeEval extends TestCase {
+	
+	public void testPermutations() {
+		
+		confirm("B3", "D7", "B3:D7");
+		confirm("B1", "B1", "B1:B1");
+		
+		confirm("B7", "D3", "B3:D7");
+		confirm("D3", "B7", "B3:D7");
+		confirm("D7", "B3", "B3:D7");
+	}
+
+	private static void confirm(String refA, String refB, String expectedAreaRef) {
+		
+		Eval[] args = {
+			createRefEval(refA),	
+			createRefEval(refB),	
+		};
+		AreaReference ar = new AreaReference(expectedAreaRef);
+		Eval result = RangeEval.instance.evaluate(args, 0, (short)0);
+		assertTrue(result instanceof AreaEval);
+		AreaEval ae = (AreaEval) result;
+		assertEquals(ar.getFirstCell().getRow(), ae.getFirstRow());
+		assertEquals(ar.getLastCell().getRow(), ae.getLastRow());
+		assertEquals(ar.getFirstCell().getCol(), ae.getFirstColumn());
+		assertEquals(ar.getLastCell().getCol(), ae.getLastColumn());
+	}
+
+	private static Eval createRefEval(String refStr) {
+		CellReference cr = new CellReference(refStr);
+		return new MockRefEval(cr.getRow(), cr.getCol());
+		
+	}
+
+	private static final class MockRefEval extends RefEvalBase {
+
+		public MockRefEval(int rowIndex, int columnIndex) {
+			super(rowIndex, columnIndex);
+		}
+		public ValueEval getInnerValueEval() {
+			throw new RuntimeException("not expected to be called during this test");
+		}
+		public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx,
+				int relLastColIx) {
+			AreaI area = new OffsetArea(getRow(), getColumn(),
+					relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
+			return new MockAreaEval(area);
+		}
+	}
+
+	private static final class MockAreaEval extends AreaEvalBase {
+
+		public MockAreaEval(AreaI ptg) {
+			super(ptg);
+		}
+		public ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex) {
+			throw new RuntimeException("not expected to be called during this test");
+		}
+		public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx,
+				int relLastColIx) {
+			throw new RuntimeException("not expected to be called during this test");
+		}
+	}
+}

Added: poi/trunk/src/testcases/org/apache/poi/ss/formula/AllSSFormulaTests.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/ss/formula/AllSSFormulaTests.java?rev=699178&view=auto
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/ss/formula/AllSSFormulaTests.java (added)
+++ poi/trunk/src/testcases/org/apache/poi/ss/formula/AllSSFormulaTests.java Thu Sep 25 21:49:20 2008
@@ -0,0 +1,34 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.ss.formula;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+/**
+ * Test suite for org.apache.poi.ss.formula
+ * 
+ * @author Josh Micich
+ */
+public final class AllSSFormulaTests {
+    public static Test suite() {
+        TestSuite result = new TestSuite(AllSSFormulaTests.class.getName());
+        result.addTestSuite(TestEvaluationCache.class);
+        result.addTestSuite(TestWorkbookEvaluator.class);
+        return result;
+    }
+}

Added: poi/trunk/src/testcases/org/apache/poi/ss/formula/TestWorkbookEvaluator.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/ss/formula/TestWorkbookEvaluator.java?rev=699178&view=auto
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/ss/formula/TestWorkbookEvaluator.java (added)
+++ poi/trunk/src/testcases/org/apache/poi/ss/formula/TestWorkbookEvaluator.java Thu Sep 25 21:49:20 2008
@@ -0,0 +1,92 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.ss.formula;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.record.formula.AreaErrPtg;
+import org.apache.poi.hssf.record.formula.AttrPtg;
+import org.apache.poi.hssf.record.formula.DeletedArea3DPtg;
+import org.apache.poi.hssf.record.formula.DeletedRef3DPtg;
+import org.apache.poi.hssf.record.formula.IntPtg;
+import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.record.formula.RefErrorPtg;
+import org.apache.poi.hssf.record.formula.eval.ErrorEval;
+import org.apache.poi.hssf.record.formula.eval.NumberEval;
+import org.apache.poi.hssf.record.formula.eval.ValueEval;
+
+/**
+ * Tests {@link WorkbookEvaluator}. 
+ *
+ * @author Josh Micich
+ */
+public class TestWorkbookEvaluator extends TestCase {
+	
+	/**
+	 * Make sure that the evaluator can directly handle tAttrSum (instead of relying on re-parsing
+	 * the whole formula which converts tAttrSum to tFuncVar("SUM") ) 
+	 */
+	public void testAttrSum() {
+		
+		Ptg[] ptgs = {
+			new IntPtg(42),
+			AttrPtg.SUM,
+		};
+		
+		ValueEval result = new WorkbookEvaluator(null).evaluateFormula(0, 0, 0, ptgs, null);
+		assertEquals(42, ((NumberEval)result).getNumberValue(), 0.0);
+	}
+	
+	/**
+	 * Make sure that the evaluator can directly handle (deleted) ref error tokens
+	 * (instead of relying on re-parsing the whole formula which converts these 
+	 * to the error constant #REF! ) 
+	 */
+	public void testRefErr() {
+		
+		confirmRefErr(new RefErrorPtg());
+		confirmRefErr(new AreaErrPtg());
+		confirmRefErr(new DeletedRef3DPtg(0));
+		confirmRefErr(new DeletedArea3DPtg(0));
+	}
+	private static void confirmRefErr(Ptg ptg) {
+		Ptg[] ptgs = {
+			ptg,
+		};
+		
+		ValueEval result = new WorkbookEvaluator(null).evaluateFormula(0, 0, 0, ptgs, null);
+		assertEquals(ErrorEval.REF_INVALID, result);
+	}
+	
+	/**
+	 * Make sure that the evaluator can directly handle tAttrSum (instead of relying on re-parsing
+	 * the whole formula which converts tAttrSum to tFuncVar("SUM") ) 
+	 */
+	public void testMemFunc() {
+		
+		Ptg[] ptgs = {
+			new IntPtg(42),
+			AttrPtg.SUM,
+		};
+		
+		ValueEval result = new WorkbookEvaluator(null).evaluateFormula(0, 0, 0, ptgs, null);
+		assertEquals(42, ((NumberEval)result).getNumberValue(), 0.0);
+	}
+	
+	
+}



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