mirror of https://github.com/apache/poi.git
Improvements to patch 47809 (support for UDFs)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@816016 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
a82e264754
commit
30dcd66257
|
@ -33,9 +33,7 @@ import org.apache.poi.util.StringUtil;
|
||||||
* @author Libin Roman (Vista Portal LDT. Developer)
|
* @author Libin Roman (Vista Portal LDT. Developer)
|
||||||
* @author Sergei Kozello (sergeikozello at mail.ru)
|
* @author Sergei Kozello (sergeikozello at mail.ru)
|
||||||
* @author Glen Stampoultzis (glens at apache.org)
|
* @author Glen Stampoultzis (glens at apache.org)
|
||||||
* @version 1.0-pre
|
* @author Petr Udalau - added method setFunction(boolean)
|
||||||
*
|
|
||||||
* Modified 8/31/09 by Petr Udalau - added method setFunction(boolean)
|
|
||||||
*/
|
*/
|
||||||
public final class NameRecord extends StandardRecord {
|
public final class NameRecord extends StandardRecord {
|
||||||
public final static short sid = 0x0018;
|
public final static short sid = 0x0018;
|
||||||
|
@ -135,7 +133,7 @@ public final class NameRecord extends StandardRecord {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For named ranges, and built-in names
|
* For named ranges, and built-in names
|
||||||
* @return the 1-based sheet number.
|
* @return the 1-based sheet number.
|
||||||
*/
|
*/
|
||||||
public int getSheetNumber()
|
public int getSheetNumber()
|
||||||
{
|
{
|
||||||
|
@ -239,13 +237,13 @@ public final class NameRecord extends StandardRecord {
|
||||||
public boolean isFunctionName() {
|
public boolean isFunctionName() {
|
||||||
return (field_1_option_flag & Option.OPT_FUNCTION_NAME) != 0;
|
return (field_1_option_flag & Option.OPT_FUNCTION_NAME) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the defined name refers to a user-defined 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.
|
* 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.
|
* @param value <code>true</code> indicates the name refers to a function.
|
||||||
*/
|
*/
|
||||||
public void setFunction(boolean function){
|
public void setFunction(boolean function){
|
||||||
if (function) {
|
if (function) {
|
||||||
field_1_option_flag |= Option.OPT_FUNCTION_NAME;
|
field_1_option_flag |= Option.OPT_FUNCTION_NAME;
|
||||||
|
@ -351,7 +349,7 @@ public final class NameRecord extends StandardRecord {
|
||||||
int field_8_length_description_text = field_15_description_text.length();
|
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_9_length_help_topic_text = field_16_help_topic_text.length();
|
||||||
int field_10_length_status_bar_text = field_17_status_bar_text.length();
|
int field_10_length_status_bar_text = field_17_status_bar_text.length();
|
||||||
|
|
||||||
// size defined below
|
// size defined below
|
||||||
out.writeShort(getOptionFlag());
|
out.writeShort(getOptionFlag());
|
||||||
out.writeByte(getKeyboardShortcut());
|
out.writeByte(getKeyboardShortcut());
|
||||||
|
@ -379,7 +377,7 @@ public final class NameRecord extends StandardRecord {
|
||||||
}
|
}
|
||||||
field_13_name_definition.serializeTokens(out);
|
field_13_name_definition.serializeTokens(out);
|
||||||
field_13_name_definition.serializeArrayConstantData(out);
|
field_13_name_definition.serializeArrayConstantData(out);
|
||||||
|
|
||||||
StringUtil.putCompressedUnicode( getCustomMenuText(), out);
|
StringUtil.putCompressedUnicode( getCustomMenuText(), out);
|
||||||
StringUtil.putCompressedUnicode( getDescriptionText(), out);
|
StringUtil.putCompressedUnicode( getDescriptionText(), out);
|
||||||
StringUtil.putCompressedUnicode( getHelpTopicText(), out);
|
StringUtil.putCompressedUnicode( getHelpTopicText(), out);
|
||||||
|
@ -388,14 +386,14 @@ public final class NameRecord extends StandardRecord {
|
||||||
private int getNameRawSize() {
|
private int getNameRawSize() {
|
||||||
if (isBuiltInName()) {
|
if (isBuiltInName()) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int nChars = field_12_name_text.length();
|
int nChars = field_12_name_text.length();
|
||||||
if(field_11_nameIsMultibyte) {
|
if(field_11_nameIsMultibyte) {
|
||||||
return 2 * nChars;
|
return 2 * nChars;
|
||||||
}
|
}
|
||||||
return nChars;
|
return nChars;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getDataSize() {
|
protected int getDataSize() {
|
||||||
return 13 // 3 shorts + 7 bytes
|
return 13 // 3 shorts + 7 bytes
|
||||||
+ getNameRawSize()
|
+ getNameRawSize()
|
||||||
|
@ -456,7 +454,7 @@ public final class NameRecord extends StandardRecord {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int nBytesAvailable = in.available() - (f7_customMenuLen
|
int nBytesAvailable = in.available() - (f7_customMenuLen
|
||||||
+ f8_descriptionTextLen + f9_helpTopicTextLen + f10_statusBarTextLen);
|
+ f8_descriptionTextLen + f9_helpTopicTextLen + f10_statusBarTextLen);
|
||||||
field_13_name_definition = Formula.read(field_4_length_name_definition, in, nBytesAvailable);
|
field_13_name_definition = Formula.read(field_4_length_name_definition, in, nBytesAvailable);
|
||||||
|
|
||||||
|
|
|
@ -22,14 +22,17 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
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.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.OperationEvaluationContext;
|
||||||
import org.apache.poi.ss.formula.eval.NotImplementedException;
|
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 static final class NotImplemented implements FreeRefFunction {
|
||||||
private final String _functionName;
|
private final String _functionName;
|
||||||
|
@ -42,13 +45,18 @@ public final class AnalysisToolPak implements ToolPack {
|
||||||
throw new NotImplementedException(_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) {
|
public FreeRefFunction findFunction(String name) {
|
||||||
return _functionsByName.get(name);
|
return _functionsByName.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, FreeRefFunction> createFunctionsMap() {
|
private Map<String, FreeRefFunction> createFunctionsMap() {
|
||||||
Map<String, FreeRefFunction> m = new HashMap<String, FreeRefFunction>(100);
|
Map<String, FreeRefFunction> m = new HashMap<String, FreeRefFunction>(100);
|
||||||
|
|
||||||
|
@ -153,16 +161,4 @@ public final class AnalysisToolPak implements ToolPack {
|
||||||
FreeRefFunction func = pFunc == null ? new NotImplemented(functionName) : pFunc;
|
FreeRefFunction func = pFunc == null ? new NotImplemented(functionName) : pFunc;
|
||||||
m.put(functionName, func);
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
package org.apache.poi.hssf.record.formula.eval;
|
package org.apache.poi.hssf.record.formula.eval;
|
||||||
|
|
||||||
import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
|
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.OperationEvaluationContext;
|
||||||
import org.apache.poi.ss.formula.eval.NotImplementedException;
|
import org.apache.poi.ss.formula.eval.NotImplementedException;
|
||||||
/**
|
/**
|
||||||
|
@ -28,8 +26,7 @@ import org.apache.poi.ss.formula.eval.NotImplementedException;
|
||||||
* <tt>AbstractFunctionPtg.field_2_fnc_index</tt> == 255)
|
* <tt>AbstractFunctionPtg.field_2_fnc_index</tt> == 255)
|
||||||
*
|
*
|
||||||
* @author Josh Micich
|
* @author Josh Micich
|
||||||
*
|
* @author Petr Udalau - Improved resolving of UDFs through the ToolPacks.
|
||||||
* Modified 09/07/09 by Petr Udalau - Improved resolving of UDFs through the ToolPacks.
|
|
||||||
*/
|
*/
|
||||||
final class UserDefinedFunction implements FreeRefFunction {
|
final class UserDefinedFunction implements FreeRefFunction {
|
||||||
|
|
||||||
|
@ -40,60 +37,28 @@ final class UserDefinedFunction implements FreeRefFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
|
public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
|
||||||
EvaluationWorkbook workbook = ec.getWorkbook();
|
|
||||||
int nIncomingArgs = args.length;
|
int nIncomingArgs = args.length;
|
||||||
if(nIncomingArgs < 1) {
|
if(nIncomingArgs < 1) {
|
||||||
throw new RuntimeException("function name argument missing");
|
throw new RuntimeException("function name argument missing");
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueEval nameArg = args[0];
|
ValueEval nameArg = args[0];
|
||||||
FreeRefFunction targetFunc;
|
String functionName;
|
||||||
if (nameArg instanceof NameEval) {
|
if (nameArg instanceof NameEval) {
|
||||||
targetFunc = findInternalUserDefinedFunction(workbook, (NameEval) nameArg);
|
functionName = ((NameEval) nameArg).getFunctionName();
|
||||||
} else if (nameArg instanceof NameXEval) {
|
} else if (nameArg instanceof NameXEval) {
|
||||||
targetFunc = findExternalUserDefinedFunction(workbook, (NameXEval) nameArg);
|
functionName = ec.getWorkbook().resolveNameXText(((NameXEval) nameArg).getPtg());
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("First argument should be a NameEval, but got ("
|
throw new RuntimeException("First argument should be a NameEval, but got ("
|
||||||
+ nameArg.getClass().getName() + ")");
|
+ nameArg.getClass().getName() + ")");
|
||||||
}
|
}
|
||||||
|
FreeRefFunction targetFunc = ec.findUserDefinedFunction(functionName);
|
||||||
|
if (targetFunc == null) {
|
||||||
|
throw new NotImplementedException(functionName);
|
||||||
|
}
|
||||||
int nOutGoingArgs = nIncomingArgs -1;
|
int nOutGoingArgs = nIncomingArgs -1;
|
||||||
ValueEval[] outGoingArgs = new ValueEval[nOutGoingArgs];
|
ValueEval[] outGoingArgs = new ValueEval[nOutGoingArgs];
|
||||||
System.arraycopy(args, 1, outGoingArgs, 0, nOutGoingArgs);
|
System.arraycopy(args, 1, outGoingArgs, 0, nOutGoingArgs);
|
||||||
return targetFunc.evaluate(outGoingArgs, ec);
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,102 +0,0 @@
|
||||||
/* ====================================================================
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
/* ====================================================================
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
==================================================================== */
|
==================================================================== */
|
||||||
|
|
||||||
package org.apache.poi.hssf.record.formula.toolpack;
|
package org.apache.poi.hssf.record.formula.udf;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -23,29 +23,27 @@ import java.util.Map;
|
||||||
import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
|
import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default tool pack.
|
* Default UDF finder - for adding your own user defined functions.
|
||||||
* If you want to add some UDF, but you don't want to create new tool pack, use this.
|
*
|
||||||
*
|
|
||||||
* @author PUdalau
|
* @author PUdalau
|
||||||
*/
|
*/
|
||||||
public class DefaultToolPack implements ToolPack {
|
public final class DefaultUDFFinder implements UDFFinder {
|
||||||
private Map<String, FreeRefFunction> functionsByName = new HashMap<String, FreeRefFunction>();
|
private final Map<String, FreeRefFunction> _functionsByName;
|
||||||
|
|
||||||
public void addFunction(String name, FreeRefFunction evaluator) {
|
public DefaultUDFFinder(String[] functionNames, FreeRefFunction[] functionImpls) {
|
||||||
if (evaluator != null){
|
int nFuncs = functionNames.length;
|
||||||
functionsByName.put(name, evaluator);
|
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 boolean containsFunction(String name) {
|
public FreeRefFunction findFunction(String name) {
|
||||||
return functionsByName.containsKey(name);
|
return _functionsByName.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FreeRefFunction findFunction(String name) {
|
|
||||||
return functionsByName.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeFunction(String name) {
|
|
||||||
functionsByName.remove(name);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -15,42 +15,24 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
==================================================================== */
|
==================================================================== */
|
||||||
|
|
||||||
package org.apache.poi.hssf.record.formula.toolpack;
|
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;
|
import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common interface for any new tool pack with executors for functions.
|
* Common interface for "Add-in" libraries and user defined function libraries.
|
||||||
*
|
*
|
||||||
* @author PUdalau
|
* @author PUdalau
|
||||||
*/
|
*/
|
||||||
public interface ToolPack {
|
public interface UDFFinder {
|
||||||
|
public static final UDFFinder DEFAULT = new AggregatingUDFFinder(AnalysisToolPak.instance);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns executor by specified name. Returns <code>null</code> if tool
|
* Returns executor by specified name. Returns <code>null</code> if the function name is unknown.
|
||||||
* pack doesn't contains such function.
|
*
|
||||||
*
|
|
||||||
* @param name Name of function.
|
* @param name Name of function.
|
||||||
* @return Function executor.
|
* @return Function executor.
|
||||||
*/
|
*/
|
||||||
FreeRefFunction findFunction(String name);
|
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);
|
|
||||||
}
|
}
|
|
@ -6,7 +6,7 @@
|
||||||
(the "License"); you may not use this file except in compliance with
|
(the "License"); you may not use this file except in compliance with
|
||||||
the License. You may obtain a copy of the License at
|
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
|
Unless required by applicable law or agreed to in writing, software
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@ -24,146 +24,145 @@ import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
|
||||||
import org.apache.poi.hssf.record.formula.NamePtg;
|
import org.apache.poi.hssf.record.formula.NamePtg;
|
||||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||||
import org.apache.poi.hssf.record.formula.Ptg;
|
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.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
|
* Internal POI use only
|
||||||
*
|
*
|
||||||
* @author Josh Micich
|
* @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 {
|
public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, EvaluationWorkbook, FormulaParsingWorkbook {
|
||||||
|
|
||||||
private final HSSFWorkbook _uBook;
|
private final HSSFWorkbook _uBook;
|
||||||
private final Workbook _iBook;
|
private final Workbook _iBook;
|
||||||
|
|
||||||
public static HSSFEvaluationWorkbook create(HSSFWorkbook book) {
|
public static HSSFEvaluationWorkbook create(HSSFWorkbook book) {
|
||||||
if (book == null) {
|
if (book == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new HSSFEvaluationWorkbook(book);
|
return new HSSFEvaluationWorkbook(book);
|
||||||
}
|
}
|
||||||
|
|
||||||
private HSSFEvaluationWorkbook(HSSFWorkbook book) {
|
private HSSFEvaluationWorkbook(HSSFWorkbook book) {
|
||||||
_uBook = book;
|
_uBook = book;
|
||||||
_iBook = book.getWorkbook();
|
_iBook = book.getWorkbook();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getExternalSheetIndex(String sheetName) {
|
public int getExternalSheetIndex(String sheetName) {
|
||||||
int sheetIndex = _uBook.getSheetIndex(sheetName);
|
int sheetIndex = _uBook.getSheetIndex(sheetName);
|
||||||
return _iBook.checkExternSheet(sheetIndex);
|
return _iBook.checkExternSheet(sheetIndex);
|
||||||
}
|
}
|
||||||
public int getExternalSheetIndex(String workbookName, String sheetName) {
|
public int getExternalSheetIndex(String workbookName, String sheetName) {
|
||||||
return _iBook.getExternalSheetIndex(workbookName, sheetName);
|
return _iBook.getExternalSheetIndex(workbookName, sheetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NameXPtg getNameXPtg(String name) {
|
public NameXPtg getNameXPtg(String name) {
|
||||||
return _iBook.getNameXPtg(name);
|
return _iBook.getNameXPtg(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lookup a named range by its name.
|
* Lookup a named range by its name.
|
||||||
*
|
*
|
||||||
* @param name the name to search
|
* @param name the name to search
|
||||||
* @param sheetIndex the 0-based index of the sheet this formula belongs to.
|
* @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
|
* The sheet index is required to resolve sheet-level names. <code>-1</code> means workbook-global names
|
||||||
*/
|
*/
|
||||||
public EvaluationName getName(String name, int sheetIndex) {
|
public EvaluationName getName(String name, int sheetIndex) {
|
||||||
for(int i=0; i < _iBook.getNumNames(); i++) {
|
for(int i=0; i < _iBook.getNumNames(); i++) {
|
||||||
NameRecord nr = _iBook.getNameRecord(i);
|
NameRecord nr = _iBook.getNameRecord(i);
|
||||||
if (nr.getSheetNumber() == sheetIndex+1 && name.equalsIgnoreCase(nr.getNameText())) {
|
if (nr.getSheetNumber() == sheetIndex+1 && name.equalsIgnoreCase(nr.getNameText())) {
|
||||||
return new Name(nr, i);
|
return new Name(nr, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sheetIndex == -1 ? null : getName(name, -1);
|
return sheetIndex == -1 ? null : getName(name, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSheetIndex(EvaluationSheet evalSheet) {
|
public int getSheetIndex(EvaluationSheet evalSheet) {
|
||||||
HSSFSheet sheet = ((HSSFEvaluationSheet)evalSheet).getHSSFSheet();
|
HSSFSheet sheet = ((HSSFEvaluationSheet)evalSheet).getHSSFSheet();
|
||||||
return _uBook.getSheetIndex(sheet);
|
return _uBook.getSheetIndex(sheet);
|
||||||
}
|
}
|
||||||
public int getSheetIndex(String sheetName) {
|
public int getSheetIndex(String sheetName) {
|
||||||
return _uBook.getSheetIndex(sheetName);
|
return _uBook.getSheetIndex(sheetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSheetName(int sheetIndex) {
|
public String getSheetName(int sheetIndex) {
|
||||||
return _uBook.getSheetName(sheetIndex);
|
return _uBook.getSheetName(sheetIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public EvaluationSheet getSheet(int sheetIndex) {
|
public EvaluationSheet getSheet(int sheetIndex) {
|
||||||
return new HSSFEvaluationSheet(_uBook.getSheetAt(sheetIndex));
|
return new HSSFEvaluationSheet(_uBook.getSheetAt(sheetIndex));
|
||||||
}
|
}
|
||||||
public int convertFromExternSheetIndex(int externSheetIndex) {
|
public int convertFromExternSheetIndex(int externSheetIndex) {
|
||||||
return _iBook.getSheetIndexFromExternSheetIndex(externSheetIndex);
|
return _iBook.getSheetIndexFromExternSheetIndex(externSheetIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExternalSheet getExternalSheet(int externSheetIndex) {
|
public ExternalSheet getExternalSheet(int externSheetIndex) {
|
||||||
return _iBook.getExternalSheet(externSheetIndex);
|
return _iBook.getExternalSheet(externSheetIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String resolveNameXText(NameXPtg n) {
|
public String resolveNameXText(NameXPtg n) {
|
||||||
return _iBook.resolveNameXText(n.getSheetRefIndex(), n.getNameIndex());
|
return _iBook.resolveNameXText(n.getSheetRefIndex(), n.getNameIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSheetNameByExternSheet(int externSheetIndex) {
|
public String getSheetNameByExternSheet(int externSheetIndex) {
|
||||||
return _iBook.findSheetNameFromExternSheet(externSheetIndex);
|
return _iBook.findSheetNameFromExternSheet(externSheetIndex);
|
||||||
}
|
}
|
||||||
public String getNameText(NamePtg namePtg) {
|
public String getNameText(NamePtg namePtg) {
|
||||||
return _iBook.getNameRecord(namePtg.getIndex()).getNameText();
|
return _iBook.getNameRecord(namePtg.getIndex()).getNameText();
|
||||||
}
|
}
|
||||||
public EvaluationName getName(NamePtg namePtg) {
|
public EvaluationName getName(NamePtg namePtg) {
|
||||||
int ix = namePtg.getIndex();
|
int ix = namePtg.getIndex();
|
||||||
return new Name(_iBook.getNameRecord(ix), ix);
|
return new Name(_iBook.getNameRecord(ix), ix);
|
||||||
}
|
}
|
||||||
public Ptg[] getFormulaTokens(EvaluationCell evalCell) {
|
public Ptg[] getFormulaTokens(EvaluationCell evalCell) {
|
||||||
HSSFCell cell = ((HSSFEvaluationCell)evalCell).getHSSFCell();
|
HSSFCell cell = ((HSSFEvaluationCell)evalCell).getHSSFCell();
|
||||||
if (false) {
|
if (false) {
|
||||||
// re-parsing the formula text also works, but is a waste of time
|
// 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
|
// 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.
|
// 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()));
|
return HSSFFormulaParser.parse(cell.getCellFormula(), _uBook, FormulaType.CELL, _uBook.getSheetIndex(cell.getSheet()));
|
||||||
}
|
}
|
||||||
FormulaRecordAggregate fra = (FormulaRecordAggregate) cell.getCellValueRecord();
|
FormulaRecordAggregate fra = (FormulaRecordAggregate) cell.getCellValueRecord();
|
||||||
return fra.getFormulaTokens();
|
return fra.getFormulaTokens();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class Name implements EvaluationName {
|
private static final class Name implements EvaluationName {
|
||||||
|
|
||||||
private final NameRecord _nameRecord;
|
private final NameRecord _nameRecord;
|
||||||
private final int _index;
|
private final int _index;
|
||||||
|
|
||||||
public Name(NameRecord nameRecord, int index) {
|
public Name(NameRecord nameRecord, int index) {
|
||||||
_nameRecord = nameRecord;
|
_nameRecord = nameRecord;
|
||||||
_index = index;
|
_index = index;
|
||||||
}
|
}
|
||||||
public Ptg[] getNameDefinition() {
|
public Ptg[] getNameDefinition() {
|
||||||
return _nameRecord.getNameDefinition();
|
return _nameRecord.getNameDefinition();
|
||||||
}
|
}
|
||||||
public String getNameText() {
|
public String getNameText() {
|
||||||
return _nameRecord.getNameText();
|
return _nameRecord.getNameText();
|
||||||
}
|
}
|
||||||
public boolean hasFormula() {
|
public boolean hasFormula() {
|
||||||
return _nameRecord.hasFormula();
|
return _nameRecord.hasFormula();
|
||||||
}
|
}
|
||||||
public boolean isFunctionName() {
|
public boolean isFunctionName() {
|
||||||
return _nameRecord.isFunctionName();
|
return _nameRecord.isFunctionName();
|
||||||
}
|
}
|
||||||
public boolean isRange() {
|
public boolean isRange() {
|
||||||
return _nameRecord.hasFormula(); // TODO - is this right?
|
return _nameRecord.hasFormula(); // TODO - is this right?
|
||||||
}
|
}
|
||||||
public NamePtg createPtg() {
|
public NamePtg createPtg() {
|
||||||
return new NamePtg(_index);
|
return new NamePtg(_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpreadsheetVersion getSpreadsheetVersion(){
|
public SpreadsheetVersion getSpreadsheetVersion(){
|
||||||
return SpreadsheetVersion.EXCEL97;
|
return SpreadsheetVersion.EXCEL97;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FreeRefFunction findUserDefinedFunction(String functionName) {
|
|
||||||
return _uBook.getUserDefinedFunction(functionName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
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.eval.ValueEval;
|
||||||
|
import org.apache.poi.hssf.record.formula.udf.UDFFinder;
|
||||||
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment;
|
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment;
|
||||||
import org.apache.poi.ss.formula.IStabilityClassifier;
|
import org.apache.poi.ss.formula.IStabilityClassifier;
|
||||||
import org.apache.poi.ss.formula.WorkbookEvaluator;
|
import org.apache.poi.ss.formula.WorkbookEvaluator;
|
||||||
|
@ -64,9 +65,27 @@ public class HSSFFormulaEvaluator implements FormulaEvaluator {
|
||||||
* evaluation begins.
|
* evaluation begins.
|
||||||
*/
|
*/
|
||||||
public HSSFFormulaEvaluator(HSSFWorkbook workbook, IStabilityClassifier stabilityClassifier) {
|
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
|
* Coordinates several formula evaluators together so that formulas that involve external
|
||||||
* references can be evaluated.
|
* references can be evaluated.
|
||||||
|
|
|
@ -24,11 +24,9 @@ import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.apache.poi.POIDocument;
|
import org.apache.poi.POIDocument;
|
||||||
|
@ -64,12 +62,10 @@ import org.apache.poi.hssf.record.formula.Ptg;
|
||||||
import org.apache.poi.hssf.record.formula.Ref3DPtg;
|
import org.apache.poi.hssf.record.formula.Ref3DPtg;
|
||||||
import org.apache.poi.hssf.record.formula.SheetNameFormatter;
|
import org.apache.poi.hssf.record.formula.SheetNameFormatter;
|
||||||
import org.apache.poi.hssf.record.formula.UnionPtg;
|
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.hssf.util.CellReference;
|
||||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||||
import org.apache.poi.ss.usermodel.CreationHelper;
|
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.usermodel.Row.MissingCellPolicy;
|
||||||
import org.apache.poi.ss.formula.FormulaType;
|
import org.apache.poi.ss.formula.FormulaType;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
|
@ -86,9 +82,6 @@ import org.apache.poi.util.POILogger;
|
||||||
* @author Andrew C. Oliver (acoliver at apache dot org)
|
* @author Andrew C. Oliver (acoliver at apache dot org)
|
||||||
* @author Glen Stampoultzis (glens at apache.org)
|
* @author Glen Stampoultzis (glens at apache.org)
|
||||||
* @author Shawn Laubach (slaubach at apache dot 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 {
|
public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.usermodel.Workbook {
|
||||||
private static final Pattern COMMA_PATTERN = Pattern.compile(",");
|
private static final Pattern COMMA_PATTERN = Pattern.compile(",");
|
||||||
|
@ -167,9 +160,6 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||||
|
|
||||||
|
|
||||||
private static POILogger log = POILogFactory.getLogger(HSSFWorkbook.class);
|
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!)
|
* Creates new HSSFWorkbook from scratch (start here!)
|
||||||
|
@ -186,7 +176,6 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||||
workbook = book;
|
workbook = book;
|
||||||
_sheets = new ArrayList( INITIAL_CAPACITY );
|
_sheets = new ArrayList( INITIAL_CAPACITY );
|
||||||
names = new ArrayList( INITIAL_CAPACITY );
|
names = new ArrayList( INITIAL_CAPACITY );
|
||||||
udfFunctions = new HashMap<String, FreeRefFunction>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public HSSFWorkbook(POIFSFileSystem fs) throws IOException {
|
public HSSFWorkbook(POIFSFileSystem fs) throws IOException {
|
||||||
|
@ -278,7 +267,6 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||||
|
|
||||||
_sheets = new ArrayList(INITIAL_CAPACITY);
|
_sheets = new ArrayList(INITIAL_CAPACITY);
|
||||||
names = new ArrayList(INITIAL_CAPACITY);
|
names = new ArrayList(INITIAL_CAPACITY);
|
||||||
udfFunctions = new HashMap<String, FreeRefFunction>();
|
|
||||||
|
|
||||||
// Grab the data from the workbook stream, however
|
// Grab the data from the workbook stream, however
|
||||||
// it happens to be spelled.
|
// it happens to be spelled.
|
||||||
|
@ -1627,25 +1615,6 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)?
|
* Is the workbook protected with a password (not encrypted)?
|
||||||
|
@ -1729,5 +1698,4 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||||
public NameXPtg getNameXPtg(String name) {
|
public NameXPtg getNameXPtg(String name) {
|
||||||
return workbook.getNameXPtg(name);
|
return workbook.getNameXPtg(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ package org.apache.poi.ss.formula;
|
||||||
import org.apache.poi.hssf.record.formula.NamePtg;
|
import org.apache.poi.hssf.record.formula.NamePtg;
|
||||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||||
import org.apache.poi.hssf.record.formula.Ptg;
|
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/>
|
* Abstracts a workbook for the purpose of formula evaluation.<br/>
|
||||||
|
@ -28,8 +27,6 @@ import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
|
||||||
* For POI internal use only
|
* For POI internal use only
|
||||||
*
|
*
|
||||||
* @author Josh Micich
|
* @author Josh Micich
|
||||||
*
|
|
||||||
* Modified 09/07/09 by Petr Udalau - added methods for searching for UDFs of this Workbook.
|
|
||||||
*/
|
*/
|
||||||
public interface EvaluationWorkbook {
|
public interface EvaluationWorkbook {
|
||||||
String getSheetName(int sheetIndex);
|
String getSheetName(int sheetIndex);
|
||||||
|
@ -54,17 +51,6 @@ public interface EvaluationWorkbook {
|
||||||
String resolveNameXText(NameXPtg ptg);
|
String resolveNameXText(NameXPtg ptg);
|
||||||
Ptg[] getFormulaTokens(EvaluationCell cell);
|
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 {
|
class ExternalSheet {
|
||||||
private final String _workbookName;
|
private final String _workbookName;
|
||||||
private final String _sheetName;
|
private final String _sheetName;
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.apache.poi.hssf.record.formula.eval.AreaEval;
|
||||||
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
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.RefEval;
|
||||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
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.SpreadsheetVersion;
|
||||||
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
|
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
|
||||||
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet;
|
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet;
|
||||||
|
@ -256,4 +257,8 @@ public final class OperationEvaluationContext {
|
||||||
}
|
}
|
||||||
return CellReference.classifyCellReference(str, ssVersion);
|
return CellReference.classifyCellReference(str, ssVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FreeRefFunction findUserDefinedFunction(String functionName) {
|
||||||
|
return _bookEvaluator.findUserDefinedFunction(functionName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,8 @@ import org.apache.poi.hssf.record.formula.eval.OperationEval;
|
||||||
import org.apache.poi.hssf.record.formula.eval.RefEval;
|
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.StringEval;
|
||||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
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.hssf.util.CellReference;
|
||||||
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
|
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
|
||||||
import org.apache.poi.ss.formula.eval.NotImplementedException;
|
import org.apache.poi.ss.formula.eval.NotImplementedException;
|
||||||
|
@ -87,12 +89,16 @@ public final class WorkbookEvaluator {
|
||||||
private final Map<String, Integer> _sheetIndexesByName;
|
private final Map<String, Integer> _sheetIndexesByName;
|
||||||
private CollaboratingWorkbooksEnvironment _collaboratingWorkbookEnvironment;
|
private CollaboratingWorkbooksEnvironment _collaboratingWorkbookEnvironment;
|
||||||
private final IStabilityClassifier _stabilityClassifier;
|
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,
|
/* package */ WorkbookEvaluator(EvaluationWorkbook workbook, IEvaluationListener evaluationListener,
|
||||||
IStabilityClassifier stabilityClassifier) {
|
IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) {
|
||||||
_workbook = workbook;
|
_workbook = workbook;
|
||||||
_evaluationListener = evaluationListener;
|
_evaluationListener = evaluationListener;
|
||||||
_cache = new EvaluationCache(evaluationListener);
|
_cache = new EvaluationCache(evaluationListener);
|
||||||
|
@ -101,6 +107,7 @@ public final class WorkbookEvaluator {
|
||||||
_collaboratingWorkbookEnvironment = CollaboratingWorkbooksEnvironment.EMPTY;
|
_collaboratingWorkbookEnvironment = CollaboratingWorkbooksEnvironment.EMPTY;
|
||||||
_workbookIx = 0;
|
_workbookIx = 0;
|
||||||
_stabilityClassifier = stabilityClassifier;
|
_stabilityClassifier = stabilityClassifier;
|
||||||
|
_udfFinder = udfFinder == null ? UDFFinder.DEFAULT : udfFinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -516,4 +523,7 @@ public final class WorkbookEvaluator {
|
||||||
EvaluationCell cell = sheet.getCell(rowIndex, columnIndex);
|
EvaluationCell cell = sheet.getCell(rowIndex, columnIndex);
|
||||||
return evaluateAny(cell, sheetIndex, rowIndex, columnIndex, tracker);
|
return evaluateAny(cell, sheetIndex, rowIndex, columnIndex, tracker);
|
||||||
}
|
}
|
||||||
|
public FreeRefFunction findUserDefinedFunction(String functionName) {
|
||||||
|
return _udfFinder.findFunction(functionName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,6 @@ import org.apache.poi.ss.usermodel.Workbook;
|
||||||
* updated after a call to {@link #getOrCreateUpdatableCell(String, int, int)}.
|
* updated after a call to {@link #getOrCreateUpdatableCell(String, int, int)}.
|
||||||
*
|
*
|
||||||
* @author Josh Micich
|
* @author Josh Micich
|
||||||
*
|
|
||||||
* Modified 09/07/09 by Petr Udalau - added methods for searching for UDFs of this Workbook.
|
|
||||||
*/
|
*/
|
||||||
final class ForkedEvaluationWorkbook implements EvaluationWorkbook {
|
final class ForkedEvaluationWorkbook implements EvaluationWorkbook {
|
||||||
|
|
||||||
|
@ -144,8 +142,4 @@ final class ForkedEvaluationWorkbook implements EvaluationWorkbook {
|
||||||
return _index - o._index;
|
return _index - o._index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public FreeRefFunction findUserDefinedFunction(String functionName) {
|
|
||||||
return _masterBook.findUserDefinedFunction(functionName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
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.eval.ValueEval;
|
||||||
|
import org.apache.poi.hssf.record.formula.udf.UDFFinder;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
|
import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
|
@ -47,9 +48,9 @@ public final class ForkedEvaluator {
|
||||||
private WorkbookEvaluator _evaluator;
|
private WorkbookEvaluator _evaluator;
|
||||||
private ForkedEvaluationWorkbook _sewb;
|
private ForkedEvaluationWorkbook _sewb;
|
||||||
|
|
||||||
private ForkedEvaluator(EvaluationWorkbook masterWorkbook, IStabilityClassifier stabilityClassifier) {
|
private ForkedEvaluator(EvaluationWorkbook masterWorkbook, IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) {
|
||||||
_sewb = new ForkedEvaluationWorkbook(masterWorkbook);
|
_sewb = new ForkedEvaluationWorkbook(masterWorkbook);
|
||||||
_evaluator = new WorkbookEvaluator(_sewb, stabilityClassifier);
|
_evaluator = new WorkbookEvaluator(_sewb, stabilityClassifier, udfFinder);
|
||||||
}
|
}
|
||||||
private static EvaluationWorkbook createEvaluationWorkbook(Workbook wb) {
|
private static EvaluationWorkbook createEvaluationWorkbook(Workbook wb) {
|
||||||
if (wb instanceof HSSFWorkbook) {
|
if (wb instanceof HSSFWorkbook) {
|
||||||
|
@ -61,8 +62,17 @@ public final class ForkedEvaluator {
|
||||||
// }
|
// }
|
||||||
throw new IllegalArgumentException("Unexpected workbook type (" + wb.getClass().getName() + ")");
|
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) {
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -49,8 +49,6 @@ package org.apache.poi.ss.usermodel;
|
||||||
* name.setRefersToFormula("IF(Loan_Amount*Interest_Rate>0,1,0)");
|
* name.setRefersToFormula("IF(Loan_Amount*Interest_Rate>0,1,0)");
|
||||||
*
|
*
|
||||||
* </blockquote></pre>
|
* </blockquote></pre>
|
||||||
*
|
|
||||||
* Modified 8/31/09 by Petr Udalau - added method setFunction(boolean)
|
|
||||||
*/
|
*/
|
||||||
public interface Name {
|
public interface Name {
|
||||||
|
|
||||||
|
@ -61,14 +59,14 @@ public interface Name {
|
||||||
*/
|
*/
|
||||||
String getSheetName();
|
String getSheetName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the name of the named range
|
* Gets the name of the named range
|
||||||
*
|
*
|
||||||
* @return named range name
|
* @return named range name
|
||||||
*/
|
*/
|
||||||
String getNameName();
|
String getNameName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the name of the named range
|
* 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>
|
* <p>The following is a list of syntax rules that you need to be aware of when you create and edit names.</p>
|
||||||
|
@ -118,7 +116,7 @@ public interface Name {
|
||||||
void setNameName(String name);
|
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
|
* @return the reference for this name, <code>null</code> if it has not been set yet. Never empty string
|
||||||
* @see #setRefersToFormula(String)
|
* @see #setRefersToFormula(String)
|
||||||
|
|
|
@ -21,15 +21,12 @@ import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
|
|
||||||
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
|
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* High level representation of a Excel workbook. This is the first object most users
|
* 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
|
* will construct whether they are reading or writing a workbook. It is also the
|
||||||
* top level object for creating new sheets/etc.
|
* 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 {
|
public interface Workbook {
|
||||||
|
|
||||||
|
@ -189,7 +186,7 @@ public interface Workbook {
|
||||||
* @param index of the sheet to remove (0-based)
|
* @param index of the sheet to remove (0-based)
|
||||||
*/
|
*/
|
||||||
void removeSheetAt(int index);
|
void removeSheetAt(int index);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the repeating rows and columns for a sheet (as found in
|
* Sets the repeating rows and columns for a sheet (as found in
|
||||||
* File->PageSetup->Sheet). This is function is included in the workbook
|
* File->PageSetup->Sheet). This is function is included in the workbook
|
||||||
|
@ -374,7 +371,7 @@ public interface Workbook {
|
||||||
* Sets the policy on what to do when
|
* Sets the policy on what to do when
|
||||||
* getting missing or blank cells from a row.
|
* 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 Row#getCell(int)} }. See
|
||||||
* {@link MissingCellPolicy}
|
* {@link MissingCellPolicy}
|
||||||
*/
|
*/
|
||||||
|
@ -467,29 +464,4 @@ public interface Workbook {
|
||||||
* @param hidden 0 for not hidden, 1 for hidden, 2 for very hidden
|
* @param hidden 0 for not hidden, 1 for hidden, 2 for very hidden
|
||||||
*/
|
*/
|
||||||
void setSheetHidden(int sheetIx, int 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();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ package org.apache.poi.xssf.usermodel;
|
||||||
import org.apache.poi.hssf.record.formula.NamePtg;
|
import org.apache.poi.hssf.record.formula.NamePtg;
|
||||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||||
import org.apache.poi.hssf.record.formula.Ptg;
|
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.formula.*;
|
||||||
import org.apache.poi.ss.SpreadsheetVersion;
|
import org.apache.poi.ss.SpreadsheetVersion;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName;
|
||||||
|
@ -29,8 +28,6 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName;
|
||||||
* Internal POI use only
|
* Internal POI use only
|
||||||
*
|
*
|
||||||
* @author Josh Micich
|
* @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 final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, EvaluationWorkbook, FormulaParsingWorkbook {
|
||||||
|
|
||||||
|
@ -180,8 +177,4 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||||
public SpreadsheetVersion getSpreadsheetVersion(){
|
public SpreadsheetVersion getSpreadsheetVersion(){
|
||||||
return SpreadsheetVersion.EXCEL2007;
|
return SpreadsheetVersion.EXCEL2007;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FreeRefFunction findUserDefinedFunction(String functionName) {
|
|
||||||
return _uBook.getUserDefinedFunction(functionName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,8 @@ import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
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.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.IStabilityClassifier;
|
||||||
import org.apache.poi.ss.formula.WorkbookEvaluator;
|
import org.apache.poi.ss.formula.WorkbookEvaluator;
|
||||||
import org.apache.poi.ss.usermodel.Cell;
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
|
@ -47,16 +49,31 @@ public class XSSFFormulaEvaluator implements FormulaEvaluator {
|
||||||
private WorkbookEvaluator _bookEvaluator;
|
private WorkbookEvaluator _bookEvaluator;
|
||||||
|
|
||||||
public XSSFFormulaEvaluator(XSSFWorkbook workbook) {
|
public XSSFFormulaEvaluator(XSSFWorkbook workbook) {
|
||||||
this(workbook, null);
|
this(workbook, null, null);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @param stabilityClassifier used to optimise caching performance. Pass <code>null</code>
|
* @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.
|
* evaluation begins.
|
||||||
|
* @deprecated (Sep 2009) (reduce overloading) use {@link #create(HSSFWorkbook, IStabilityClassifier, UDFFinder)}
|
||||||
*/
|
*/
|
||||||
public XSSFFormulaEvaluator(XSSFWorkbook workbook, IStabilityClassifier stabilityClassifier) {
|
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
|
* Should be called whenever there are major changes (e.g. moving sheets) to input cells
|
||||||
|
|
|
@ -32,7 +32,6 @@ import org.apache.poi.POIXMLDocumentPart;
|
||||||
import org.apache.poi.POIXMLException;
|
import org.apache.poi.POIXMLException;
|
||||||
import org.apache.poi.POIXMLProperties;
|
import org.apache.poi.POIXMLProperties;
|
||||||
import org.apache.poi.hssf.record.formula.SheetNameFormatter;
|
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.exceptions.OpenXML4JException;
|
||||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
|
@ -41,7 +40,6 @@ import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||||
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
|
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
|
||||||
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
|
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
|
||||||
import org.apache.poi.openxml4j.opc.TargetMode;
|
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.Row;
|
||||||
import org.apache.poi.ss.usermodel.Sheet;
|
import org.apache.poi.ss.usermodel.Sheet;
|
||||||
import org.apache.poi.ss.usermodel.Workbook;
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
|
@ -65,8 +63,6 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
|
||||||
* High level representation of a SpreadsheetML workbook. This is the first object most users
|
* 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
|
* will construct whether they are reading or writing a workbook. It is also the
|
||||||
* top level object for creating new sheets/etc.
|
* 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> {
|
public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<XSSFSheet> {
|
||||||
private static final Pattern COMMA_PATTERN = Pattern.compile(",");
|
private static final Pattern COMMA_PATTERN = Pattern.compile(",");
|
||||||
|
@ -133,9 +129,6 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
|
||||||
private List<XSSFPictureData> pictures;
|
private List<XSSFPictureData> pictures;
|
||||||
|
|
||||||
private static POILogger logger = POILogFactory.getLogger(XSSFWorkbook.class);
|
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.
|
* Create a new SpreadsheetML workbook.
|
||||||
|
@ -1352,23 +1345,4 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
|
||||||
public MapInfo getMapInfo(){
|
public MapInfo getMapInfo(){
|
||||||
return mapInfo;
|
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,97 +17,79 @@
|
||||||
|
|
||||||
package org.apache.poi.hssf.record.formula.eval;
|
package org.apache.poi.hssf.record.formula.eval;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||||
import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
|
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.udf.DefaultUDFFinder;
|
||||||
import org.apache.poi.hssf.record.formula.toolpack.MainToolPacksHandler;
|
import org.apache.poi.hssf.record.formula.udf.AggregatingUDFFinder;
|
||||||
import org.apache.poi.hssf.record.formula.toolpack.ToolPack;
|
import org.apache.poi.hssf.record.formula.udf.UDFFinder;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
|
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFRow;
|
import org.apache.poi.hssf.usermodel.HSSFRow;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
import org.apache.poi.ss.formula.OperationEvaluationContext;
|
import org.apache.poi.ss.formula.OperationEvaluationContext;
|
||||||
import org.apache.poi.ss.usermodel.Workbook;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Josh Micich
|
* @author Josh Micich
|
||||||
*
|
* @author Petr Udalau - registering UDFs in workbook and using ToolPacks.
|
||||||
* Modified 09/14/09 by Petr Udalau - Test of registering UDFs in workbook and
|
|
||||||
* using ToolPacks.
|
|
||||||
*/
|
*/
|
||||||
public final class TestExternalFunction extends TestCase {
|
public final class TestExternalFunction extends TestCase {
|
||||||
|
|
||||||
private static class MyFunc implements FreeRefFunction {
|
private static class MyFunc implements FreeRefFunction {
|
||||||
public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
|
public MyFunc() {
|
||||||
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) {
|
||||||
public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
|
if (args.length != 1 || !(args[0] instanceof StringEval)) {
|
||||||
if (args.length != 1 || !(args[0] instanceof StringEval)) {
|
return ErrorEval.VALUE_INVALID;
|
||||||
return ErrorEval.VALUE_INVALID;
|
}
|
||||||
} else {
|
StringEval input = (StringEval) args[0];
|
||||||
StringEval input = (StringEval) args[0];
|
return new StringEval(input.getStringValue() + "abc");
|
||||||
return new StringEval(input.getStringValue() + "abc2");
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
private static class MyFunc2 implements FreeRefFunction {
|
||||||
* Creates and registers user-defined function "MyFunc()" directly with POI.
|
public MyFunc2() {
|
||||||
* 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());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
|
||||||
* Creates example ToolPack which contains function "MyFunc2()".
|
if (args.length != 1 || !(args[0] instanceof StringEval)) {
|
||||||
*/
|
return ErrorEval.VALUE_INVALID;
|
||||||
private void createExampleToolPack() {
|
}
|
||||||
ToolPack exampleToolPack = new DefaultToolPack();
|
StringEval input = (StringEval) args[0];
|
||||||
exampleToolPack.addFunction("myFunc2", new MyFunc2());
|
return new StringEval(input.getStringValue() + "abc2");
|
||||||
MainToolPacksHandler.instance().addToolPack(exampleToolPack);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks that an external function can get invoked from the formula
|
* Checks that an external function can get invoked from the formula
|
||||||
* evaluator.
|
* evaluator.
|
||||||
*
|
*/
|
||||||
* @throws IOException
|
public void testInvoke() {
|
||||||
*
|
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("testNames.xls");
|
||||||
*/
|
HSSFSheet sheet = wb.getSheetAt(0);
|
||||||
public void testInvoke() {
|
|
||||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("testNames.xls");
|
|
||||||
HSSFSheet sheet = wb.getSheetAt(0);
|
|
||||||
|
|
||||||
registerMyFunc(wb);
|
/**
|
||||||
createExampleToolPack();
|
* 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("_")
|
HSSFRow row = sheet.getRow(0);
|
||||||
|
HSSFCell myFuncCell = row.getCell(1); // =myFunc("_")
|
||||||
|
|
||||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
HSSFCell myFunc2Cell = row.getCell(2); // =myFunc2("_")
|
||||||
try {
|
|
||||||
assertEquals("_abc", fe.evaluate(myFuncCell).getStringValue());
|
HSSFFormulaEvaluator fe = HSSFFormulaEvaluator.create(wb, null, udff);
|
||||||
assertEquals("_abc2", fe.evaluate(myFunc2Cell).getStringValue());
|
assertEquals("_abc", fe.evaluate(myFuncCell).getStringValue());
|
||||||
} catch (Exception e) {
|
assertEquals("_abc2", fe.evaluate(myFunc2Cell).getStringValue());
|
||||||
assertFalse(true);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ public class TestWorkbookEvaluator extends TestCase {
|
||||||
|
|
||||||
private static ValueEval evaluateFormula(Ptg[] ptgs) {
|
private static ValueEval evaluateFormula(Ptg[] ptgs) {
|
||||||
OperationEvaluationContext ec = new OperationEvaluationContext(null, null, 0, 0, 0, null);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -22,7 +22,7 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows tests to execute {@link WorkbookEvaluator}s and track the internal workings.
|
* Allows tests to execute {@link WorkbookEvaluator}s and track the internal workings.
|
||||||
*
|
*
|
||||||
* @author Josh Micich
|
* @author Josh Micich
|
||||||
*/
|
*/
|
||||||
public final class WorkbookEvaluatorTestHelper {
|
public final class WorkbookEvaluatorTestHelper {
|
||||||
|
@ -30,8 +30,8 @@ public final class WorkbookEvaluatorTestHelper {
|
||||||
private WorkbookEvaluatorTestHelper() {
|
private WorkbookEvaluatorTestHelper() {
|
||||||
// no instances of this class
|
// no instances of this class
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WorkbookEvaluator createEvaluator(HSSFWorkbook wb, EvaluationListener listener) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue