* @author Libin Roman (Vista Portal LDT. Developer)
* @author Sergei Kozello (sergeikozello at mail.ru)
* @author Glen Stampoultzis (glens at apache.org)
- * @version 1.0-pre
- *
- * Modified 8/31/09 by Petr Udalau - added method setFunction(boolean)
+ * @author Petr Udalau - added method setFunction(boolean)
*/
public final class NameRecord extends StandardRecord {
public final static short sid = 0x0018;
/**
* For named ranges, and built-in names
- * @return the 1-based sheet number.
+ * @return the 1-based sheet number.
*/
public int getSheetNumber()
{
public boolean isFunctionName() {
return (field_1_option_flag & Option.OPT_FUNCTION_NAME) != 0;
}
-
- /**
- * Indicates that the defined name refers to a user-defined function.
- * This attribute is used when there is an add-in or other code project associated with the file.
- *
- * @param value <code>true</code> indicates the name refers to a function.
- */
+
+ /**
+ * Indicates that the defined name refers to a user-defined function.
+ * This attribute is used when there is an add-in or other code project associated with the file.
+ *
+ * @param value <code>true</code> indicates the name refers to a function.
+ */
public void setFunction(boolean function){
if (function) {
field_1_option_flag |= Option.OPT_FUNCTION_NAME;
int field_8_length_description_text = field_15_description_text.length();
int field_9_length_help_topic_text = field_16_help_topic_text.length();
int field_10_length_status_bar_text = field_17_status_bar_text.length();
-
+
// size defined below
out.writeShort(getOptionFlag());
out.writeByte(getKeyboardShortcut());
}
field_13_name_definition.serializeTokens(out);
field_13_name_definition.serializeArrayConstantData(out);
-
+
StringUtil.putCompressedUnicode( getCustomMenuText(), out);
StringUtil.putCompressedUnicode( getDescriptionText(), out);
StringUtil.putCompressedUnicode( getHelpTopicText(), out);
private int getNameRawSize() {
if (isBuiltInName()) {
return 1;
- }
+ }
int nChars = field_12_name_text.length();
if(field_11_nameIsMultibyte) {
return 2 * nChars;
- }
+ }
return nChars;
}
-
+
protected int getDataSize() {
return 13 // 3 shorts + 7 bytes
+ getNameRawSize()
}
}
- int nBytesAvailable = in.available() - (f7_customMenuLen
+ int nBytesAvailable = in.available() - (f7_customMenuLen
+ f8_descriptionTextLen + f9_helpTopicTextLen + f10_statusBarTextLen);
field_13_name_definition = Formula.read(field_4_length_name_definition, in, nBytesAvailable);
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.hssf.record.formula.udf.UDFFinder;
import org.apache.poi.ss.formula.OperationEvaluationContext;
import org.apache.poi.ss.formula.eval.NotImplementedException;
/**
- * Modified 09/07/09 by Petr Udalau - systematized work of ToolPacks.
+ * @author Josh Micich
+ * @author Petr Udalau - systematized work of add-in libraries and user defined functions.
*/
-public final class AnalysisToolPak implements ToolPack {
+public final class AnalysisToolPak implements UDFFinder {
+
+ public static final UDFFinder instance = new AnalysisToolPak();
private static final class NotImplemented implements FreeRefFunction {
private final String _functionName;
throw new NotImplementedException(_functionName);
}
};
-
- private Map<String, FreeRefFunction> _functionsByName = createFunctionsMap();
+
+ private final Map<String, FreeRefFunction> _functionsByName = createFunctionsMap();
+
+
+ private AnalysisToolPak() {
+ // enforce singleton
+ }
public FreeRefFunction findFunction(String name) {
return _functionsByName.get(name);
}
-
+
private Map<String, FreeRefFunction> createFunctionsMap() {
Map<String, FreeRefFunction> m = new HashMap<String, FreeRefFunction>(100);
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);
- }
}
package org.apache.poi.hssf.record.formula.eval;
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;
/**
* <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.
+ * @author Petr Udalau - Improved resolving of UDFs through the ToolPacks.
*/
final class UserDefinedFunction implements FreeRefFunction {
}
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");
}
ValueEval nameArg = args[0];
- FreeRefFunction targetFunc;
+ String functionName;
if (nameArg instanceof NameEval) {
- targetFunc = findInternalUserDefinedFunction(workbook, (NameEval) nameArg);
+ functionName = ((NameEval) nameArg).getFunctionName();
} else if (nameArg instanceof NameXEval) {
- targetFunc = findExternalUserDefinedFunction(workbook, (NameXEval) nameArg);
+ functionName = ec.getWorkbook().resolveNameXText(((NameXEval) nameArg).getPtg());
} else {
throw new RuntimeException("First argument should be a NameEval, but got ("
+ nameArg.getClass().getName() + ")");
}
+ FreeRefFunction targetFunc = ec.findUserDefinedFunction(functionName);
+ if (targetFunc == null) {
+ throw new NotImplementedException(functionName);
+ }
int nOutGoingArgs = nIncomingArgs -1;
ValueEval[] outGoingArgs = new ValueEval[nOutGoingArgs];
System.arraycopy(args, 1, outGoingArgs, 0, nOutGoingArgs);
return targetFunc.evaluate(outGoingArgs, ec);
}
-
- private static FreeRefFunction findExternalUserDefinedFunction(EvaluationWorkbook workbook,
- NameXEval n) {
- String functionName = workbook.resolveNameXText(n.getPtg());
-
- if(false) {
- System.out.println("received call to external user defined function (" + functionName + ")");
- }
- // 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 = MainToolPacksHandler.instance().findFunction(functionName);
- if (result != null) {
- return result;
- }
- throw new NotImplementedException(functionName);
- }
-
- 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);
- }
}
+++ /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.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);
- }
-}
+++ /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.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);
- }
-}
+++ /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.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);
-}
--- /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.hssf.record.formula.udf;
+
+import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
+
+/**
+ * Collects add-in libraries and VB macro functions together into one UDF finder
+ *
+ * @author PUdalau
+ */
+public final class AggregatingUDFFinder implements UDFFinder {
+
+ private final UDFFinder[] _usedToolPacks;
+
+ public AggregatingUDFFinder(UDFFinder ... usedToolPacks) {
+ _usedToolPacks = usedToolPacks.clone();
+ }
+
+ /**
+ * 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. <code>null</code> if not found
+ */
+ public FreeRefFunction findFunction(String name) {
+ FreeRefFunction evaluatorForFunction;
+ for (UDFFinder pack : _usedToolPacks) {
+ evaluatorForFunction = pack.findFunction(name);
+ if (evaluatorForFunction != null) {
+ return evaluatorForFunction;
+ }
+ }
+ return null;
+ }
+}
--- /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.hssf.record.formula.udf;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
+
+/**
+ * Default UDF finder - for adding your own user defined functions.
+ *
+ * @author PUdalau
+ */
+public final class DefaultUDFFinder implements UDFFinder {
+ private final Map<String, FreeRefFunction> _functionsByName;
+
+ public DefaultUDFFinder(String[] functionNames, FreeRefFunction[] functionImpls) {
+ int nFuncs = functionNames.length;
+ if (functionImpls.length != nFuncs) {
+ throw new IllegalArgumentException(
+ "Mismatch in number of function names and implementations");
+ }
+ HashMap<String, FreeRefFunction> m = new HashMap<String, FreeRefFunction>(nFuncs * 3 / 2);
+ for (int i = 0; i < functionImpls.length; i++) {
+ m.put(functionNames[i], functionImpls[i]);
+ }
+ _functionsByName = m;
+ }
+
+ public FreeRefFunction findFunction(String name) {
+ return _functionsByName.get(name);
+ }
+}
--- /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.hssf.record.formula.udf;
+
+import org.apache.poi.hssf.record.formula.atp.AnalysisToolPak;
+import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
+
+/**
+ * Common interface for "Add-in" libraries and user defined function libraries.
+ *
+ * @author PUdalau
+ */
+public interface UDFFinder {
+ public static final UDFFinder DEFAULT = new AggregatingUDFFinder(AnalysisToolPak.instance);
+
+ /**
+ * Returns executor by specified name. Returns <code>null</code> if the function name is unknown.
+ *
+ * @param name Name of function.
+ * @return Function executor.
+ */
+ FreeRefFunction findFunction(String name);
+}
(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
+ 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,
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.apache.poi.ss.formula.EvaluationCell;
+import org.apache.poi.ss.formula.EvaluationName;
+import org.apache.poi.ss.formula.EvaluationSheet;
+import org.apache.poi.ss.formula.EvaluationWorkbook;
+import org.apache.poi.ss.formula.FormulaParsingWorkbook;
+import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
+import org.apache.poi.ss.formula.FormulaType;
/**
* 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 {
- private final HSSFWorkbook _uBook;
- private final Workbook _iBook;
-
- public static HSSFEvaluationWorkbook create(HSSFWorkbook book) {
- if (book == null) {
- return null;
- }
- return new HSSFEvaluationWorkbook(book);
- }
-
- private HSSFEvaluationWorkbook(HSSFWorkbook book) {
- _uBook = book;
- _iBook = book.getWorkbook();
- }
-
- public int getExternalSheetIndex(String sheetName) {
- int sheetIndex = _uBook.getSheetIndex(sheetName);
- return _iBook.checkExternSheet(sheetIndex);
- }
- public int getExternalSheetIndex(String workbookName, String sheetName) {
- return _iBook.getExternalSheetIndex(workbookName, sheetName);
- }
-
- public NameXPtg getNameXPtg(String name) {
- return _iBook.getNameXPtg(name);
- }
-
- /**
- * Lookup a named range by its name.
- *
- * @param name the name to search
- * @param sheetIndex the 0-based index of the sheet this formula belongs to.
- * The sheet index is required to resolve sheet-level names. <code>-1</code> means workbook-global names
- */
- public EvaluationName getName(String name, int sheetIndex) {
- for(int i=0; i < _iBook.getNumNames(); i++) {
- NameRecord nr = _iBook.getNameRecord(i);
- if (nr.getSheetNumber() == sheetIndex+1 && name.equalsIgnoreCase(nr.getNameText())) {
- return new Name(nr, i);
- }
- }
- return sheetIndex == -1 ? null : getName(name, -1);
- }
-
- public int getSheetIndex(EvaluationSheet evalSheet) {
- HSSFSheet sheet = ((HSSFEvaluationSheet)evalSheet).getHSSFSheet();
- return _uBook.getSheetIndex(sheet);
- }
- public int getSheetIndex(String sheetName) {
- return _uBook.getSheetIndex(sheetName);
- }
-
- public String getSheetName(int sheetIndex) {
- return _uBook.getSheetName(sheetIndex);
- }
-
- public EvaluationSheet getSheet(int sheetIndex) {
- return new HSSFEvaluationSheet(_uBook.getSheetAt(sheetIndex));
- }
- public int convertFromExternSheetIndex(int externSheetIndex) {
- return _iBook.getSheetIndexFromExternSheetIndex(externSheetIndex);
- }
-
- public ExternalSheet getExternalSheet(int externSheetIndex) {
- return _iBook.getExternalSheet(externSheetIndex);
- }
-
- public String resolveNameXText(NameXPtg n) {
- return _iBook.resolveNameXText(n.getSheetRefIndex(), n.getNameIndex());
- }
-
- public String getSheetNameByExternSheet(int externSheetIndex) {
- return _iBook.findSheetNameFromExternSheet(externSheetIndex);
- }
- public String getNameText(NamePtg namePtg) {
- return _iBook.getNameRecord(namePtg.getIndex()).getNameText();
- }
- public EvaluationName getName(NamePtg namePtg) {
- int ix = namePtg.getIndex();
- return new Name(_iBook.getNameRecord(ix), ix);
- }
- public Ptg[] getFormulaTokens(EvaluationCell evalCell) {
- HSSFCell cell = ((HSSFEvaluationCell)evalCell).getHSSFCell();
- if (false) {
- // re-parsing the formula text also works, but is a waste of time
- // It is useful from time to time to run all unit tests with this code
- // to make sure that all formulas POI can evaluate can also be parsed.
- return HSSFFormulaParser.parse(cell.getCellFormula(), _uBook, FormulaType.CELL, _uBook.getSheetIndex(cell.getSheet()));
- }
- FormulaRecordAggregate fra = (FormulaRecordAggregate) cell.getCellValueRecord();
- return fra.getFormulaTokens();
- }
-
- private static final class Name implements EvaluationName {
-
- private final NameRecord _nameRecord;
- private final int _index;
-
- public Name(NameRecord nameRecord, int index) {
- _nameRecord = nameRecord;
- _index = index;
- }
- public Ptg[] getNameDefinition() {
- return _nameRecord.getNameDefinition();
- }
- public String getNameText() {
- return _nameRecord.getNameText();
- }
- public boolean hasFormula() {
- return _nameRecord.hasFormula();
- }
- public boolean isFunctionName() {
- return _nameRecord.isFunctionName();
- }
- public boolean isRange() {
- return _nameRecord.hasFormula(); // TODO - is this right?
- }
- public NamePtg createPtg() {
- return new NamePtg(_index);
- }
- }
-
- public SpreadsheetVersion getSpreadsheetVersion(){
- return SpreadsheetVersion.EXCEL97;
- }
-
- public FreeRefFunction findUserDefinedFunction(String functionName) {
- return _uBook.getUserDefinedFunction(functionName);
- }
+ private final HSSFWorkbook _uBook;
+ private final Workbook _iBook;
+
+ public static HSSFEvaluationWorkbook create(HSSFWorkbook book) {
+ if (book == null) {
+ return null;
+ }
+ return new HSSFEvaluationWorkbook(book);
+ }
+
+ private HSSFEvaluationWorkbook(HSSFWorkbook book) {
+ _uBook = book;
+ _iBook = book.getWorkbook();
+ }
+
+ public int getExternalSheetIndex(String sheetName) {
+ int sheetIndex = _uBook.getSheetIndex(sheetName);
+ return _iBook.checkExternSheet(sheetIndex);
+ }
+ public int getExternalSheetIndex(String workbookName, String sheetName) {
+ return _iBook.getExternalSheetIndex(workbookName, sheetName);
+ }
+
+ public NameXPtg getNameXPtg(String name) {
+ return _iBook.getNameXPtg(name);
+ }
+
+ /**
+ * Lookup a named range by its name.
+ *
+ * @param name the name to search
+ * @param sheetIndex the 0-based index of the sheet this formula belongs to.
+ * The sheet index is required to resolve sheet-level names. <code>-1</code> means workbook-global names
+ */
+ public EvaluationName getName(String name, int sheetIndex) {
+ for(int i=0; i < _iBook.getNumNames(); i++) {
+ NameRecord nr = _iBook.getNameRecord(i);
+ if (nr.getSheetNumber() == sheetIndex+1 && name.equalsIgnoreCase(nr.getNameText())) {
+ return new Name(nr, i);
+ }
+ }
+ return sheetIndex == -1 ? null : getName(name, -1);
+ }
+
+ public int getSheetIndex(EvaluationSheet evalSheet) {
+ HSSFSheet sheet = ((HSSFEvaluationSheet)evalSheet).getHSSFSheet();
+ return _uBook.getSheetIndex(sheet);
+ }
+ public int getSheetIndex(String sheetName) {
+ return _uBook.getSheetIndex(sheetName);
+ }
+
+ public String getSheetName(int sheetIndex) {
+ return _uBook.getSheetName(sheetIndex);
+ }
+
+ public EvaluationSheet getSheet(int sheetIndex) {
+ return new HSSFEvaluationSheet(_uBook.getSheetAt(sheetIndex));
+ }
+ public int convertFromExternSheetIndex(int externSheetIndex) {
+ return _iBook.getSheetIndexFromExternSheetIndex(externSheetIndex);
+ }
+
+ public ExternalSheet getExternalSheet(int externSheetIndex) {
+ return _iBook.getExternalSheet(externSheetIndex);
+ }
+
+ public String resolveNameXText(NameXPtg n) {
+ return _iBook.resolveNameXText(n.getSheetRefIndex(), n.getNameIndex());
+ }
+
+ public String getSheetNameByExternSheet(int externSheetIndex) {
+ return _iBook.findSheetNameFromExternSheet(externSheetIndex);
+ }
+ public String getNameText(NamePtg namePtg) {
+ return _iBook.getNameRecord(namePtg.getIndex()).getNameText();
+ }
+ public EvaluationName getName(NamePtg namePtg) {
+ int ix = namePtg.getIndex();
+ return new Name(_iBook.getNameRecord(ix), ix);
+ }
+ public Ptg[] getFormulaTokens(EvaluationCell evalCell) {
+ HSSFCell cell = ((HSSFEvaluationCell)evalCell).getHSSFCell();
+ if (false) {
+ // re-parsing the formula text also works, but is a waste of time
+ // It is useful from time to time to run all unit tests with this code
+ // to make sure that all formulas POI can evaluate can also be parsed.
+ return HSSFFormulaParser.parse(cell.getCellFormula(), _uBook, FormulaType.CELL, _uBook.getSheetIndex(cell.getSheet()));
+ }
+ FormulaRecordAggregate fra = (FormulaRecordAggregate) cell.getCellValueRecord();
+ return fra.getFormulaTokens();
+ }
+
+ private static final class Name implements EvaluationName {
+
+ private final NameRecord _nameRecord;
+ private final int _index;
+
+ public Name(NameRecord nameRecord, int index) {
+ _nameRecord = nameRecord;
+ _index = index;
+ }
+ public Ptg[] getNameDefinition() {
+ return _nameRecord.getNameDefinition();
+ }
+ public String getNameText() {
+ return _nameRecord.getNameText();
+ }
+ public boolean hasFormula() {
+ return _nameRecord.hasFormula();
+ }
+ public boolean isFunctionName() {
+ return _nameRecord.isFunctionName();
+ }
+ public boolean isRange() {
+ return _nameRecord.hasFormula(); // TODO - is this right?
+ }
+ public NamePtg createPtg() {
+ return new NamePtg(_index);
+ }
+ }
+
+ public SpreadsheetVersion getSpreadsheetVersion(){
+ return SpreadsheetVersion.EXCEL97;
+ }
}
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
+import org.apache.poi.hssf.record.formula.udf.UDFFinder;
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment;
import org.apache.poi.ss.formula.IStabilityClassifier;
import org.apache.poi.ss.formula.WorkbookEvaluator;
* evaluation begins.
*/
public HSSFFormulaEvaluator(HSSFWorkbook workbook, IStabilityClassifier stabilityClassifier) {
- _bookEvaluator = new WorkbookEvaluator(HSSFEvaluationWorkbook.create(workbook), stabilityClassifier);
+ this(workbook, stabilityClassifier, null);
}
+ /**
+ * @param udfFinder pass <code>null</code> for default (AnalysisToolPak only)
+ */
+ private HSSFFormulaEvaluator(HSSFWorkbook workbook, IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) {
+ _bookEvaluator = new WorkbookEvaluator(HSSFEvaluationWorkbook.create(workbook), stabilityClassifier, udfFinder);
+ }
+
+ /**
+ * @param stabilityClassifier used to optimise caching performance. Pass <code>null</code>
+ * for the (conservative) assumption that any cell may have its definition changed after
+ * evaluation begins.
+ * @param udfFinder pass <code>null</code> for default (AnalysisToolPak only)
+ */
+ public static HSSFFormulaEvaluator create(HSSFWorkbook workbook, IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) {
+ return new HSSFFormulaEvaluator(workbook, stabilityClassifier, udfFinder);
+ }
+
+
/**
* Coordinates several formula evaluators together so that formulas that involve external
* references can be evaluated.
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;
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;
* @author Andrew C. Oliver (acoliver at apache dot org)
* @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(",");
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!)
workbook = book;
_sheets = new ArrayList( INITIAL_CAPACITY );
names = new ArrayList( INITIAL_CAPACITY );
- udfFunctions = new HashMap<String, FreeRefFunction>();
}
public HSSFWorkbook(POIFSFileSystem fs) throws IOException {
_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.
}
}
}
-
- 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)?
public NameXPtg getNameXPtg(String name) {
return workbook.getNameXPtg(name);
}
-
}
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/>
* 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);
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;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
+import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet;
}
return CellReference.classifyCellReference(str, ssVersion);
}
+
+ public FreeRefFunction findUserDefinedFunction(String functionName) {
+ return _bookEvaluator.findUserDefinedFunction(functionName);
+ }
}
import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.StringEval;
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.udf.UDFFinder;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
import org.apache.poi.ss.formula.eval.NotImplementedException;
private final Map<String, Integer> _sheetIndexesByName;
private CollaboratingWorkbooksEnvironment _collaboratingWorkbookEnvironment;
private final IStabilityClassifier _stabilityClassifier;
+ private final UDFFinder _udfFinder;
- public WorkbookEvaluator(EvaluationWorkbook workbook, IStabilityClassifier stabilityClassifier) {
- this (workbook, null, stabilityClassifier);
+ /**
+ * @param udfFinder pass <code>null</code> for default (AnalysisToolPak only)
+ */
+ public WorkbookEvaluator(EvaluationWorkbook workbook, IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) {
+ this (workbook, null, stabilityClassifier, udfFinder);
}
/* package */ WorkbookEvaluator(EvaluationWorkbook workbook, IEvaluationListener evaluationListener,
- IStabilityClassifier stabilityClassifier) {
+ IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) {
_workbook = workbook;
_evaluationListener = evaluationListener;
_cache = new EvaluationCache(evaluationListener);
_collaboratingWorkbookEnvironment = CollaboratingWorkbooksEnvironment.EMPTY;
_workbookIx = 0;
_stabilityClassifier = stabilityClassifier;
+ _udfFinder = udfFinder == null ? UDFFinder.DEFAULT : udfFinder;
}
/**
EvaluationCell cell = sheet.getCell(rowIndex, columnIndex);
return evaluateAny(cell, sheetIndex, rowIndex, columnIndex, tracker);
}
+ public FreeRefFunction findUserDefinedFunction(String functionName) {
+ return _udfFinder.findFunction(functionName);
+ }
}
* 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 {
return _index - o._index;
}
}
-
- public FreeRefFunction findUserDefinedFunction(String functionName) {
- return _masterBook.findUserDefinedFunction(functionName);
- }
}
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
+import org.apache.poi.hssf.record.formula.udf.UDFFinder;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
private WorkbookEvaluator _evaluator;
private ForkedEvaluationWorkbook _sewb;
- private ForkedEvaluator(EvaluationWorkbook masterWorkbook, IStabilityClassifier stabilityClassifier) {
+ private ForkedEvaluator(EvaluationWorkbook masterWorkbook, IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) {
_sewb = new ForkedEvaluationWorkbook(masterWorkbook);
- _evaluator = new WorkbookEvaluator(_sewb, stabilityClassifier);
+ _evaluator = new WorkbookEvaluator(_sewb, stabilityClassifier, udfFinder);
}
private static EvaluationWorkbook createEvaluationWorkbook(Workbook wb) {
if (wb instanceof HSSFWorkbook) {
// }
throw new IllegalArgumentException("Unexpected workbook type (" + wb.getClass().getName() + ")");
}
+ /**
+ * @deprecated (Sep 2009) (reduce overloading) use {@link #create(Workbook, IStabilityClassifier, UDFFinder)}
+ */
public static ForkedEvaluator create(Workbook wb, IStabilityClassifier stabilityClassifier) {
- return new ForkedEvaluator(createEvaluationWorkbook(wb), stabilityClassifier);
+ return create(wb, stabilityClassifier, null);
+ }
+ /**
+ * @param udfFinder pass <code>null</code> for default (AnalysisToolPak only)
+ */
+ public static ForkedEvaluator create(Workbook wb, IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) {
+ return new ForkedEvaluator(createEvaluationWorkbook(wb), stabilityClassifier, udfFinder);
}
/**
* name.setRefersToFormula("IF(Loan_Amount*Interest_Rate>0,1,0)");
*
* </blockquote></pre>
- *
- * Modified 8/31/09 by Petr Udalau - added method setFunction(boolean)
*/
public interface Name {
*/
String getSheetName();
- /**
+ /**
* Gets the name of the named range
*
* @return named range name
*/
String getNameName();
- /**
+ /**
* Sets the name of the named range
*
* <p>The following is a list of syntax rules that you need to be aware of when you create and edit names.</p>
void setNameName(String name);
/**
- * Returns the formula that the name is defined to refer to.
+ * Returns the formula that the name is defined to refer to.
*
* @return the reference for this name, <code>null</code> if it has not been set yet. Never empty string
* @see #setRefersToFormula(String)
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 {
* @param index of the sheet to remove (0-based)
*/
void removeSheetAt(int index);
-
+
/**
* Sets the repeating rows and columns for a sheet (as found in
* File->PageSetup->Sheet). This is function is included in the workbook
* Sets the policy on what to do when
* getting missing or blank cells from a row.
*
- * This will then apply to all calls to
+ * This will then apply to all calls to
* {@link Row#getCell(int)} }. See
* {@link MissingCellPolicy}
*/
* @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();
}
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;
* 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 {
public SpreadsheetVersion getSpreadsheetVersion(){
return SpreadsheetVersion.EXCEL2007;
}
-
- public FreeRefFunction findUserDefinedFunction(String functionName) {
- return _uBook.getUserDefinedFunction(functionName);
- }
}
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
+import org.apache.poi.hssf.record.formula.udf.UDFFinder;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.formula.IStabilityClassifier;
import org.apache.poi.ss.formula.WorkbookEvaluator;
import org.apache.poi.ss.usermodel.Cell;
private WorkbookEvaluator _bookEvaluator;
public XSSFFormulaEvaluator(XSSFWorkbook workbook) {
- this(workbook, null);
+ this(workbook, null, null);
}
/**
* @param stabilityClassifier used to optimise caching performance. Pass <code>null</code>
- * for the (conservative) assumption that any cell may have its definition changed after
+ * for the (conservative) assumption that any cell may have its definition changed after
* evaluation begins.
+ * @deprecated (Sep 2009) (reduce overloading) use {@link #create(HSSFWorkbook, IStabilityClassifier, UDFFinder)}
*/
public XSSFFormulaEvaluator(XSSFWorkbook workbook, IStabilityClassifier stabilityClassifier) {
- _bookEvaluator = new WorkbookEvaluator(XSSFEvaluationWorkbook.create(workbook), stabilityClassifier);
+ _bookEvaluator = new WorkbookEvaluator(XSSFEvaluationWorkbook.create(workbook), stabilityClassifier, null);
}
+ private XSSFFormulaEvaluator(XSSFWorkbook workbook, IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) {
+ _bookEvaluator = new WorkbookEvaluator(XSSFEvaluationWorkbook.create(workbook), stabilityClassifier, udfFinder);
+ }
+
+ /**
+ * @param stabilityClassifier used to optimise caching performance. Pass <code>null</code>
+ * for the (conservative) assumption that any cell may have its definition changed after
+ * evaluation begins.
+ * @param udfFinder pass <code>null</code> for default (AnalysisToolPak only)
+ */
+ public static XSSFFormulaEvaluator create(XSSFWorkbook workbook, IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) {
+ return new XSSFFormulaEvaluator(workbook, stabilityClassifier, udfFinder);
+ }
+
/**
* Should be called whenever there are major changes (e.g. moving sheets) to input cells
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;
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;
* 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(",");
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.
public MapInfo getMapInfo(){
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());
- }
-
}
package org.apache.poi.hssf.record.formula.eval;
-import java.io.IOException;
-
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.record.formula.udf.DefaultUDFFinder;
+import org.apache.poi.hssf.record.formula.udf.AggregatingUDFFinder;
+import org.apache.poi.hssf.record.formula.udf.UDFFinder;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
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.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.
+ * @author Petr Udalau - registering UDFs in workbook and using ToolPacks.
*/
public final class TestExternalFunction extends TestCase {
- 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);
- }
- }
+ private static class MyFunc implements FreeRefFunction {
+ public MyFunc() {
+ //
+ }
+
+ public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
+ if (args.length != 1 || !(args[0] instanceof StringEval)) {
+ return ErrorEval.VALUE_INVALID;
+ }
+ StringEval input = (StringEval) args[0];
+ return new StringEval(input.getStringValue() + "abc");
+ }
+ }
+
+ private static class MyFunc2 implements FreeRefFunction {
+ public MyFunc2() {
+ //
+ }
+
+ public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
+ if (args.length != 1 || !(args[0] instanceof StringEval)) {
+ return ErrorEval.VALUE_INVALID;
+ }
+ StringEval input = (StringEval) args[0];
+ return new StringEval(input.getStringValue() + "abc2");
+ }
+ }
+
+ /**
+ * Checks that an external function can get invoked from the formula
+ * evaluator.
+ */
+ public void testInvoke() {
+ HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("testNames.xls");
+ HSSFSheet sheet = wb.getSheetAt(0);
+
+ /**
+ * register the two test UDFs in a UDF finder, to be passed to the evaluator
+ */
+ UDFFinder udff1 = new DefaultUDFFinder(new String[] { "myFunc", },
+ new FreeRefFunction[] { new MyFunc(), });
+ UDFFinder udff2 = new DefaultUDFFinder(new String[] { "myFunc2", },
+ new FreeRefFunction[] { new MyFunc2(), });
+ UDFFinder udff = new AggregatingUDFFinder(udff1, udff2);
+
+
+ HSSFRow row = sheet.getRow(0);
+ HSSFCell myFuncCell = row.getCell(1); // =myFunc("_")
+
+ HSSFCell myFunc2Cell = row.getCell(2); // =myFunc2("_")
+
+ HSSFFormulaEvaluator fe = HSSFFormulaEvaluator.create(wb, null, udff);
+ assertEquals("_abc", fe.evaluate(myFuncCell).getStringValue());
+ assertEquals("_abc2", fe.evaluate(myFunc2Cell).getStringValue());
+ }
}
private static ValueEval evaluateFormula(Ptg[] ptgs) {
OperationEvaluationContext ec = new OperationEvaluationContext(null, null, 0, 0, 0, null);
- return new WorkbookEvaluator(null, null).evaluateFormula(ec, ptgs);
+ return new WorkbookEvaluator(null, null, null).evaluateFormula(ec, ptgs);
}
/**
/**
* Allows tests to execute {@link WorkbookEvaluator}s and track the internal workings.
- *
+ *
* @author Josh Micich
*/
public final class WorkbookEvaluatorTestHelper {
private WorkbookEvaluatorTestHelper() {
// no instances of this class
}
-
+
public static WorkbookEvaluator createEvaluator(HSSFWorkbook wb, EvaluationListener listener) {
- return new WorkbookEvaluator(HSSFEvaluationWorkbook.create(wb), listener, null);
+ return new WorkbookEvaluator(HSSFEvaluationWorkbook.create(wb), listener, null, null);
}
}