You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ye...@apache.org on 2009/09/16 21:16:40 UTC

svn commit: r815928 - in /poi/trunk: src/documentation/content/xdocs/ src/java/org/apache/poi/hssf/record/formula/atp/ src/java/org/apache/poi/hssf/record/formula/eval/ src/java/org/apache/poi/hssf/record/formula/toolpack/ src/java/org/apache/poi/hssf/...

Author: yegor
Date: Wed Sep 16 19:16:39 2009
New Revision: 815928

URL: http://svn.apache.org/viewvc?rev=815928&view=rev
Log:
improved work with user-defined functions, see Bugzilla 47809

Added:
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/DefaultToolPack.java   (with props)
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/MainToolPacksHandler.java   (with props)
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/ToolPack.java   (with props)
Modified:
    poi/trunk/src/documentation/content/xdocs/status.xml
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/atp/AnalysisToolPak.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/UserDefinedFunction.java
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
    poi/trunk/src/java/org/apache/poi/ss/formula/EvaluationWorkbook.java
    poi/trunk/src/java/org/apache/poi/ss/formula/eval/forked/ForkedEvaluationWorkbook.java
    poi/trunk/src/java/org/apache/poi/ss/usermodel/Workbook.java
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java
    poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/TestExternalFunction.java
    poi/trunk/test-data/spreadsheet/testNames.xls

Modified: poi/trunk/src/documentation/content/xdocs/status.xml
URL: http://svn.apache.org/viewvc/poi/trunk/src/documentation/content/xdocs/status.xml?rev=815928&r1=815927&r2=815928&view=diff
==============================================================================
--- poi/trunk/src/documentation/content/xdocs/status.xml (original)
+++ poi/trunk/src/documentation/content/xdocs/status.xml Wed Sep 16 19:16:39 2009
@@ -33,6 +33,7 @@
 
     <changes>
         <release version="3.5-beta7" date="2009-??-??">
+           <action dev="POI-DEVELOPERS" type="add">47809 - Improved work with user-defined functions</action>
            <action dev="POI-DEVELOPERS" type="fix">47581 - fixed  XSSFSheet.setColumnWidth to produce XML compatible with Mac Excel 2008</action>
            <action dev="POI-DEVELOPERS" type="fix">47734 - removed unnecessary svn:executable flag from files in SVN trunk</action>
            <action dev="POI-DEVELOPERS" type="fix">47543 - added javadoc how to avoid Excel crash when creating too many HSSFRichTextString cells</action>

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/atp/AnalysisToolPak.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/atp/AnalysisToolPak.java?rev=815928&r1=815927&r2=815928&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/atp/AnalysisToolPak.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/atp/AnalysisToolPak.java Wed Sep 16 19:16:39 2009
@@ -22,10 +22,14 @@
 
 import org.apache.poi.hssf.record.formula.eval.ValueEval;
 import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
+import org.apache.poi.hssf.record.formula.toolpack.ToolPack;
 import org.apache.poi.ss.formula.OperationEvaluationContext;
 import org.apache.poi.ss.formula.eval.NotImplementedException;
 
-public final class AnalysisToolPak {
+/**
+ * Modified 09/07/09 by Petr Udalau - systematized work of ToolPacks. 
+ */
+public final class AnalysisToolPak implements ToolPack {
 
 	private static final class NotImplemented implements FreeRefFunction {
 		private final String _functionName;
@@ -38,18 +42,14 @@
 			throw new NotImplementedException(_functionName);
 		}
 	};
+	
+	private Map<String, FreeRefFunction> _functionsByName = createFunctionsMap();
 
-	private static Map<String, FreeRefFunction> _functionsByName = createFunctionsMap();
-
-	private AnalysisToolPak() {
-		// no instances of this class
-	}
-
-	public static FreeRefFunction findFunction(String name) {
+	public FreeRefFunction findFunction(String name) {
 		return _functionsByName.get(name);
 	}
-
-	private static Map<String, FreeRefFunction> createFunctionsMap() {
+	
+	private Map<String, FreeRefFunction> createFunctionsMap() {
 		Map<String, FreeRefFunction> m = new HashMap<String, FreeRefFunction>(100);
 
 		r(m, "ACCRINT", null);
@@ -153,4 +153,16 @@
 		FreeRefFunction func = pFunc == null ? new NotImplemented(functionName) : pFunc;
 		m.put(functionName, func);
 	}
+
+    public void addFunction(String name, FreeRefFunction evaluator) {
+        r(_functionsByName, name, evaluator);
+    }
+
+    public boolean containsFunction(String name) {
+        return _functionsByName.containsKey(name);
+    }
+
+    public void removeFunction(String name) {
+        _functionsByName.remove(name);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/UserDefinedFunction.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/UserDefinedFunction.java?rev=815928&r1=815927&r2=815928&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/UserDefinedFunction.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/UserDefinedFunction.java Wed Sep 16 19:16:39 2009
@@ -17,8 +17,8 @@
 
 package org.apache.poi.hssf.record.formula.eval;
 
-import org.apache.poi.hssf.record.formula.atp.AnalysisToolPak;
 import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
+import org.apache.poi.hssf.record.formula.toolpack.MainToolPacksHandler;
 import org.apache.poi.ss.formula.EvaluationWorkbook;
 import org.apache.poi.ss.formula.OperationEvaluationContext;
 import org.apache.poi.ss.formula.eval.NotImplementedException;
@@ -28,6 +28,8 @@
  * <tt>AbstractFunctionPtg.field_2_fnc_index</tt> == 255)
  *
  * @author Josh Micich
+ * 
+ * Modified 09/07/09 by Petr Udalau - Improved resolving of UDFs through the ToolPacks. 
  */
 final class UserDefinedFunction implements FreeRefFunction {
 
@@ -38,7 +40,7 @@
 	}
 
 	public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
-
+		EvaluationWorkbook workbook = ec.getWorkbook();
 		int nIncomingArgs = args.length;
 		if(nIncomingArgs < 1) {
 			throw new RuntimeException("function name argument missing");
@@ -47,9 +49,9 @@
 		ValueEval nameArg = args[0];
 		FreeRefFunction targetFunc;
 		if (nameArg instanceof NameEval) {
-			targetFunc = findInternalUserDefinedFunction((NameEval) nameArg);
+			targetFunc = findInternalUserDefinedFunction(workbook, (NameEval) nameArg);
 		} else if (nameArg instanceof NameXEval) {
-			targetFunc = findExternalUserDefinedFunction(ec.getWorkbook(), (NameXEval) nameArg);
+			targetFunc = findExternalUserDefinedFunction(workbook, (NameXEval) nameArg);
 		} else {
 			throw new RuntimeException("First argument should be a NameEval, but got ("
 					+ nameArg.getClass().getName() + ")");
@@ -67,21 +69,29 @@
 		if(false) {
 			System.out.println("received call to external user defined function (" + functionName + ")");
 		}
-		// currently only looking for functions from the 'Analysis TookPak'  e.g. "YEARFRAC" or "ISEVEN"
+		// currently only looking for functions from the 'Analysis TookPak'(contained in MainToolPacksHandler)  e.g. "YEARFRAC" or "ISEVEN"
 		// not sure how much this logic would need to change to support other or multiple add-ins.
-		FreeRefFunction result = AnalysisToolPak.findFunction(functionName);
+		FreeRefFunction result = MainToolPacksHandler.instance().findFunction(functionName);
 		if (result != null) {
 			return result;
 		}
 		throw new NotImplementedException(functionName);
 	}
 
-	private static FreeRefFunction findInternalUserDefinedFunction(NameEval functionNameEval) {
+	private static FreeRefFunction findInternalUserDefinedFunction(EvaluationWorkbook workbook,
+			NameEval functionNameEval) {
 
 		String functionName = functionNameEval.getFunctionName();
 		if(false) {
 			System.out.println("received call to internal user defined function  (" + functionName + ")");
 		}
+		FreeRefFunction functionEvaluator = workbook.findUserDefinedFunction(functionName); 
+		if (functionEvaluator == null) {
+		    functionEvaluator = MainToolPacksHandler.instance().findFunction(functionName);
+		}
+		if (functionEvaluator != null) {
+            return functionEvaluator;
+        }
 		// TODO find the implementation for the user defined function
 
 		throw new NotImplementedException(functionName);

Added: poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/DefaultToolPack.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/DefaultToolPack.java?rev=815928&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/DefaultToolPack.java (added)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/DefaultToolPack.java Wed Sep 16 19:16:39 2009
@@ -0,0 +1,51 @@
+/* ====================================================================
+   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.toolpack;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
+
+/**
+ * Default tool pack.
+ * If you want to add some UDF, but you don't want to create new tool pack, use this.
+ * 
+ * @author PUdalau
+ */
+public class DefaultToolPack implements ToolPack {
+    private Map<String, FreeRefFunction> functionsByName = new HashMap<String, FreeRefFunction>();
+
+    public void addFunction(String name, FreeRefFunction evaluator) {
+        if (evaluator != null){
+            functionsByName.put(name, evaluator);
+        }
+    }
+
+    public boolean containsFunction(String name) {
+        return functionsByName.containsKey(name);
+    }
+
+    public FreeRefFunction findFunction(String name) {
+        return functionsByName.get(name);
+    }
+
+    public void removeFunction(String name) {
+        functionsByName.remove(name);
+    }
+}

Propchange: poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/DefaultToolPack.java
------------------------------------------------------------------------------
    svn:executable = *

Added: poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/MainToolPacksHandler.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/MainToolPacksHandler.java?rev=815928&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/MainToolPacksHandler.java (added)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/MainToolPacksHandler.java Wed Sep 16 19:16:39 2009
@@ -0,0 +1,102 @@
+/* ====================================================================
+   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.toolpack;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.hssf.record.formula.atp.AnalysisToolPak;
+import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
+
+/**
+ * Contains all tool packs. Processing of UDF is through this class.
+ * 
+ * @author PUdalau
+ */
+public class MainToolPacksHandler{
+
+    private DefaultToolPack defaultToolPack;
+
+    private List<ToolPack> usedToolPacks = new ArrayList<ToolPack>();
+
+    private static MainToolPacksHandler instance;
+
+    /**
+     * @return Unique instance of handler.
+     */
+    public static MainToolPacksHandler instance() {
+        if (instance == null) {
+            instance = new MainToolPacksHandler();
+        }
+        return instance;
+    }
+
+    /**
+     * @return Default tool pack(which is obligatory exists in handler).
+     */
+    public DefaultToolPack getDefaultToolPack() {
+        return defaultToolPack;
+    }
+
+    private MainToolPacksHandler() {
+        defaultToolPack = new DefaultToolPack();
+        usedToolPacks.add(defaultToolPack);
+        usedToolPacks.add(new AnalysisToolPak());
+    }
+
+    /**
+	 * Checks if such function exists in any registered tool pack. 
+	 * @param name Name of function.
+	 * @return true if some tool pack contains such function.
+     */
+    public boolean containsFunction(String name) {
+        for (ToolPack pack : usedToolPacks) {
+            if (pack.containsFunction(name)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+	 * Returns executor by specified name. Returns <code>null</code> if
+	 * function isn't contained by any registered tool pack.
+	 * 
+	 * @param name
+	 *            Name of function.
+	 * @return Function executor.
+	 */
+    public FreeRefFunction findFunction(String name) {
+        FreeRefFunction evaluatorForFunction;
+        for (ToolPack pack : usedToolPacks) {
+            evaluatorForFunction = pack.findFunction(name);
+            if (evaluatorForFunction != null) {
+                return evaluatorForFunction;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Registers new tool pack in handler.
+     * @param pack Tool pack to add.
+     */
+    public void addToolPack(ToolPack pack) {
+        usedToolPacks.add(pack);
+    }
+}

Propchange: poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/MainToolPacksHandler.java
------------------------------------------------------------------------------
    svn:executable = *

Added: poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/ToolPack.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/ToolPack.java?rev=815928&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/ToolPack.java (added)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/ToolPack.java Wed Sep 16 19:16:39 2009
@@ -0,0 +1,56 @@
+/* ====================================================================
+   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.toolpack;
+
+import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
+
+/**
+ * Common interface for any new tool pack with executors for functions.
+ * 
+ * @author PUdalau
+ */
+public interface ToolPack {
+	/**
+	 * Returns executor by specified name. Returns <code>null</code> if tool
+	 * pack doesn't contains such function.
+	 * 
+	 * @param name Name of function.
+	 * @return Function executor.
+	 */
+	FreeRefFunction findFunction(String name);
+
+	/**
+	 * Add new function with executor.
+	 * @param name Name of function.
+	 * @param evaluator Function executor.
+	 */
+	void addFunction(String name, FreeRefFunction evaluator);
+
+	/**
+	 * Returns executor by specified name if it exists.
+	 * @param name Name of function.
+	 */
+	void removeFunction(String name);
+
+	/**
+	 * Checks if such function exists in tool pack. 
+	 * @param name Name of function.
+	 * @return true if tool pack contains such function.
+	 */
+	boolean containsFunction(String name);
+}

Propchange: poi/trunk/src/java/org/apache/poi/hssf/record/formula/toolpack/ToolPack.java
------------------------------------------------------------------------------
    svn:executable = *

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=815928&r1=815927&r2=815928&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 Wed Sep 16 19:16:39 2009
@@ -24,6 +24,7 @@
 import org.apache.poi.hssf.record.formula.NamePtg;
 import org.apache.poi.hssf.record.formula.NameXPtg;
 import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
 import org.apache.poi.ss.formula.*;
 import org.apache.poi.ss.SpreadsheetVersion;
 
@@ -31,6 +32,8 @@
  * Internal POI use only
  *
  * @author Josh Micich
+ * 
+ * Modified 09/07/09 by Petr Udalau - added methods for searching for UDFs of this Workbook. 
  */
 public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, EvaluationWorkbook, FormulaParsingWorkbook {
 
@@ -159,4 +162,8 @@
     public SpreadsheetVersion getSpreadsheetVersion(){
         return SpreadsheetVersion.EXCEL97;
     }
+    
+    public FreeRefFunction findUserDefinedFunction(String functionName) {
+        return _uBook.getUserDefinedFunction(functionName);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java?rev=815928&r1=815927&r2=815928&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java Wed Sep 16 19:16:39 2009
@@ -24,9 +24,11 @@
 import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.regex.Pattern;
 
 import org.apache.poi.POIDocument;
@@ -62,15 +64,18 @@
 import org.apache.poi.hssf.record.formula.Ref3DPtg;
 import org.apache.poi.hssf.record.formula.SheetNameFormatter;
 import org.apache.poi.hssf.record.formula.UnionPtg;
+import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
 import org.apache.poi.hssf.util.CellReference;
 import org.apache.poi.poifs.filesystem.DirectoryNode;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 import org.apache.poi.ss.usermodel.CreationHelper;
+import org.apache.poi.ss.usermodel.Name;
 import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
 import org.apache.poi.ss.formula.FormulaType;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
 
+
 /**
  * High level representation of a workbook.  This is the first object most users
  * will construct whether they are reading or writing a workbook.  It is also the
@@ -82,6 +87,8 @@
  * @author  Glen Stampoultzis (glens at apache.org)
  * @author  Shawn Laubach (slaubach at apache dot org)
  *
+ * 
+ * Modified 09/07/09 by Petr Udalau - added methods for work with UDFs of this Workbook. 
  */
 public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.usermodel.Workbook {
     private static final Pattern COMMA_PATTERN = Pattern.compile(",");
@@ -160,8 +167,9 @@
 
 
     private static POILogger log = POILogFactory.getLogger(HSSFWorkbook.class);
-
-
+    
+    /** Map of user defined functions, key - function name, value - instance of FreeRefFunctions */
+	private Map<String, FreeRefFunction> udfFunctions;
 
     /**
      * Creates new HSSFWorkbook from scratch (start here!)
@@ -178,6 +186,7 @@
         workbook = book;
         _sheets = new ArrayList( INITIAL_CAPACITY );
         names = new ArrayList( INITIAL_CAPACITY );
+        udfFunctions = new HashMap<String, FreeRefFunction>(); 
     }
 
     public HSSFWorkbook(POIFSFileSystem fs) throws IOException {
@@ -269,6 +278,7 @@
 
         _sheets = new ArrayList(INITIAL_CAPACITY);
         names  = new ArrayList(INITIAL_CAPACITY);
+        udfFunctions = new HashMap<String, FreeRefFunction>();
 
         // Grab the data from the workbook stream, however
         //  it happens to be spelled.
@@ -1617,6 +1627,25 @@
             }
         }
     }
+    
+    public FreeRefFunction getUserDefinedFunction(String functionName) {
+    	return udfFunctions.get(functionName);
+    }
+    
+    public void registerUserDefinedFunction(String functionName, FreeRefFunction freeRefFunction) {
+    	Name udfDeclaration = getName(functionName);
+        if (udfDeclaration == null) {
+            udfDeclaration = createName();
+        }
+        udfDeclaration.setNameName(functionName);
+        udfDeclaration.setFunction(true);
+        udfFunctions.put(functionName, freeRefFunction);
+    	
+    }
+
+	public List<String> getUserDefinedFunctionNames() {
+		return new ArrayList<String>(udfFunctions.keySet());
+	}
 
     /**
      * Is the workbook protected with a password (not encrypted)?

Modified: poi/trunk/src/java/org/apache/poi/ss/formula/EvaluationWorkbook.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/formula/EvaluationWorkbook.java?rev=815928&r1=815927&r2=815928&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/formula/EvaluationWorkbook.java (original)
+++ poi/trunk/src/java/org/apache/poi/ss/formula/EvaluationWorkbook.java Wed Sep 16 19:16:39 2009
@@ -20,6 +20,7 @@
 import org.apache.poi.hssf.record.formula.NamePtg;
 import org.apache.poi.hssf.record.formula.NameXPtg;
 import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
 
 /**
  * Abstracts a workbook for the purpose of formula evaluation.<br/>
@@ -27,6 +28,8 @@
  * For POI internal use only
  *
  * @author Josh Micich
+ * 
+ * Modified 09/07/09 by Petr Udalau - added methods for searching for UDFs of this Workbook. 
  */
 public interface EvaluationWorkbook {
 	String getSheetName(int sheetIndex);
@@ -51,6 +54,17 @@
 	String resolveNameXText(NameXPtg ptg);
 	Ptg[] getFormulaTokens(EvaluationCell cell);
 
+	/**
+     * Find and return user defined function (UDF) contained by workbook with
+     * specified name.
+     * 
+     * @param functionName UDF name
+     * @return instance of FreeRefFunction or null if no UDF with the specified
+     *         name exists.
+     */
+	FreeRefFunction findUserDefinedFunction(String functionName);
+
+
 	class ExternalSheet {
 		private final String _workbookName;
 		private final String _sheetName;

Modified: poi/trunk/src/java/org/apache/poi/ss/formula/eval/forked/ForkedEvaluationWorkbook.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/formula/eval/forked/ForkedEvaluationWorkbook.java?rev=815928&r1=815927&r2=815928&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/formula/eval/forked/ForkedEvaluationWorkbook.java (original)
+++ poi/trunk/src/java/org/apache/poi/ss/formula/eval/forked/ForkedEvaluationWorkbook.java Wed Sep 16 19:16:39 2009
@@ -23,6 +23,7 @@
 import org.apache.poi.hssf.record.formula.NamePtg;
 import org.apache.poi.hssf.record.formula.NameXPtg;
 import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
 import org.apache.poi.ss.formula.EvaluationCell;
 import org.apache.poi.ss.formula.EvaluationName;
 import org.apache.poi.ss.formula.EvaluationSheet;
@@ -35,6 +36,8 @@
  * updated after a call to {@link #getOrCreateUpdatableCell(String, int, int)}.
  *
  * @author Josh Micich
+ * 
+ * Modified 09/07/09 by Petr Udalau - added methods for searching for UDFs of this Workbook. 
  */
 final class ForkedEvaluationWorkbook implements EvaluationWorkbook {
 
@@ -141,4 +144,8 @@
 			return _index - o._index;
 		}
 	}
+
+    public FreeRefFunction findUserDefinedFunction(String functionName) {
+        return _masterBook.findUserDefinedFunction(functionName);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ss/usermodel/Workbook.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/usermodel/Workbook.java?rev=815928&r1=815927&r2=815928&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/usermodel/Workbook.java (original)
+++ poi/trunk/src/java/org/apache/poi/ss/usermodel/Workbook.java Wed Sep 16 19:16:39 2009
@@ -21,12 +21,15 @@
 import java.io.OutputStream;
 import java.util.List;
 
+import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
 import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
 
 /**
  * High level representation of a Excel workbook.  This is the first object most users
  * will construct whether they are reading or writing a workbook.  It is also the
  * top level object for creating new sheets/etc.
+ * 
+ * Modified 09/07/09 by Petr Udalau - added methods for work with UDFs of this Workbook. 
  */
 public interface Workbook {
 
@@ -464,4 +467,29 @@
      * @param hidden 0 for not hidden, 1 for hidden, 2 for very hidden
      */
     void setSheetHidden(int sheetIx, int hidden);
+    
+    /**
+	 * Find and return user defined function (UDF) with specified name.
+	 * 
+	 * @param functionName
+	 *            UDF name
+	 * @return instance of FreeRefFunction or null if no UDF with the specified
+	 *         name exists.
+	 */
+	FreeRefFunction getUserDefinedFunction(String functionName);
+	
+	/**
+	 * Add user defined function (UDF) to workbook
+	 * 
+	 * @param name
+	 * @param function
+	 */
+	void registerUserDefinedFunction(String name, FreeRefFunction function);
+
+	/**
+	 * Returns user defined functions (UDF) names
+	 * 
+	 * @return list of UDF names
+	 */
+	List<String> getUserDefinedFunctionNames();
 }

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java?rev=815928&r1=815927&r2=815928&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java Wed Sep 16 19:16:39 2009
@@ -20,6 +20,7 @@
 import org.apache.poi.hssf.record.formula.NamePtg;
 import org.apache.poi.hssf.record.formula.NameXPtg;
 import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
 import org.apache.poi.ss.formula.*;
 import org.apache.poi.ss.SpreadsheetVersion;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName;
@@ -28,6 +29,8 @@
  * Internal POI use only
  *
  * @author Josh Micich
+ * 
+ * Modified 09/07/09 by Petr Udalau - added methods for searching for UDFs of this Workbook. 
  */
 public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, EvaluationWorkbook, FormulaParsingWorkbook {
 
@@ -177,4 +180,8 @@
 	public SpreadsheetVersion getSpreadsheetVersion(){
 		return SpreadsheetVersion.EXCEL2007;
 	}
+
+    public FreeRefFunction findUserDefinedFunction(String functionName) {
+        return _uBook.getUserDefinedFunction(functionName);
+    }
 }

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java?rev=815928&r1=815927&r2=815928&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java Wed Sep 16 19:16:39 2009
@@ -32,6 +32,7 @@
 import org.apache.poi.POIXMLException;
 import org.apache.poi.POIXMLProperties;
 import org.apache.poi.hssf.record.formula.SheetNameFormatter;
+import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
 import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
 import org.apache.poi.openxml4j.opc.OPCPackage;
 import org.apache.poi.openxml4j.opc.PackagePart;
@@ -40,6 +41,7 @@
 import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
 import org.apache.poi.openxml4j.opc.PackagingURIHelper;
 import org.apache.poi.openxml4j.opc.TargetMode;
+import org.apache.poi.ss.usermodel.Name;
 import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.ss.usermodel.Workbook;
@@ -63,6 +65,8 @@
  * High level representation of a SpreadsheetML workbook.  This is the first object most users
  * will construct whether they are reading or writing a workbook.  It is also the
  * top level object for creating new sheets/etc.
+ * 
+ * Modified 09/07/09 by Petr Udalau - added methods for work with UDFs of this Workbook. 
  */
 public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<XSSFSheet> {
     private static final Pattern COMMA_PATTERN = Pattern.compile(",");
@@ -129,6 +133,9 @@
     private List<XSSFPictureData> pictures;
 
     private static POILogger logger = POILogFactory.getLogger(XSSFWorkbook.class);
+    
+    /** Map of user defined functions, key - function name, value - instance of FreeRefFunctions */
+	private Map<String, FreeRefFunction> udfFunctions = new HashMap<String, FreeRefFunction>();
 
     /**
      * Create a new SpreadsheetML workbook.
@@ -1346,4 +1353,22 @@
     	return mapInfo;
     }
 
+    public FreeRefFunction getUserDefinedFunction(String functionName) {
+    	return udfFunctions.get(functionName);
+    }
+    
+    public void registerUserDefinedFunction(String functionName, FreeRefFunction freeRefFunction) {
+    	Name udfDeclaration = getName(functionName);
+        if (udfDeclaration == null) {
+            udfDeclaration = createName();
+        }
+        udfDeclaration.setNameName(functionName);
+        udfDeclaration.setFunction(true);
+        udfFunctions.put(functionName, freeRefFunction);
+    }
+    
+	public List<String> getUserDefinedFunctionNames() {
+		return new ArrayList<String>(udfFunctions.keySet());
+	}
+
 }

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/TestExternalFunction.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/TestExternalFunction.java?rev=815928&r1=815927&r2=815928&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/TestExternalFunction.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/TestExternalFunction.java Wed Sep 16 19:16:39 2009
@@ -22,61 +22,92 @@
 import junit.framework.TestCase;
 
 import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
+import org.apache.poi.hssf.record.formula.toolpack.DefaultToolPack;
+import org.apache.poi.hssf.record.formula.toolpack.MainToolPacksHandler;
+import org.apache.poi.hssf.record.formula.toolpack.ToolPack;
 import org.apache.poi.hssf.usermodel.HSSFCell;
 import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFName;
 import org.apache.poi.hssf.usermodel.HSSFRow;
 import org.apache.poi.hssf.usermodel.HSSFSheet;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.formula.eval.NotImplementedException;
-import org.apache.poi.ss.usermodel.CellValue;
+import org.apache.poi.ss.formula.OperationEvaluationContext;
+import org.apache.poi.ss.usermodel.Workbook;
+
 /**
  * 
  * @author Josh Micich
+ * 
+ * Modified 09/14/09 by Petr Udalau - Test of registering UDFs in workbook and
+ * using ToolPacks.
  */
 public final class TestExternalFunction extends TestCase {
 
-	/**
-	 * Checks that an external function can get invoked from the formula evaluator. 
-	 * @throws IOException 
-
-	 */
-	public void testInvoke() {
-		
-		HSSFWorkbook wb;
-		HSSFSheet sheet;
-		HSSFCell cell;
-		if (false) {
-			// TODO - this code won't work until we can create user-defined functions directly with POI
-			wb = new HSSFWorkbook();
-			sheet = wb.createSheet();
-			wb.setSheetName(0, "Sheet1");
-			HSSFName hssfName = wb.createName();
-			hssfName.setNameName("myFunc");
-			
-		} else {
-			// This sample spreadsheet already has a VB function called 'myFunc'
-			wb = HSSFTestDataSamples.openSampleWorkbook("testNames.xls");
-			sheet = wb.getSheetAt(0);
-			HSSFRow row = sheet.createRow(0);
-			cell = row.createCell(1);
-		}
-		
-		cell.setCellFormula("myFunc()");
-		String actualFormula=cell.getCellFormula();
-		assertEquals("myFunc()", actualFormula);
-		
-		HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
-		// Check out what ExternalFunction.evaluate() does:
-		CellValue evalResult;
-		try {
-			evalResult = fe.evaluate(cell);
-		} catch (NotImplementedException e) {
-			assertEquals("Error evaluating cell Sheet1!B1", e.getMessage());
-			assertEquals("myFunc", e.getCause().getMessage());
-			return;
-		}
-		// TODO - make this test assert something more interesting as soon as ExternalFunction works a bit better
-		assertNotNull(evalResult);
-	}
+    private static class MyFunc implements FreeRefFunction {
+        public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
+            if (args.length != 1 || !(args[0] instanceof StringEval)) {
+                return ErrorEval.VALUE_INVALID;
+            } else {
+                StringEval input = (StringEval) args[0];
+                return new StringEval(input.getStringValue() + "abc");
+            }
+        }
+    }
+
+    private static class MyFunc2 implements FreeRefFunction {
+        public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
+            if (args.length != 1 || !(args[0] instanceof StringEval)) {
+                return ErrorEval.VALUE_INVALID;
+            } else {
+                StringEval input = (StringEval) args[0];
+                return new StringEval(input.getStringValue() + "abc2");
+            }
+        }
+    }
+
+    /**
+     * Creates and registers user-defined function "MyFunc()" directly with POI.
+     * This is VB function defined in "testNames.xls". In future there must be
+     * some parser of VBA scripts which will register UDFs.
+     */
+    private void registerMyFunc(Workbook workbook) {
+        workbook.registerUserDefinedFunction("myFunc", new MyFunc());
+    }
+
+    /**
+     * Creates example ToolPack which contains function "MyFunc2()".
+     */
+    private void createExampleToolPack() {
+        ToolPack exampleToolPack = new DefaultToolPack();
+        exampleToolPack.addFunction("myFunc2", new MyFunc2());
+        MainToolPacksHandler.instance().addToolPack(exampleToolPack);
+    }
+
+    /**
+     * Checks that an external function can get invoked from the formula
+     * evaluator.
+     * 
+     * @throws IOException
+     * 
+     */
+    public void testInvoke() {
+        HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("testNames.xls");
+        HSSFSheet sheet = wb.getSheetAt(0);
+
+        registerMyFunc(wb);
+        createExampleToolPack();
+
+        HSSFRow row = sheet.getRow(0);
+        HSSFCell myFuncCell = row.getCell(1); //=myFunc("_")
+
+        HSSFCell myFunc2Cell = row.getCell(2); //=myFunc2("_")
+
+        HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
+        try {
+            assertEquals("_abc", fe.evaluate(myFuncCell).getStringValue());
+            assertEquals("_abc2", fe.evaluate(myFunc2Cell).getStringValue());
+        } catch (Exception e) {
+            assertFalse(true);
+        }
+    }
 }

Modified: poi/trunk/test-data/spreadsheet/testNames.xls
URL: http://svn.apache.org/viewvc/poi/trunk/test-data/spreadsheet/testNames.xls?rev=815928&r1=815927&r2=815928&view=diff
==============================================================================
Binary files - no diff available.



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