package org.apache.poi.ss.formula.atp;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.function.FunctionMetadata;
+import org.apache.poi.ss.formula.function.FunctionMetadataRegistry;
import org.apache.poi.ss.formula.functions.FreeRefFunction;
+import org.apache.poi.ss.formula.functions.Function;
+import org.apache.poi.ss.formula.functions.NotImplementedFunction;
import org.apache.poi.ss.formula.functions.Sumifs;
import org.apache.poi.ss.formula.udf.UDFFinder;
import org.apache.poi.ss.formula.OperationEvaluationContext;
FreeRefFunction func = pFunc == null ? new NotImplemented(functionName) : pFunc;
m.put(functionName, func);
}
+
+ public static boolean isATPFunction(String name){
+ AnalysisToolPak inst = (AnalysisToolPak)instance;
+ return inst._functionsByName.containsKey(name);
+ }
+
+ /**
+ * Returns an array of function names implemented by POI.
+ *
+ * @return an array of supported functions
+ * @since 3.8 beta6
+ */
+ public static String[] getSupportedFunctionNames(){
+ AnalysisToolPak inst = (AnalysisToolPak)instance;
+ ArrayList<String> lst = new ArrayList<String>();
+ for(String name : inst._functionsByName.keySet()){
+ FreeRefFunction func = inst._functionsByName.get(name);
+ if(func != null && !(func instanceof NotImplemented)){
+ lst.add(name);
+ }
+ }
+ return lst.toArray(new String[lst.size()]);
+ }
+
+ /**
+ * Register a ATP function in runtime.
+ *
+ * @param name the function name
+ * @param func the functoin to register
+ * @throws IllegalArgumentException if the function is unknown or already registered.
+ * @since 3.8 beta6
+ */
+ public static void registerFunction(String name, FreeRefFunction func){
+ AnalysisToolPak inst = (AnalysisToolPak)instance;
+ if(!isATPFunction(name)) {
+ FunctionMetadata metaData = FunctionMetadataRegistry.getFunctionByName(name);
+ if(metaData != null) {
+ throw new IllegalArgumentException(name + " is a built-in Excel function. " +
+ "Use FunctoinEval.registerFunction(String name, Function func) instead.");
+ } else {
+ throw new IllegalArgumentException(name + " is not a function from the Excel Analysis Toolpack.");
+ }
+ }
+ FreeRefFunction f = inst.findFunction(name);
+ if(f != null && !(f instanceof NotImplemented)) {
+ throw new IllegalArgumentException("POI already implememts " + name +
+ ". You cannot override POI's implementations of Excel functions");
+ }
+
+ inst._functionsByName.put(name, func);
+ }
}
package org.apache.poi.ss.formula.eval;
+import org.apache.poi.ss.formula.atp.AnalysisToolPak;
import org.apache.poi.ss.formula.function.FunctionMetadata;
import org.apache.poi.ss.formula.function.FunctionMetadataRegistry;
import org.apache.poi.ss.formula.functions.*;
+import java.util.ArrayList;
+
/**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
*/
}
return result;
}
+
+ /**
+ * Register a new function in runtime.
+ *
+ * @param name the function name
+ * @param func the functoin to register
+ * @throws IllegalArgumentException if the function is unknown or already registered.
+ * @since 3.8 beta6
+ */
+ public static void registerFunction(String name, Function func){
+ FunctionMetadata metaData = FunctionMetadataRegistry.getFunctionByName(name);
+ if(metaData == null) {
+ if(AnalysisToolPak.isATPFunction(name)) {
+ throw new IllegalArgumentException(name + " is a function from the Excel Analysis Toolpack. " +
+ "Use AnalysisToolpack.registerFunction(String name, FreeRefFunction func) instead.");
+ } else {
+ throw new IllegalArgumentException("Unknown function: " + name);
+ }
+ }
+
+ int idx = metaData.getIndex();
+ if(functions[idx] instanceof NotImplementedFunction) {
+ functions[idx] = func;
+ } else {
+ throw new IllegalArgumentException("POI already implememts " + name +
+ ". You cannot override POI's implementations of Excel functions");
+ }
+ }
+
+ /**
+ * Returns an array of function names implemented by POI.
+ *
+ * @return an array of supported functions
+ * @since 3.8 beta6
+ */
+ public static String[] getSupportedFunctionNames(){
+ ArrayList<String> lst = new ArrayList<String>();
+ for(int i = 0; i < functions.length; i++){
+ Function func = functions[i];
+ if(func != null && !(func instanceof NotImplementedFunction)){
+ FunctionMetadata metaData = FunctionMetadataRegistry.getFunctionByIndex(i);
+ lst.add(metaData.getName());
+ }
+ }
+ return lst.toArray(new String[lst.size()]);
+ }
}
--- /dev/null
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ====================================================================
+ */
+
+package org.apache.poi.ss.formula;
+
+import junit.framework.TestCase;
+import org.apache.poi.hssf.usermodel.*;
+import org.apache.poi.ss.formula.atp.AnalysisToolPak;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.FunctionEval;
+import org.apache.poi.ss.formula.eval.NotImplementedException;
+import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.functions.FreeRefFunction;
+import org.apache.poi.ss.formula.functions.Function;
+import org.apache.poi.ss.usermodel.CellValue;
+
+/**
+ *
+ * @author Yegor Kozlov
+ */
+public class TestFunctionRegistry extends TestCase {
+
+ public void testRegisterInRuntime() {
+ HSSFWorkbook wb = new HSSFWorkbook();
+ HSSFSheet sheet = wb.createSheet("Sheet1");
+ HSSFRow row = sheet.createRow(0);
+ HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
+
+ HSSFCell cellA = row.createCell(0);
+ cellA.setCellFormula("FISHER(A5)");
+ CellValue cv;
+ try {
+ cv = fe.evaluate(cellA);
+ fail("expectecd exception");
+ } catch (NotImplementedException e) {
+ ;
+ }
+
+ FunctionEval.registerFunction("FISHER", new Function() {
+ public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+ return ErrorEval.NA;
+ }
+ });
+
+ cv = fe.evaluate(cellA);
+ assertEquals(ErrorEval.NA.getErrorCode(), cv.getErrorValue());
+
+ HSSFCell cellB = row.createCell(1);
+ cellB.setCellFormula("CUBEMEMBERPROPERTY(A5)");
+ try {
+ cv = fe.evaluate(cellB);
+ fail("expectecd exception");
+ } catch (NotImplementedException e) {
+ ;
+ }
+
+ AnalysisToolPak.registerFunction("CUBEMEMBERPROPERTY", new FreeRefFunction() {
+ public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
+ return ErrorEval.NUM_ERROR;
+ }
+ });
+
+ cv = fe.evaluate(cellB);
+ assertEquals(ErrorEval.NUM_ERROR.getErrorCode(), cv.getErrorValue());
+ }
+
+ public void testExceptions() {
+ Function func = new Function() {
+ public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+ return ErrorEval.NA;
+ }
+ };
+ try {
+ FunctionEval.registerFunction("SUM", func);
+ fail("expectecd exception");
+ } catch (IllegalArgumentException e){
+ assertEquals("POI already implememts SUM" +
+ ". You cannot override POI's implementations of Excel functions", e.getMessage());
+ }
+ try {
+ FunctionEval.registerFunction("SUMXXX", func);
+ fail("expectecd exception");
+ } catch (IllegalArgumentException e){
+ assertEquals("Unknown function: SUMXXX", e.getMessage());
+ }
+ try {
+ FunctionEval.registerFunction("ISODD", func);
+ fail("expectecd exception");
+ } catch (IllegalArgumentException e){
+ assertEquals("ISODD is a function from the Excel Analysis Toolpack. " +
+ "Use AnalysisToolpack.registerFunction(String name, FreeRefFunction func) instead.", e.getMessage());
+ }
+
+ FreeRefFunction atpFunc = new FreeRefFunction() {
+ public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
+ return ErrorEval.NUM_ERROR;
+ }
+ };
+ try {
+ AnalysisToolPak.registerFunction("ISODD", atpFunc);
+ fail("expectecd exception");
+ } catch (IllegalArgumentException e){
+ assertEquals("POI already implememts ISODD" +
+ ". You cannot override POI's implementations of Excel functions", e.getMessage());
+ }
+ try {
+ AnalysisToolPak.registerFunction("ISODDXXX", atpFunc);
+ fail("expectecd exception");
+ } catch (IllegalArgumentException e){
+ assertEquals("ISODDXXX is not a function from the Excel Analysis Toolpack.", e.getMessage());
+ }
+ try {
+ AnalysisToolPak.registerFunction("SUM", atpFunc);
+ fail("expectecd exception");
+ } catch (IllegalArgumentException e){
+ assertEquals("SUM is a built-in Excel function. " +
+ "Use FunctoinEval.registerFunction(String name, Function func) instead.", e.getMessage());
+ }
+ }
+}