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

svn commit: r692932 [3/4] - in /poi/branches/ooxml: ./ src/documentation/content/xdocs/ src/java/org/apache/poi/ddf/ src/java/org/apache/poi/hssf/model/ src/java/org/apache/poi/hssf/record/ src/java/org/apache/poi/hssf/record/formula/ src/java/org/apac...

Added: poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/OperationEvaluatorFactory.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/OperationEvaluatorFactory.java?rev=692932&view=auto
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/OperationEvaluatorFactory.java (added)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/OperationEvaluatorFactory.java Sun Sep  7 13:11:32 2008
@@ -0,0 +1,184 @@
+/* ====================================================================
+   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.usermodel;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.poi.hssf.record.formula.AddPtg;
+import org.apache.poi.hssf.record.formula.ConcatPtg;
+import org.apache.poi.hssf.record.formula.DividePtg;
+import org.apache.poi.hssf.record.formula.EqualPtg;
+import org.apache.poi.hssf.record.formula.ExpPtg;
+import org.apache.poi.hssf.record.formula.FuncPtg;
+import org.apache.poi.hssf.record.formula.FuncVarPtg;
+import org.apache.poi.hssf.record.formula.GreaterEqualPtg;
+import org.apache.poi.hssf.record.formula.GreaterThanPtg;
+import org.apache.poi.hssf.record.formula.LessEqualPtg;
+import org.apache.poi.hssf.record.formula.LessThanPtg;
+import org.apache.poi.hssf.record.formula.MultiplyPtg;
+import org.apache.poi.hssf.record.formula.NotEqualPtg;
+import org.apache.poi.hssf.record.formula.OperationPtg;
+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.SubtractPtg;
+import org.apache.poi.hssf.record.formula.UnaryMinusPtg;
+import org.apache.poi.hssf.record.formula.UnaryPlusPtg;
+import org.apache.poi.hssf.record.formula.eval.AddEval;
+import org.apache.poi.hssf.record.formula.eval.ConcatEval;
+import org.apache.poi.hssf.record.formula.eval.DivideEval;
+import org.apache.poi.hssf.record.formula.eval.EqualEval;
+import org.apache.poi.hssf.record.formula.eval.FuncVarEval;
+import org.apache.poi.hssf.record.formula.eval.GreaterEqualEval;
+import org.apache.poi.hssf.record.formula.eval.GreaterThanEval;
+import org.apache.poi.hssf.record.formula.eval.LessEqualEval;
+import org.apache.poi.hssf.record.formula.eval.LessThanEval;
+import org.apache.poi.hssf.record.formula.eval.MultiplyEval;
+import org.apache.poi.hssf.record.formula.eval.NotEqualEval;
+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.SubtractEval;
+import org.apache.poi.hssf.record.formula.eval.UnaryMinusEval;
+import org.apache.poi.hssf.record.formula.eval.UnaryPlusEval;
+
+/**
+ * This class creates <tt>OperationEval</tt> instances to help evaluate <tt>OperationPtg</tt>
+ * formula tokens.
+ * 
+ * @author Josh Micich
+ */
+final class OperationEvaluatorFactory {
+	private static final Class[] OPERATION_CONSTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class };
+	// TODO - use singleton instances directly instead of reflection
+	private static final Map _constructorsByPtgClass = initialiseConstructorsMap();
+	private static final Map _instancesByPtgClass = initialiseInstancesMap();
+	
+	private OperationEvaluatorFactory() {
+		// no instances of this class
+	}
+	
+	private static Map initialiseConstructorsMap() {
+		Map m = new HashMap(32);
+		add(m, ConcatPtg.class, ConcatEval.class);
+		add(m, FuncPtg.class, FuncVarEval.class);
+		add(m, FuncVarPtg.class, FuncVarEval.class);
+		return m;
+	}
+	private static Map initialiseInstancesMap() {
+		Map m = new HashMap(32);
+		add(m, EqualPtg.class, EqualEval.instance);
+		add(m, GreaterEqualPtg.class, GreaterEqualEval.instance);
+		add(m, GreaterThanPtg.class, GreaterThanEval.instance);
+		add(m, LessEqualPtg.class, LessEqualEval.instance);
+		add(m, LessThanPtg.class, LessThanEval.instance);
+		add(m, NotEqualPtg.class, NotEqualEval.instance);
+
+		add(m, AddPtg.class, AddEval.instance);
+		add(m, DividePtg.class, DivideEval.instance);
+		add(m, MultiplyPtg.class, MultiplyEval.instance);
+		add(m, PercentPtg.class, PercentEval.instance);
+		add(m, PowerPtg.class, PowerEval.instance);
+		add(m, SubtractPtg.class, SubtractEval.instance);
+		add(m, UnaryMinusPtg.class, UnaryMinusEval.instance);
+		add(m, UnaryPlusPtg.class, UnaryPlusEval.instance);
+		return m;
+	}
+
+	private static void add(Map m, Class ptgClass, OperationEval evalInstance) {
+		if(!Ptg.class.isAssignableFrom(ptgClass)) {
+			throw new IllegalArgumentException("Expected Ptg subclass");
+		}
+		m.put(ptgClass, evalInstance);
+	}
+
+	private static void add(Map m, Class ptgClass, Class evalClass) {
+		// perform some validation now, to keep later exception handlers simple
+		if(!Ptg.class.isAssignableFrom(ptgClass)) {
+			throw new IllegalArgumentException("Expected Ptg subclass");
+		}
+		
+		if(!OperationEval.class.isAssignableFrom(evalClass)) {
+			throw new IllegalArgumentException("Expected OperationEval subclass");
+		}
+		if (!Modifier.isPublic(evalClass.getModifiers())) {
+			throw new RuntimeException("Eval class must be public");
+		}
+		if (Modifier.isAbstract(evalClass.getModifiers())) {
+			throw new RuntimeException("Eval class must not be abstract");
+		}
+		
+		Constructor constructor;
+		try {
+			constructor = evalClass.getDeclaredConstructor(OPERATION_CONSTRUCTOR_CLASS_ARRAY);
+		} catch (NoSuchMethodException e) {
+			throw new RuntimeException("Missing constructor");
+		}
+		if (!Modifier.isPublic(constructor.getModifiers())) {
+			throw new RuntimeException("Eval constructor must be public");
+		}
+		m.put(ptgClass, constructor);
+	}
+
+	/**
+	 * returns the OperationEval concrete impl instance corresponding
+	 * to the supplied operationPtg
+	 */
+	public static OperationEval create(OperationPtg ptg) {
+		if(ptg == null) {
+			throw new IllegalArgumentException("ptg must not be null");
+		}
+		Object result;
+		
+		Class ptgClass = ptg.getClass();
+		
+		result = _instancesByPtgClass.get(ptgClass);
+		if (result != null) {
+			return (OperationEval) result;
+		}
+		
+		
+		Constructor constructor = (Constructor) _constructorsByPtgClass.get(ptgClass);
+		if(constructor == null) {
+			if(ptgClass == ExpPtg.class) {
+				// ExpPtg is used for array formulas and shared formulas.
+				// it is currently unsupported, and may not even get implemented here
+				throw new RuntimeException("ExpPtg currently not supported");
+			}
+			throw new RuntimeException("Unexpected operation ptg class (" + ptgClass.getName() + ")");
+		}
+		
+		Object[] initargs = { ptg };
+		try {
+			result = constructor.newInstance(initargs);
+		} catch (IllegalArgumentException e) {
+			throw new RuntimeException(e);
+		} catch (InstantiationException e) {
+			throw new RuntimeException(e);
+		} catch (IllegalAccessException e) {
+			throw new RuntimeException(e);
+		} catch (InvocationTargetException e) {
+			throw new RuntimeException(e);
+		}
+		return (OperationEval) result;
+	}
+}

Propchange: poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/OperationEvaluatorFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/OperationEvaluatorFactory.java
------------------------------------------------------------------------------
    svn:executable = *

Added: poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/EvaluationCache.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/EvaluationCache.java?rev=692932&view=auto
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/EvaluationCache.java (added)
+++ poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/EvaluationCache.java Sun Sep  7 13:11:32 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.ss.usermodel;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.poi.hssf.record.formula.eval.ValueEval;
+
+/**
+ * Performance optimisation for {@link HSSFFormulaEvaluator}. This class stores previously
+ * calculated values of already visited cells, to avoid unnecessary re-calculation when the 
+ * same cells are referenced multiple times
+ * 
+ * 
+ * @author Josh Micich
+ */
+final class EvaluationCache {
+	private static final class Key {
+
+		private final int _sheetIndex;
+		private final int _srcRowNum;
+		private final int _srcColNum;
+		private final int _hashCode;
+
+		public Key(int sheetIndex, int srcRowNum, int srcColNum) {
+			_sheetIndex = sheetIndex;
+			_srcRowNum = srcRowNum;
+			_srcColNum = srcColNum;
+			_hashCode = sheetIndex + srcRowNum + srcColNum;
+		}
+
+		public int hashCode() {
+			return _hashCode;
+		}
+
+		public boolean equals(Object obj) {
+			Key other = (Key) obj;
+			if (_hashCode != other._hashCode) {
+				return false;
+			}
+			if (_sheetIndex != other._sheetIndex) {
+				return false;
+			}
+			if (_srcRowNum != other._srcRowNum) {
+				return false;
+			}
+			if (_srcColNum != other._srcColNum) {
+				return false;
+			}
+			return true;
+		}
+	}
+
+	private final Map _valuesByKey;
+
+	/* package */EvaluationCache() {
+		_valuesByKey = new HashMap();
+	}
+
+	public ValueEval getValue(int sheetIndex, int srcRowNum, int srcColNum) {
+		Key key = new Key(sheetIndex, srcRowNum, srcColNum);
+		return (ValueEval) _valuesByKey.get(key);
+	}
+
+	public void setValue(int sheetIndex, int srcRowNum, int srcColNum, ValueEval value) {
+		Key key = new Key(sheetIndex, srcRowNum, srcColNum);
+		if (_valuesByKey.containsKey(key)) {
+			throw new RuntimeException("Already have cached value for this cell");
+		}
+		_valuesByKey.put(key, value);
+	}
+
+	/**
+	 * Should be called whenever there are changes to input cells in the evaluated workbook.
+	 */
+	public void clear() {
+		_valuesByKey.clear();
+	}
+}

Propchange: poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/EvaluationCache.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/FormulaEvaluator.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/FormulaEvaluator.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/FormulaEvaluator.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/FormulaEvaluator.java Sun Sep  7 13:11:32 2008
@@ -20,7 +20,11 @@
 import java.util.Iterator;
 import java.util.Stack;
 
+import org.apache.poi.ss.util.AreaReference;
+import org.apache.poi.ss.util.CellReference;
+
 import org.apache.poi.hssf.model.FormulaParser;
+import org.apache.poi.hssf.record.NameRecord;
 import org.apache.poi.hssf.record.formula.Area3DPtg;
 import org.apache.poi.hssf.record.formula.AreaPtg;
 import org.apache.poi.hssf.record.formula.BoolPtg;
@@ -56,17 +60,64 @@
 import org.apache.poi.hssf.record.formula.eval.ValueEval;
 
 /**
+ * Evaluates formula cells.<p/>
+ * 
+ * For performance reasons, this class keeps a cache of all previously calculated intermediate
+ * cell values.  Be sure to call {@link #clearCache()} if any workbook cells are changed between
+ * calls to evaluate~ methods on this class.
+ * 
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
- *
+ * @author Josh Micich
  */
 public class FormulaEvaluator {
+	/**
+	 * used to track the number of evaluations
+	 */
+    private static final class Counter {
+        public int value;
+        public Counter() {
+            value = 0;
+        }
+    }
 
     protected Sheet _sheet;
     protected Workbook _workbook;
+    private final EvaluationCache _cache;
+
+    private Counter _evaluationCounter;
+
 
     public FormulaEvaluator(Sheet sheet, Workbook workbook) {
+        this(sheet, workbook, new EvaluationCache(), new Counter());
+    }
+    
+    private FormulaEvaluator(Sheet sheet, Workbook workbook, EvaluationCache cache, Counter evaluationCounter) {
         _sheet = sheet;
         _workbook = workbook;
+        _cache = cache;
+        _evaluationCounter = evaluationCounter;
+    }
+
+    /**
+     * for debug use. Used in toString methods
+     */
+    public String getSheetName(Sheet sheet) {
+        return _workbook.getSheetName(_workbook.getSheetIndex(sheet));
+    }
+    /**
+     * for debug/test use
+     */
+    public int getEvaluationCount() {
+        return _evaluationCounter.value;
+    }
+
+    private static boolean isDebugLogEnabled() {
+        return false;
+    }
+    private static void logDebug(String s) {
+        if (isDebugLogEnabled()) {
+            System.out.println(s);
+        }
     }
 
     /**
@@ -75,6 +126,18 @@
      */
     public void setCurrentRow(Row row) {
         // do nothing
+        if (false) {
+            row.getClass(); // suppress unused parameter compiler warning
+        }
+    }
+
+    /**
+     * Should be called whenever there are changes to input cells in the evaluated workbook.
+     * Failure to call this method after changing cell values will cause incorrect behaviour
+     * of the evaluate~ methods of this class
+     */
+    public void clearCache() {
+        _cache.clear();
     }
 
 
@@ -102,7 +165,7 @@
                 retval.setErrorValue(cell.getErrorCellValue());
                 break;
             case Cell.CELL_TYPE_FORMULA:
-                retval = getCellValueForEval(internalEvaluate(cell, _sheet, _workbook), _workbook.getCreationHelper());
+                retval = getCellValueForEval(internalEvaluate(cell, _sheet), _workbook.getCreationHelper());
                 break;
             case Cell.CELL_TYPE_NUMERIC:
                 retval = new CellValue(Cell.CELL_TYPE_NUMERIC, _workbook.getCreationHelper());
@@ -140,7 +203,7 @@
         if (cell != null) {
             switch (cell.getCellType()) {
             case Cell.CELL_TYPE_FORMULA:
-                CellValue cv = getCellValueForEval(internalEvaluate(cell, _sheet, _workbook), _workbook.getCreationHelper());
+                CellValue cv = getCellValueForEval(internalEvaluate(cell, _sheet), _workbook.getCreationHelper());
                 switch (cv.getCellType()) {
                 case Cell.CELL_TYPE_BOOLEAN:
                     cell.setCellValue(cv.getBooleanValue());
@@ -185,7 +248,7 @@
         if (cell != null) {
             switch (cell.getCellType()) {
             case Cell.CELL_TYPE_FORMULA:
-                CellValue cv = getCellValueForEval(internalEvaluate(cell, _sheet, _workbook), _workbook.getCreationHelper());
+                CellValue cv = getCellValueForEval(internalEvaluate(cell, _sheet), _workbook.getCreationHelper());
                 switch (cv.getCellType()) {
                 case Cell.CELL_TYPE_BOOLEAN:
                     cell.setCellType(Cell.CELL_TYPE_BOOLEAN);
@@ -283,26 +346,40 @@
      * else a runtime exception will be thrown somewhere inside the method.
      * (Hence this is a private method.)
      */
-    private static ValueEval internalEvaluate(Cell srcCell, Sheet sheet, Workbook workbook) {
+    private ValueEval internalEvaluate(Cell srcCell, Sheet sheet) {
         int srcRowNum = srcCell.getRowIndex();
-        short srcColNum = srcCell.getCellNum();
+        int srcColNum = srcCell.getCellNum();
 
+        ValueEval result;
+
+        int sheetIndex = _workbook.getSheetIndex(sheet);
+        result = _cache.getValue(sheetIndex, srcRowNum, srcColNum);
+        if (result != null) {
+           return result;
+        }
+        _evaluationCounter.value++;
 
         EvaluationCycleDetector tracker = EvaluationCycleDetectorManager.getTracker();
 
-        if(!tracker.startEvaluate(workbook, sheet, srcRowNum, srcColNum)) {
+        if(!tracker.startEvaluate(_workbook, sheet, srcRowNum, srcColNum)) {
             return ErrorEval.CIRCULAR_REF_ERROR;
         }
         try {
-            return evaluateCell(workbook, sheet, srcRowNum, srcColNum, srcCell.getCellFormula());
+            result = evaluateCell(srcRowNum, (short)srcColNum, srcCell.getCellFormula());
         } finally {
-            tracker.endEvaluate(workbook, sheet, srcRowNum, srcColNum);
+            tracker.endEvaluate(_workbook, sheet, srcRowNum, srcColNum);
+            _cache.setValue(sheetIndex, srcRowNum, srcColNum, result);
         }
+        if (isDebugLogEnabled()) {
+            String sheetName = _workbook.getSheetName(sheetIndex);
+            CellReference cr = new CellReference(srcRowNum, srcColNum);
+            logDebug("Evaluated " + sheetName + "!" + cr.formatAsString() + " to " + result.toString());
+        }
+        return result;
     }
-    private static ValueEval evaluateCell(Workbook workbook, Sheet sheet,
-            int srcRowNum, short srcColNum, String cellFormulaText) {
+    private ValueEval evaluateCell(int srcRowNum, short srcColNum, String cellFormulaText) {
 
-        Ptg[] ptgs = FormulaParser.parse(cellFormulaText, workbook);
+        Ptg[] ptgs = FormulaParser.parse(cellFormulaText, _workbook);
 
         Stack stack = new Stack();
         for (int i = 0, iSize = ptgs.length; i < iSize; i++) {
@@ -314,19 +391,10 @@
                 continue;
             }
             if (ptg instanceof MemErrPtg) { continue; }
-            if (ptg instanceof MissingArgPtg) { continue; }
-            if (ptg instanceof NamePtg) {
-                // named ranges, macro functions
-                NamePtg namePtg = (NamePtg) ptg;
-                stack.push(new NameEval(namePtg.getIndex()));
-                continue;
-            }
-            if (ptg instanceof NameXPtg) {
-                NameXPtg nameXPtg = (NameXPtg) ptg;
-                stack.push(new NameXEval(nameXPtg.getSheetRefIndex(), nameXPtg.getNameIndex()));
-                continue;
+            if (ptg instanceof MissingArgPtg) {
+               // TODO - might need to push BlankEval or MissingArgEval
+               continue;
             }
-            if (ptg instanceof UnknownPtg) { continue; }
             Eval opResult;
             if (ptg instanceof OperationPtg) {
                 OperationPtg optg = (OperationPtg) ptg;
@@ -343,10 +411,15 @@
                     Eval p = (Eval) stack.pop();
                     ops[j] = p;
                 }
-                opResult = invokeOperation(operation, ops, srcRowNum, srcColNum, workbook, sheet);
+                logDebug("invoke " + operation + " (nAgs=" + numops + ")");
+                opResult = invokeOperation(operation, ops, srcRowNum, srcColNum, _workbook, _sheet);
             } else {
-                opResult = getEvalForPtg(ptg, sheet, workbook);
+                opResult = getEvalForPtg(ptg, _sheet);
             }
+            if (opResult == null) {
+                throw new RuntimeException("Evaluation result must not be null");
+            }
+            logDebug("push " + opResult);
             stack.push(opResult);
         }
 
@@ -403,28 +476,63 @@
         return operation.evaluate(ops, srcRowNum, srcColNum);
     }
 
+    private Sheet getOtherSheet(int externSheetIndex) {
+        return _workbook.getSheetAt(_workbook.getSheetIndexFromExternSheetIndex(externSheetIndex));
+    }
+    private FormulaEvaluator createEvaluatorForAnotherSheet(Sheet sheet) {
+        return new FormulaEvaluator(sheet, _workbook, _cache, _evaluationCounter);
+    }
+
     /**
      * returns an appropriate Eval impl instance for the Ptg. The Ptg must be
      * one of: Area3DPtg, AreaPtg, ReferencePtg, Ref3DPtg, IntPtg, NumberPtg,
      * StringPtg, BoolPtg <br/>special Note: OperationPtg subtypes cannot be
      * passed here!
      */
-    private static Eval getEvalForPtg(Ptg ptg, Sheet sheet, Workbook workbook) {
+    private Eval getEvalForPtg(Ptg ptg, Sheet sheet) {
+        if (ptg instanceof NamePtg) {
+            // named ranges, macro functions
+            NamePtg namePtg = (NamePtg) ptg;
+            int numberOfNames = _workbook.getNumberOfNames();
+            int nameIndex = namePtg.getIndex();
+            if(nameIndex < 0 || nameIndex >= numberOfNames) {
+                throw new RuntimeException("Bad name index (" + nameIndex
+                        + "). Allowed range is (0.." + (numberOfNames-1) + ")");
+            }
+            if(_workbook instanceof org.apache.poi.hssf.usermodel.HSSFWorkbook) { 
+				org.apache.poi.hssf.usermodel.HSSFWorkbook hssfWb = 
+					(org.apache.poi.hssf.usermodel.HSSFWorkbook)_workbook;
+				NameRecord nameRecord = hssfWb.getNameRecord(nameIndex);
+				if (nameRecord.isFunctionName()) {
+					return new NameEval(nameRecord.getNameText());
+				}
+				if (nameRecord.hasFormula()) {
+					return evaluateNameFormula(nameRecord.getNameDefinition(), sheet);
+				}
+				throw new RuntimeException("Don't know how to evalate name '" + nameRecord.getNameText() + "'");
+			} else {
+				throw new RuntimeException("Don't know how to evaluate name records for XSSF");
+			}
+        }
+        if (ptg instanceof NameXPtg) {
+            NameXPtg nameXPtg = (NameXPtg) ptg;
+            return new NameXEval(nameXPtg.getSheetRefIndex(), nameXPtg.getNameIndex());
+        }
         if (ptg instanceof RefPtg) {
-            return new LazyRefEval(((RefPtg) ptg), sheet, workbook);
+            return new LazyRefEval(((RefPtg) ptg), sheet, this);
         }
         if (ptg instanceof Ref3DPtg) {
             Ref3DPtg refPtg = (Ref3DPtg) ptg;
-            Sheet xsheet = workbook.getSheetAt(workbook.getSheetIndexFromExternSheetIndex(refPtg.getExternSheetIndex()));
-            return new LazyRefEval(refPtg, xsheet, workbook);
+            Sheet xsheet = getOtherSheet(refPtg.getExternSheetIndex());
+            return new LazyRefEval(refPtg, xsheet, createEvaluatorForAnotherSheet(xsheet));
         }
         if (ptg instanceof AreaPtg) {
-            return new LazyAreaEval(((AreaPtg) ptg), sheet, workbook);
+            return new LazyAreaEval(((AreaPtg) ptg), sheet, this);
         }
         if (ptg instanceof Area3DPtg) {
             Area3DPtg a3dp = (Area3DPtg) ptg;
-            Sheet xsheet = workbook.getSheetAt(workbook.getSheetIndexFromExternSheetIndex(a3dp.getExternSheetIndex()));
-            return new LazyAreaEval(a3dp, xsheet, workbook);
+            Sheet xsheet = getOtherSheet(a3dp.getExternSheetIndex());
+            return new LazyAreaEval(a3dp, xsheet, createEvaluatorForAnotherSheet(xsheet));
         }
 
         if (ptg instanceof IntPtg) {
@@ -442,8 +550,19 @@
         if (ptg instanceof ErrPtg) {
             return ErrorEval.valueOf(((ErrPtg) ptg).getErrorCode());
         }
+        if (ptg instanceof UnknownPtg) {
+            // TODO - remove UnknownPtg
+            throw new RuntimeException("UnknownPtg not allowed");
+        }
         throw new RuntimeException("Unexpected ptg class (" + ptg.getClass().getName() + ")");
     }
+    private Eval evaluateNameFormula(Ptg[] ptgs, Sheet sheet) {
+        if (ptgs.length > 1) {
+            throw new RuntimeException("Complex name formulas not supported yet");
+        }
+        return getEvalForPtg(ptgs[0], sheet);
+    }
+
     /**
      * Given a cell, find its type and from that create an appropriate ValueEval
      * impl instance and return that. Since the cell could be an external
@@ -453,7 +572,7 @@
      * @param sheet
      * @param workbook
      */
-    public static ValueEval getEvalForCell(Cell cell, Sheet sheet, Workbook workbook) {
+    public ValueEval getEvalForCell(Cell cell, Sheet sheet) {
 
         if (cell == null) {
             return BlankEval.INSTANCE;
@@ -464,7 +583,7 @@
             case Cell.CELL_TYPE_STRING:
                 return new StringEval(cell.getRichStringCellValue().getString());
             case Cell.CELL_TYPE_FORMULA:
-                return internalEvaluate(cell, sheet, workbook);
+                return internalEvaluate(cell, sheet);
             case Cell.CELL_TYPE_BOOLEAN:
                 return BoolEval.valueOf(cell.getBooleanCellValue());
             case Cell.CELL_TYPE_BLANK:

Modified: poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/OperationEvaluatorFactory.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/OperationEvaluatorFactory.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/OperationEvaluatorFactory.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/OperationEvaluatorFactory.java Sun Sep  7 13:11:32 2008
@@ -69,8 +69,9 @@
  */
 final class OperationEvaluatorFactory {
 	private static final Class[] OPERATION_CONSTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class };
-	
+	// TODO - use singleton instances directly instead of reflection
 	private static final Map _constructorsByPtgClass = initialiseConstructorsMap();
+	private static final Map _instancesByPtgClass = initialiseInstancesMap();
 	
 	private OperationEvaluatorFactory() {
 		// no instances of this class
@@ -78,32 +79,44 @@
 	
 	private static Map initialiseConstructorsMap() {
 		Map m = new HashMap(32);
-		add(m, AddPtg.class, AddEval.class);
 		add(m, ConcatPtg.class, ConcatEval.class);
-		add(m, DividePtg.class, DivideEval.class);
-		add(m, EqualPtg.class, EqualEval.class);
 		add(m, FuncPtg.class, FuncVarEval.class);
 		add(m, FuncVarPtg.class, FuncVarEval.class);
-		add(m, GreaterEqualPtg.class, GreaterEqualEval.class);
-		add(m, GreaterThanPtg.class, GreaterThanEval.class);
-		add(m, LessEqualPtg.class, LessEqualEval.class);
-		add(m, LessThanPtg.class, LessThanEval.class);
-		add(m, MultiplyPtg.class, MultiplyEval.class);
-		add(m, NotEqualPtg.class, NotEqualEval.class);
-		add(m, PercentPtg.class, PercentEval.class);
-		add(m, PowerPtg.class, PowerEval.class);
-		add(m, SubtractPtg.class, SubtractEval.class);
-		add(m, UnaryMinusPtg.class, UnaryMinusEval.class);
-		add(m, UnaryPlusPtg.class, UnaryPlusEval.class);
 		return m;
 	}
+	private static Map initialiseInstancesMap() {
+		Map m = new HashMap(32);
+		add(m, EqualPtg.class, EqualEval.instance);
+		add(m, GreaterEqualPtg.class, GreaterEqualEval.instance);
+		add(m, GreaterThanPtg.class, GreaterThanEval.instance);
+		add(m, LessEqualPtg.class, LessEqualEval.instance);
+		add(m, LessThanPtg.class, LessThanEval.instance);
+		add(m, NotEqualPtg.class, NotEqualEval.instance);
+
+		add(m, AddPtg.class, AddEval.instance);
+		add(m, DividePtg.class, DivideEval.instance);
+		add(m, MultiplyPtg.class, MultiplyEval.instance);
+		add(m, PercentPtg.class, PercentEval.instance);
+		add(m, PowerPtg.class, PowerEval.instance);
+		add(m, SubtractPtg.class, SubtractEval.instance);
+		add(m, UnaryMinusPtg.class, UnaryMinusEval.instance);
+		add(m, UnaryPlusPtg.class, UnaryPlusEval.instance);
+		return m;
+	}
+
+	private static void add(Map m, Class ptgClass, OperationEval evalInstance) {
+		if(!Ptg.class.isAssignableFrom(ptgClass)) {
+			throw new IllegalArgumentException("Expected Ptg subclass");
+		}
+		m.put(ptgClass, evalInstance);
+	}
 
 	private static void add(Map m, Class ptgClass, Class evalClass) {
-		
 		// perform some validation now, to keep later exception handlers simple
 		if(!Ptg.class.isAssignableFrom(ptgClass)) {
 			throw new IllegalArgumentException("Expected Ptg subclass");
 		}
+		
 		if(!OperationEval.class.isAssignableFrom(evalClass)) {
 			throw new IllegalArgumentException("Expected OperationEval subclass");
 		}
@@ -125,7 +138,7 @@
 		}
 		m.put(ptgClass, constructor);
 	}
-	
+
 	/**
 	 * returns the OperationEval concrete impl instance corresponding
 	 * to the supplied operationPtg
@@ -134,9 +147,16 @@
 		if(ptg == null) {
 			throw new IllegalArgumentException("ptg must not be null");
 		}
+		Object result;
 		
 		Class ptgClass = ptg.getClass();
 		
+		result = _instancesByPtgClass.get(ptgClass);
+		if (result != null) {
+			return (OperationEval) result;
+		}
+		
+		
 		Constructor constructor = (Constructor) _constructorsByPtgClass.get(ptgClass);
 		if(constructor == null) {
 			if(ptgClass == ExpPtg.class) {
@@ -147,7 +167,6 @@
 			throw new RuntimeException("Unexpected operation ptg class (" + ptgClass.getName() + ")");
 		}
 		
-		Object result;
 		Object[] initargs = { ptg };
 		try {
 			result = constructor.newInstance(initargs);

Modified: poi/branches/ooxml/src/java/org/apache/poi/ss/util/AreaReference.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/ss/util/AreaReference.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/ss/util/AreaReference.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/ss/util/AreaReference.java Sun Sep  7 13:11:32 2008
@@ -46,29 +46,59 @@
         }
 
         String[] parts = separateAreaRefs(reference);
+        String part0 = parts[0];
+        if (parts.length == 1) {
+            // TODO - probably shouldn't initialize area ref when text is really a cell ref
+            // Need to fix some named range stuff to get rid of this
+            _firstCell = new CellReference(part0);
+            
+            _lastCell = _firstCell;
+            _isSingleCell = true;
+            return;
+        }
+        if (parts.length != 2) {
+            throw new IllegalArgumentException("Bad area ref '" + reference + "'");
+        }
         
-        // Special handling for whole-column references
-        if(parts.length == 2 && parts[0].length() == 1 &&
-                parts[1].length() == 1 && 
-                parts[0].charAt(0) >= 'A' && parts[0].charAt(0) <= 'Z' &&
-                parts[1].charAt(0) >= 'A' && parts[1].charAt(0) <= 'Z') {
+        String part1 = parts[1];
+        if (isPlainColumn(part0)) {
+            if (!isPlainColumn(part1)) {
+                throw new RuntimeException("Bad area ref '" + reference + "'");
+            }
+            // Special handling for whole-column references
             // Represented internally as x$1 to x$65536
             //  which is the maximum range of rows
-            parts[0] = parts[0] + "$1";
-            parts[1] = parts[1] + "$65536";
-        }
-        
-        _firstCell = new CellReference(parts[0]);
-        
-        if(parts.length == 2) {
-            _lastCell = new CellReference(parts[1]);
+
+            boolean firstIsAbs = CellReference.isPartAbsolute(part0);
+            boolean lastIsAbs = CellReference.isPartAbsolute(part1);
+            
+            int col0 = CellReference.convertColStringToIndex(part0);
+            int col1 = CellReference.convertColStringToIndex(part1);
+            
+            _firstCell = new CellReference(0, col0, true, firstIsAbs);
+            _lastCell = new CellReference(0xFFFF, col1, true, lastIsAbs);
             _isSingleCell = false;
+            // TODO - whole row refs
         } else {
-            _lastCell = _firstCell;
-            _isSingleCell = true;
+            _firstCell = new CellReference(part0);
+            _lastCell = new CellReference(part1);
+            _isSingleCell = part0.equals(part1);
+       }
+     }
+    
+    private boolean isPlainColumn(String refPart) {
+        for(int i=refPart.length()-1; i>=0; i--) {
+            int ch = refPart.charAt(i);
+            if (ch == '$' && i==0) {
+            	continue;
+            }
+            if (ch < 'A' || ch > 'Z') {
+                return false;
+            }
         }
+        return true;
     }
-    
+
     /**
      * Creates an area ref from a pair of Cell References.
      */

Modified: poi/branches/ooxml/src/java/org/apache/poi/ss/util/CellReference.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/ss/util/CellReference.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/ss/util/CellReference.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/ss/util/CellReference.java Sun Sep  7 13:11:32 2008
@@ -80,7 +80,7 @@
         if (_isColAbs) {
             colRef=colRef.substring(1);
         }
-        _colIndex = convertColStringToNum(colRef);
+        _colIndex = convertColStringToIndex(colRef);
         
         String rowRef=parts[2];
         if (rowRef.length() < 1) {
@@ -94,7 +94,7 @@
     }
 
     public CellReference(int pRow, int pCol) {
-    	this(pRow, pCol, false, false);
+    	this(pRow, pCol & 0xFFFF, false, false);
     }
     public CellReference(int pRow, short pCol) {
     	this(pRow, (int)pCol, false, false);
@@ -130,18 +130,31 @@
     public String getSheetName(){
         return _sheetName;
     }
-    
+ 
+    public static boolean isPartAbsolute(String part) {
+        return part.charAt(0) == ABSOLUTE_REFERENCE_MARKER;
+    }
+
     /**
      * takes in a column reference portion of a CellRef and converts it from
      * ALPHA-26 number format to 0-based base 10.
+     * 'A' -> 0
+     * 'Z' -> 25
+     * 'AA' -> 26
+     * 'IV' -> 255
+     * @return zero based column index
      */
-    private int convertColStringToNum(String ref) {
-		int lastIx = ref.length()-1;
-		int retval=0;
-		int pos = 0;
-		
-		for (int k = lastIx; k > -1; k--) {
+    protected static int convertColStringToIndex(String ref) {
+        int pos = 0;
+        int retval=0;
+		for (int k = ref.length()-1; k >= 0; k--) {
 			char thechar = ref.charAt(k);
+            if (thechar == ABSOLUTE_REFERENCE_MARKER) {
+               if (k != 0) {
+                  throw new IllegalArgumentException("Bad col ref format '" + ref + "'");
+               }
+               break;
+            }
 			// Character.getNumericValue() returns the values
 			//  10-35 for the letter A-Z
 			int shift = (int)Math.pow(26, pos);

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hslf/record/Document.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hslf/record/Document.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hslf/record/Document.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hslf/record/Document.java Sun Sep  7 13:11:32 2008
@@ -71,27 +71,44 @@
 	 * This will normally return an array of size 2 or 3
 	 */
 	public SlideListWithText[] getSlideListWithTexts() { return slwts; }
-	/**
+
+    /**
 	 * Returns the SlideListWithText that deals with the
 	 *  Master Slides 
 	 */
 	public SlideListWithText getMasterSlideListWithText() { 
-		if(slwts.length > 0) { return slwts[0]; }
-		return null; }
+        for (int i = 0; i < slwts.length; i++) {
+            if(slwts[i].getInstance() == SlideListWithText.MASTER) {
+                return slwts[i];
+            }
+        }
+        return null;
+    }
+
 	/**
 	 * Returns the SlideListWithText that deals with the
 	 *  Slides, or null if there isn't one
 	 */
-	public SlideListWithText getSlideSlideListWithText() { 
-		if(slwts.length > 1) { return slwts[1]; }
-		return null; }
+	public SlideListWithText getSlideSlideListWithText() {
+        for (int i = 0; i < slwts.length; i++) {
+            if(slwts[i].getInstance() == SlideListWithText.SLIDES) {
+                return slwts[i];
+            }
+        }
+		return null;
+    }
 	/**
 	 * Returns the SlideListWithText that deals with the
 	 *  notes, or null if there isn't one
 	 */
 	public SlideListWithText getNotesSlideListWithText() {
-		if(slwts.length > 2) { return slwts[2]; }
-		return null; }
+        for (int i = 0; i < slwts.length; i++) {
+            if(slwts[i].getInstance() == SlideListWithText.NOTES) {
+                return slwts[i];
+            }
+        }
+		return null;
+    }
 
 
 	/** 

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hslf/record/RecordContainer.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hslf/record/RecordContainer.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hslf/record/RecordContainer.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hslf/record/RecordContainer.java Sun Sep  7 13:11:32 2008
@@ -243,8 +243,16 @@
 			moveChildRecords(oldLoc, newLoc, number);
 		}
 	}
-	
-	
+
+    /**
+     * Set child records. 
+     *
+     * @param records   the new child records
+     */
+    public void setChildRecord(Record[] records) {
+        this._children = records;
+    }
+
 	/* ===============================================================
 	 *                 External Serialisation Methods
 	 * ===============================================================

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hslf/record/SlideListWithText.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hslf/record/SlideListWithText.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hslf/record/SlideListWithText.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hslf/record/SlideListWithText.java Sun Sep  7 13:11:32 2008
@@ -50,7 +50,24 @@
 // For now, pretend to be an atom
 public class SlideListWithText extends RecordContainer
 {
-	private byte[] _header;
+
+    /**
+     * Instance filed of the record header indicates that this SlideListWithText stores
+     * references to slides
+     */
+    public static final int SLIDES = 0;
+    /**
+     * Instance filed of the record header indicates that this SlideListWithText stores
+     * references to master slides
+     */
+    public static final int MASTER = 1;
+    /**
+     * Instance filed of the record header indicates that this SlideListWithText stores
+     * references to notes
+     */
+    public static final int NOTES = 2;
+
+    private byte[] _header;
 	private static long _type = 4080;
 
 	private SlideAtomsSet[] slideAtomsSets;
@@ -123,9 +140,9 @@
 	public void addSlidePersistAtom(SlidePersistAtom spa) {
 		// Add the new SlidePersistAtom at the end
 		appendChildRecord(spa);
-		
+
 		SlideAtomsSet newSAS = new SlideAtomsSet(spa, new Record[0]);
-		
+
 		// Update our SlideAtomsSets with this
 		SlideAtomsSet[] sas = new SlideAtomsSet[slideAtomsSets.length+1];
 		System.arraycopy(slideAtomsSets, 0, sas, 0, slideAtomsSets.length);
@@ -133,7 +150,15 @@
 		slideAtomsSets = sas;
 	}
 
-	/**
+    public int getInstance(){
+        return LittleEndian.getShort(_header, 0) >> 4;
+    }
+
+    public void setInstance(int inst){
+        LittleEndian.putShort(_header, (short)((inst << 4) | 0xF));
+    }
+
+    /**
 	 * Get access to the SlideAtomsSets of the children of this record
 	 */
 	public SlideAtomsSet[] getSlideAtomsSets() { return slideAtomsSets; }
@@ -152,35 +177,6 @@
 	}
 
 	/**
-	 * Shifts a SlideAtomsSet to a new position.
-	 * Works by shifting the child records about, then updating
-	 *  the SlideAtomSets array
-	 * @param toMove The SlideAtomsSet to move
-	 * @param newPosition The new (0 based) position for the SlideAtomsSet
-	 */
-	public void repositionSlideAtomsSet(SlideAtomsSet toMove, int newPosition) {
-		// Ensure it's one of ours
-		int curPos = -1;
-		for(int i=0; i<slideAtomsSets.length; i++) {
-			if(slideAtomsSets[i] == toMove) { curPos = i; }
-		}
-		if(curPos == -1) {
-			throw new IllegalArgumentException("The supplied SlideAtomsSet didn't belong to this SlideListWithText");
-		}
-		
-		// Ensure the newPosision is valid
-		if(newPosition < 0 || newPosition >= slideAtomsSets.length) {
-			throw new IllegalArgumentException("The new position must be between 0, and the number of SlideAtomsSets");
-		}
-		
-		// Build the new records list
-		moveChildrenBefore(toMove.getSlidePersistAtom(), toMove.slideRecords.length, slideAtomsSets[newPosition].getSlidePersistAtom());
-		
-		// Build the new SlideAtomsSets list
-		ArrayUtil.arrayMoveWithin(slideAtomsSets, curPos, newPosition, 1);
-	}
-
-	/** 
 	 * Inner class to wrap up a matching set of records that hold the
 	 *  text for a given sheet. Contains the leading SlidePersistAtom,
 	 *  and all of the records until the next SlidePersistAtom. This 

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java Sun Sep  7 13:11:32 2008
@@ -536,32 +536,37 @@
 	
 	/**
 	 * Re-orders a slide, to a new position.
-	 * @param oldSlideNumer The old slide number (1 based)
+	 * @param oldSlideNumber The old slide number (1 based)
 	 * @param newSlideNumber The new slide number (1 based)
 	 */
-	public void reorderSlide(int oldSlideNumer, int newSlideNumber) {
+	public void reorderSlide(int oldSlideNumber, int newSlideNumber) {
 		// Ensure these numbers are valid
-		if(oldSlideNumer < 1 || newSlideNumber < 1) {
+		if(oldSlideNumber < 1 || newSlideNumber < 1) {
 			throw new IllegalArgumentException("Old and new slide numbers must be greater than 0");
 		}
-		if(oldSlideNumer > _slides.length || newSlideNumber > _slides.length) {
+		if(oldSlideNumber > _slides.length || newSlideNumber > _slides.length) {
 			throw new IllegalArgumentException("Old and new slide numbers must not exceed the number of slides (" + _slides.length + ")");
 		}
-		
-		// Shift the SlideAtomsSet
-		SlideListWithText slwt = _documentRecord.getSlideSlideListWithText(); 
-		slwt.repositionSlideAtomsSet( 
-				slwt.getSlideAtomsSets()[(oldSlideNumer-1)],
-				(newSlideNumber-1)
-		);
-		
-		// Re-order the slides
-		ArrayUtil.arrayMoveWithin(_slides, (oldSlideNumer-1), (newSlideNumber-1), 1);
-		
-		// Tell the appropriate slides their new numbers
-		for(int i=0; i<_slides.length; i++) {
-			_slides[i].setSlideNumber( (i+1) );
-		}
+
+        //  The order of slides is defined by the order of slide atom sets in the SlideListWithText container.
+        SlideListWithText slwt = _documentRecord.getSlideSlideListWithText();
+        SlideAtomsSet[] sas = slwt.getSlideAtomsSets();
+
+        SlideAtomsSet tmp = sas[oldSlideNumber-1];
+        sas[oldSlideNumber-1] = sas[newSlideNumber-1];
+        sas[newSlideNumber-1] = tmp;
+
+        ArrayList lst = new ArrayList();
+        for (int i = 0; i < sas.length; i++) {
+            lst.add(sas[i].getSlidePersistAtom());
+            Record[] r = sas[i].getSlideRecords();
+            for (int j = 0; j < r.length; j++) {
+                lst.add(r[j]);
+            }
+            _slides[i].setSlideNumber(i+1);
+        }
+        Record[] r = (Record[])lst.toArray(new Record[lst.size()]);
+        slwt.setChildRecord(r);
 	}
 
 	/* ===============================================================
@@ -585,7 +590,8 @@
   		if(slist == null) {
   			// Need to add a new one
   			slist = new SlideListWithText();
-  			_documentRecord.addSlideListWithText(slist);
+  			slist.setInstance(SlideListWithText.SLIDES);
+            _documentRecord.addSlideListWithText(slist);
   		}
 
   		// Grab the SlidePersistAtom with the highest Slide Number.
@@ -678,11 +684,11 @@
 		ptr.addSlideLookup(sp.getRefID(), slideOffset);
 		logger.log(POILogger.INFO, "New slide ended up at " + slideOffset);
 
-  		// All done and added
+        slide.setMasterSheet(_masters[0]);
+          // All done and added
   		return slide;
 	}
 
-
     /**
      * Adds a picture to this presentation and returns the associated index.
      *

Modified: poi/branches/ooxml/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestReOrderingSlides.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestReOrderingSlides.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestReOrderingSlides.java (original)
+++ poi/branches/ooxml/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestReOrderingSlides.java Sun Sep  7 13:11:32 2008
@@ -279,18 +279,23 @@
 		assertEquals(3, ss_read.getSlides().length);
 		
 		// And check it's as expected
-		s1 = ss_read.getSlides()[0];
-		s2 = ss_read.getSlides()[1];
-		s3 = ss_read.getSlides()[2];
-		
-		assertEquals(257, s1._getSheetNumber());
-		assertEquals(4, s1._getSheetRefId());
+		Slide _s1 = ss_read.getSlides()[0];
+		Slide _s2 = ss_read.getSlides()[1];
+		Slide _s3 = ss_read.getSlides()[2];
+
+        // 1 --> 3
+        assertEquals(s1._getSheetNumber(), _s3._getSheetNumber());
+		assertEquals(s1._getSheetRefId(), _s3._getSheetRefId());
 		assertEquals(1, s1.getSlideNumber());
-		assertEquals(256, s2._getSheetNumber());
-		assertEquals(3, s2._getSheetRefId());
+
+        // 2nd slide is not updated
+        assertEquals(s2._getSheetNumber(), _s2._getSheetNumber());
+        assertEquals(s2._getSheetRefId(), _s2._getSheetRefId());
 		assertEquals(2, s2.getSlideNumber());
-		assertEquals(258, s3._getSheetNumber());
-		assertEquals(5, s3._getSheetRefId());
+
+        // 3 --> 1
+        assertEquals(s3._getSheetNumber(), _s1._getSheetNumber());
+        assertEquals(s3._getSheetRefId(), _s1._getSheetRefId());
 		assertEquals(3, s3.getSlideNumber());
 	}
 }

Modified: poi/branches/ooxml/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
Binary files - no diff available.

Modified: poi/branches/ooxml/src/testcases/org/apache/poi/hssf/data/LookupFunctionsTestCaseData.xls
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/testcases/org/apache/poi/hssf/data/LookupFunctionsTestCaseData.xls?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
Binary files - no diff available.

Modified: poi/branches/ooxml/src/testcases/org/apache/poi/hssf/data/externalFunctionExample.xls
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/testcases/org/apache/poi/hssf/data/externalFunctionExample.xls?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
Binary files - no diff available.

Modified: poi/branches/ooxml/src/testcases/org/apache/poi/hssf/data/testNames.xls
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/testcases/org/apache/poi/hssf/data/testNames.xls?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
Binary files - no diff available.

Modified: poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/TestExternalFunctionFormulas.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/TestExternalFunctionFormulas.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/TestExternalFunctionFormulas.java (original)
+++ poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/TestExternalFunctionFormulas.java Sun Sep  7 13:11:32 2008
@@ -74,9 +74,18 @@
 	public void testEvaluate() {
 		HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("externalFunctionExample.xls");
 		HSSFSheet sheet = wb.getSheetAt(0);
-		HSSFCell cell = sheet.getRow(0).getCell(0);
 		HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
-		CellValue evalResult = fe.evaluate(cell);
-		evalResult.toString();
+		confirmCellEval(sheet, 0, 0, fe, "YEARFRAC(B1,C1)", 29.0/90.0);
+		confirmCellEval(sheet, 1, 0, fe, "YEARFRAC(B2,C2)", 0.0);
+		confirmCellEval(sheet, 2, 0, fe, "IF(ISEVEN(3),1.2,1.6)", 1.6);
+		confirmCellEval(sheet, 3, 0, fe, "IF(ISODD(3),1.2,1.6)", 1.2);
+	}
+
+	private static void confirmCellEval(HSSFSheet sheet, int rowIx, int colIx, 
+			HSSFFormulaEvaluator fe, String expectedFormula, double expectedResult) {
+		HSSFCell cell = sheet.getRow(rowIx).getCell(colIx);
+		assertEquals(expectedFormula, cell.getCellFormula());
+		CellValue cv = fe.evaluate(cell);
+		assertEquals(expectedResult, cv.getNumberValue(), 0.0);
 	}
 }

Modified: poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/atp/TestYearFracCalculator.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/atp/TestYearFracCalculator.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/atp/TestYearFracCalculator.java (original)
+++ poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/atp/TestYearFracCalculator.java Sun Sep  7 13:11:32 2008
@@ -38,6 +38,7 @@
 		confirm(md(1999, 3, 31), md(1999, 4, 3), 1, 0.008219178);
 		confirm(md(1999, 4, 5), md(1999, 4, 8), 1, 0.008219178);
 		confirm(md(1999, 4, 4), md(1999, 4, 7), 1, 0.008219178);
+		confirm(md(2000, 2, 5), md(2000, 6, 1), 0, 0.322222222);
 	}
 
 	private void confirm(double startDate, double endDate, int basis, double expectedValue) {

Modified: poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/AllFormulaEvalTests.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/AllFormulaEvalTests.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/AllFormulaEvalTests.java (original)
+++ poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/AllFormulaEvalTests.java Sun Sep  7 13:11:32 2008
@@ -31,6 +31,8 @@
 		TestSuite result = new TestSuite(AllFormulaEvalTests.class.getName());
 		result.addTestSuite(TestAreaEval.class);
 		result.addTestSuite(TestCircularReferences.class);
+		result.addTestSuite(TestDivideEval.class);
+		result.addTestSuite(TestEqualEval.class);
 		result.addTestSuite(TestExternalFunction.class);
 		result.addTestSuite(TestFormulaBugs.class);
 		result.addTestSuite(TestFormulasFromSpreadsheet.class);

Modified: poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/TestCircularReferences.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/TestCircularReferences.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/TestCircularReferences.java (original)
+++ poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/TestCircularReferences.java Sun Sep  7 13:11:32 2008
@@ -93,7 +93,6 @@
 		HSSFCell testCell = row.createCell(0);
 		testCell.setCellFormula("A1");
 
-		HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb);
 		CellValue cellValue = evaluateWithCycles(wb, sheet, testCell);
 		
 		confirmCycleErrorCode(cellValue);
@@ -114,7 +113,6 @@
 		HSSFCell testCell = row.createCell(3);
 		testCell.setCellFormula("A1");
 
-		HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb);
 		CellValue cellValue = evaluateWithCycles(wb, sheet, testCell);
 		
 		confirmCycleErrorCode(cellValue);

Modified: poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/TestPercentEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/TestPercentEval.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/TestPercentEval.java (original)
+++ poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/TestPercentEval.java Sun Sep  7 13:11:32 2008
@@ -20,7 +20,7 @@
 import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 
-import org.apache.poi.hssf.record.formula.PercentPtg;
+import org.apache.poi.hssf.record.formula.functions.EvalFactory;
 import org.apache.poi.hssf.record.formula.functions.NumericFunctionInvoker;
 import org.apache.poi.hssf.usermodel.HSSFCell;
 import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
@@ -41,8 +41,8 @@
 			arg,	
 		};
 		
-		PercentEval opEval = new PercentEval(PercentPtg.instance);
-		double result = NumericFunctionInvoker.invoke(opEval, args, -1, (short)-1);
+		OperationEval opEval = PercentEval.instance;
+		double result = NumericFunctionInvoker.invoke(opEval, args, 0, 0);
 		
 		assertEquals(expectedResult, result, 0);
 	}
@@ -55,6 +55,10 @@
 		confirm(BoolEval.TRUE, 0.01);
 	}
 
+	public void test1x1Area() {
+		AreaEval ae = EvalFactory.createAreaEval("B2:B2", new ValueEval[] { new NumberEval(50), });
+		confirm(ae, 0.5);
+	}
 	public void testInSpreadSheet() {
 		HSSFWorkbook wb = new HSSFWorkbook();
 		HSSFSheet sheet = wb.createSheet("Sheet1");

Modified: poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/TestUnaryPlusEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/TestUnaryPlusEval.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/TestUnaryPlusEval.java (original)
+++ poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/TestUnaryPlusEval.java Sun Sep  7 13:11:32 2008
@@ -1,27 +1,25 @@
-/*
-* 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.
-*/
-
+/* ====================================================================
+   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 junit.framework.TestCase;
 
 import org.apache.poi.hssf.record.formula.AreaPtg;
-import org.apache.poi.hssf.record.formula.UnaryPlusPtg;
 import org.apache.poi.hssf.record.formula.functions.EvalFactory;
 import org.apache.poi.hssf.record.formula.functions.NumericFunctionInvoker;
 
@@ -53,7 +51,7 @@
 			EvalFactory.createAreaEval(areaPtg, values),
 		};
 
-		double result = NumericFunctionInvoker.invoke(new UnaryPlusEval(UnaryPlusPtg.instance), args, 10, (short)20);
+		double result = NumericFunctionInvoker.invoke(UnaryPlusEval.instance, args, 10, (short)20);
 
 		assertEquals(35, result, 0);
 	}

Modified: poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/AllIndividualFunctionEvaluationTests.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/AllIndividualFunctionEvaluationTests.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/AllIndividualFunctionEvaluationTests.java (original)
+++ poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/AllIndividualFunctionEvaluationTests.java Sun Sep  7 13:11:32 2008
@@ -36,6 +36,7 @@
 		result.addTestSuite(TestIndex.class);
 		result.addTestSuite(TestIsBlank.class);
 		result.addTestSuite(TestLen.class);
+		result.addTestSuite(TestLookupFunctionsFromSpreadsheet.class);
 		result.addTestSuite(TestMid.class);
 		result.addTestSuite(TestMathX.class);
 		result.addTestSuite(TestMatch.class);

Modified: poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/TestDate.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/TestDate.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/TestDate.java (original)
+++ poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/TestDate.java Sun Sep  7 13:11:32 2008
@@ -28,29 +28,29 @@
  * @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
  */
 public final class TestDate extends TestCase {
-    
+
     private HSSFCell cell11;
     private HSSFFormulaEvaluator evaluator;
 
     public void setUp() {
         HSSFWorkbook wb = new HSSFWorkbook();
         HSSFSheet sheet = wb.createSheet("new sheet");
-		cell11 = sheet.createRow(0).createCell(0);
+        cell11 = sheet.createRow(0).createCell(0);
         cell11.setCellType(HSSFCell.CELL_TYPE_FORMULA);
         evaluator = new HSSFFormulaEvaluator(sheet, wb);
     }
-    
-	/**
-	 * Test disabled pending a fix in the formula evaluator
-	 * TODO - create MissingArgEval and modify the formula evaluator to handle this
-	 */
+
+    /**
+     * Test disabled pending a fix in the formula evaluator
+     * TODO - create MissingArgEval and modify the formula evaluator to handle this
+     */
     public void DISABLEDtestSomeArgumentsMissing() {
         confirm("DATE(, 1, 0)", 0.0);
         confirm("DATE(, 1, 1)", 1.0);
     }
-    
+
     public void testValid() {
-        
+
         confirm("DATE(1900, 1, 1)", 1);
         confirm("DATE(1900, 1, 32)", 32);
         confirm("DATE(1900, 222, 1)", 6727);
@@ -58,7 +58,7 @@
         confirm("DATE(2000, 1, 222)", 36747.00);
         confirm("DATE(2007, 1, 1)", 39083);
     }
-    
+
     public void testBugDate() {
         confirm("DATE(1900, 2, 29)", 60);
         confirm("DATE(1900, 2, 30)", 61);
@@ -66,7 +66,7 @@
         confirm("DATE(1900, 1, 2222)", 2222);
         confirm("DATE(1900, 1, 22222)", 22222);
     }
-    
+
     public void testPartYears() {
         confirm("DATE(4, 1, 1)", 1462.00);
         confirm("DATE(14, 1, 1)", 5115.00);
@@ -74,10 +74,11 @@
         confirm("DATE(1004, 1, 1)", 366705.00);
     }
 
-	private void confirm(String formulaText, double expectedResult) {
+    private void confirm(String formulaText, double expectedResult) {
         cell11.setCellFormula(formulaText);
+        evaluator.clearCache();
         double actualValue = evaluator.evaluate(cell11).getNumberValue();
-		assertEquals(expectedResult, actualValue, 0);
-	}
+        assertEquals(expectedResult, actualValue, 0);
+    }
 }
 

Modified: poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/AllUserModelTests.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/AllUserModelTests.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/AllUserModelTests.java (original)
+++ poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/AllUserModelTests.java Sun Sep  7 13:11:32 2008
@@ -46,6 +46,7 @@
 		result.addTestSuite(TestHSSFConditionalFormatting.class);
 		result.addTestSuite(TestHSSFDataFormatter.class);
 		result.addTestSuite(TestHSSFDateUtil.class);
+		result.addTestSuite(TestHSSFFormulaEvaluator.class);
 		result.addTestSuite(TestHSSFHeaderFooter.class);
 		result.addTestSuite(TestHSSFHyperlink.class);
 		result.addTestSuite(TestHSSFOptimiser.class);

Modified: poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java (original)
+++ poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java Sun Sep  7 13:11:32 2008
@@ -37,6 +37,7 @@
 import org.apache.poi.hssf.record.NameRecord;
 import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
 import org.apache.poi.hssf.record.formula.DeletedArea3DPtg;
+import org.apache.poi.hssf.record.formula.Ptg;
 import org.apache.poi.util.TempFile;
 
 /**
@@ -1020,9 +1021,9 @@
             NameRecord r = w.getNameRecord(i);
             assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
             
-            List nd = r.getNameDefinition();
-            assertEquals(1, nd.size());
-            assertTrue(nd.get(0) instanceof DeletedArea3DPtg);
+            Ptg[] nd = r.getNameDefinition();
+            assertEquals(1, nd.length);
+            assertTrue(nd[0] instanceof DeletedArea3DPtg);
         }
         
         
@@ -1038,9 +1039,9 @@
             NameRecord r = w.getNameRecord(i);
             assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
             
-            List nd = r.getNameDefinition();
-            assertEquals(1, nd.size());
-            assertTrue(nd.get(0) instanceof DeletedArea3DPtg);
+            Ptg[] nd = r.getNameDefinition();
+            assertEquals(1, nd.length);
+            assertTrue(nd[0] instanceof DeletedArea3DPtg);
         }
         
         
@@ -1055,9 +1056,9 @@
             NameRecord r = w.getNameRecord(i);
             assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
             
-            List nd = r.getNameDefinition();
-            assertEquals(1, nd.size());
-            assertTrue(nd.get(0) instanceof DeletedArea3DPtg);
+            Ptg[] nd = r.getNameDefinition();
+            assertEquals(1, nd.length);
+            assertTrue(nd[0] instanceof DeletedArea3DPtg);
         }
     }
     

Modified: poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestFormulaEvaluatorBugs.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestFormulaEvaluatorBugs.java?rev=692932&r1=692931&r2=692932&view=diff
==============================================================================
--- poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestFormulaEvaluatorBugs.java (original)
+++ poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestFormulaEvaluatorBugs.java Sun Sep  7 13:11:32 2008
@@ -19,6 +19,8 @@
 
 import java.io.File;
 import java.io.FileOutputStream;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
 import java.util.Iterator;
 
 import junit.framework.AssertionFailedError;
@@ -35,6 +37,7 @@
  */
 public final class TestFormulaEvaluatorBugs extends TestCase {
 
+	private static final boolean OUTPUT_TEST_FILES = false;
 	private String tmpDirName;
 
 	protected void setUp() {
@@ -65,13 +68,15 @@
 		HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
 		assertEquals(4.2 * 25, row.getCell(3).getNumericCellValue(), 0.0001);
 
-		// Save
-		File existing = new File(tmpDirName, "44636-existing.xls");
-		FileOutputStream out = new FileOutputStream(existing);
-		wb.write(out);
-		out.close();
-		System.err.println("Existing file for bug #44636 written to " + existing.toString());
-
+		FileOutputStream out;
+		if (OUTPUT_TEST_FILES) {
+			// Save
+			File existing = new File(tmpDirName, "44636-existing.xls");
+			out = new FileOutputStream(existing);
+			wb.write(out);
+			out.close();
+			System.err.println("Existing file for bug #44636 written to " + existing.toString());
+		}
 		// Now, do a new file from scratch
 		wb = new HSSFWorkbook();
 		sheet = wb.createSheet();
@@ -86,12 +91,14 @@
 		HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
 		assertEquals(5.4, row.getCell(0).getNumericCellValue(), 0.0001);
 
-		// Save
-		File scratch = new File(tmpDirName, "44636-scratch.xls");
-		out = new FileOutputStream(scratch);
-		wb.write(out);
-		out.close();
-		System.err.println("New file for bug #44636 written to " + scratch.toString());
+		if (OUTPUT_TEST_FILES) {
+			// Save
+			File scratch = new File(tmpDirName, "44636-scratch.xls");
+			out = new FileOutputStream(scratch);
+			wb.write(out);
+			out.close();
+			System.err.println("New file for bug #44636 written to " + scratch.toString());
+		}
 	}
 
 	/**
@@ -281,64 +288,39 @@
 	}
 	
 	/**
-	 * Apparently, each subsequent call takes longer, which is very
-	 *  odd.
-	 * We think it's because the formulas are recursive and crazy
+	 * The HSSFFormula evaluator performance benefits greatly from caching of intermediate cell values
 	 */
-	public void DISABLEDtestSlowEvaluate45376() throws Exception {
-		HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("45376.xls");
+	public void testSlowEvaluate45376() {
 		
-		final String SHEET_NAME = "Eingabe";
-        final int row = 6;
-        final HSSFSheet sheet = wb.getSheet(SHEET_NAME);
-        
-        int firstCol = 4;
-        int lastCol = 14;
-        long[] timings = new long[lastCol-firstCol+1];
-        long[] rtimings = new long[lastCol-firstCol+1];
-        
-        long then, now;
-
-        final HSSFRow excelRow = sheet.getRow(row);
-        for(int i = firstCol; i <= lastCol; i++) {
-             final HSSFCell excelCell = excelRow.getCell(i);
-             final HSSFFormulaEvaluator evaluator = new
-                 HSSFFormulaEvaluator(sheet, wb);
-
-             now = System.currentTimeMillis();
-             evaluator.evaluate(excelCell);
-             then = System.currentTimeMillis();
-             timings[i-firstCol] = (then-now);
-             System.err.println("Col " + i + " took " + (then-now) + "ms");
-        }
-        for(int i = lastCol; i >= firstCol; i--) {
-            final HSSFCell excelCell = excelRow.getCell(i);
-            final HSSFFormulaEvaluator evaluator = new
-                HSSFFormulaEvaluator(sheet, wb);
-
-            now = System.currentTimeMillis();
-            evaluator.evaluate(excelCell);
-            then = System.currentTimeMillis();
-            rtimings[i-firstCol] = (then-now);
-            System.err.println("Col " + i + " took " + (then-now) + "ms");
-       }
-        
-        // The timings for each should be about the same
-        long avg = 0;
-        for(int i=0; i<timings.length; i++) {
-        	avg += timings[i];
-        }
-        avg = (long)( ((double)avg) / timings.length );
-        
-        // Warn if any took more then 1.5 the average
-        // TODO - replace with assert or similar
-        for(int i=0; i<timings.length; i++) {
-        	if(timings[i] > 1.5*avg) {
-        		System.err.println("Doing col " + (i+firstCol) + 
-        				" took " + timings[i] + "ms, vs avg " + 
-        				avg + "ms"
-        		);
-        	}
-        }
+		// Firstly set up a sequence of formula cells where each depends on the  previous multiple
+		// times.  Without caching, each subsequent cell take about 4 times longer to evaluate.
+		HSSFWorkbook wb = new HSSFWorkbook();
+		HSSFSheet sheet = wb.createSheet("Sheet1");
+		HSSFRow row = sheet.createRow(0);
+		for(int i=1; i<10; i++) {
+			HSSFCell cell = row.createCell(i);
+			char prevCol = (char) ('A' + i-1);
+			String prevCell = prevCol + "1";
+			// this formula is inspired by the offending formula of the attachment for bug 45376
+			String formula = "IF(DATE(YEAR(" + prevCell + "),MONTH(" + prevCell + ")+1,1)<=$D$3," +
+					"DATE(YEAR(" + prevCell + "),MONTH(" + prevCell + ")+1,1),NA())";
+			cell.setCellFormula(formula);
+			
+		}
+		Calendar cal = new GregorianCalendar(2000, 0, 1, 0, 0, 0);
+		row.createCell(0).setCellValue(cal);
+		
+		// Choose cell A9, so that the failing test case doesn't take too long to execute.
+		HSSFCell cell = row.getCell(8);
+		HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb);
+		evaluator.evaluate(cell);
+		int evalCount = evaluator.getEvaluationCount();
+		// With caching, the evaluationCount is 8 which is a big improvement
+		if (evalCount > 10) {
+			// Without caching, evaluating cell 'A9' takes 21845 evaluations which consumes
+			// much time (~3 sec on Core 2 Duo 2.2GHz)
+			System.err.println("Cell A9 took " + evalCount + " intermediate evaluations");
+			throw new AssertionFailedError("Identifed bug 45376 - Formula evaluator should cache values");
+		}
 	}
 }
\ No newline at end of file

Copied: poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFFormulaEvaluator.java (from r692893, poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFFormulaEvaluator.java)
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFFormulaEvaluator.java?p2=poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFFormulaEvaluator.java&p1=poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFFormulaEvaluator.java&r1=692893&r2=692932&rev=692932&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFFormulaEvaluator.java (original)
+++ poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFFormulaEvaluator.java Sun Sep  7 13:11:32 2008
@@ -18,7 +18,7 @@
 package org.apache.poi.hssf.usermodel;
 
 import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator.CellValue;
+import org.apache.poi.ss.usermodel.FormulaEvaluator.CellValue;
 
 import junit.framework.TestCase;
 /**



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