mirror of https://github.com/apache/poi.git
improved work with UDFs and Analysis Toolpack functions, ATP functions are enabled by default and user can create / evaluate them just like built-in functions, both HSSF andf XSSF are supported
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1039870 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
fa5be6e820
commit
db89d09ca3
|
@ -66,9 +66,7 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||||
}
|
}
|
||||||
|
|
||||||
public NameXPtg getNameXPtg(String name) {
|
public NameXPtg getNameXPtg(String name) {
|
||||||
// TODO YK: passing UDFFinder.DEFAULT is temporary,
|
return _iBook.getNameXPtg(name, _uBook.getUDFFinder());
|
||||||
// a proper design should take it from the parent HSSFWorkbook
|
|
||||||
return _iBook.getNameXPtg(name, UDFFinder.DEFAULT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -147,6 +145,9 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||||
FormulaRecordAggregate fra = (FormulaRecordAggregate) cell.getCellValueRecord();
|
FormulaRecordAggregate fra = (FormulaRecordAggregate) cell.getCellValueRecord();
|
||||||
return fra.getFormulaTokens();
|
return fra.getFormulaTokens();
|
||||||
}
|
}
|
||||||
|
public UDFFinder getUDFFinder(){
|
||||||
|
return _uBook.getUDFFinder();
|
||||||
|
}
|
||||||
|
|
||||||
private static final class Name implements EvaluationName {
|
private static final class Name implements EvaluationName {
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,8 @@ import org.apache.poi.ss.formula.ptg.UnionPtg;
|
||||||
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.formula.udf.AggregatingUDFFinder;
|
||||||
|
import org.apache.poi.ss.formula.udf.UDFFinder;
|
||||||
import org.apache.poi.ss.usermodel.CreationHelper;
|
import org.apache.poi.ss.usermodel.CreationHelper;
|
||||||
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;
|
||||||
|
@ -148,6 +150,12 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
|
||||||
|
|
||||||
private static POILogger log = POILogFactory.getLogger(HSSFWorkbook.class);
|
private static POILogger log = POILogFactory.getLogger(HSSFWorkbook.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The locator of user-defined functions.
|
||||||
|
* By default includes functions from the Excel Analysis Toolpack
|
||||||
|
*/
|
||||||
|
private UDFFinder _udfFinder = UDFFinder.DEFAULT;
|
||||||
|
|
||||||
public static HSSFWorkbook create(InternalWorkbook book) {
|
public static HSSFWorkbook create(InternalWorkbook book) {
|
||||||
return new HSSFWorkbook(book);
|
return new HSSFWorkbook(book);
|
||||||
}
|
}
|
||||||
|
@ -1672,11 +1680,33 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CreationHelper getCreationHelper() {
|
public HSSFCreationHelper getCreationHelper() {
|
||||||
return new HSSFCreationHelper(this);
|
return new HSSFCreationHelper(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] newUID() {
|
private static byte[] newUID() {
|
||||||
return new byte[16];
|
return new byte[16];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Returns the locator of user-defined functions.
|
||||||
|
* The default instance extends the built-in functions with the Analysis Tool Pack
|
||||||
|
*
|
||||||
|
* @return the locator of user-defined functions
|
||||||
|
*/
|
||||||
|
/*package*/ UDFFinder getUDFFinder(){
|
||||||
|
return _udfFinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new toolpack in this workbook.
|
||||||
|
*
|
||||||
|
* @param toopack the toolpack to register
|
||||||
|
*/
|
||||||
|
public void addToolPack(UDFFinder toopack){
|
||||||
|
AggregatingUDFFinder udfs = (AggregatingUDFFinder)_udfFinder;
|
||||||
|
udfs.add(toopack);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.apache.poi.ss.formula;
|
||||||
import org.apache.poi.ss.formula.ptg.NamePtg;
|
import org.apache.poi.ss.formula.ptg.NamePtg;
|
||||||
import org.apache.poi.ss.formula.ptg.NameXPtg;
|
import org.apache.poi.ss.formula.ptg.NameXPtg;
|
||||||
import org.apache.poi.ss.formula.ptg.Ptg;
|
import org.apache.poi.ss.formula.ptg.Ptg;
|
||||||
|
import org.apache.poi.ss.formula.udf.UDFFinder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstracts a workbook for the purpose of formula evaluation.<br/>
|
* Abstracts a workbook for the purpose of formula evaluation.<br/>
|
||||||
|
@ -49,8 +50,10 @@ public interface EvaluationWorkbook {
|
||||||
int convertFromExternSheetIndex(int externSheetIndex);
|
int convertFromExternSheetIndex(int externSheetIndex);
|
||||||
ExternalName getExternalName(int externSheetIndex, int externNameIndex);
|
ExternalName getExternalName(int externSheetIndex, int externNameIndex);
|
||||||
EvaluationName getName(NamePtg namePtg);
|
EvaluationName getName(NamePtg namePtg);
|
||||||
|
EvaluationName getName(String name, int sheetIndex);
|
||||||
String resolveNameXText(NameXPtg ptg);
|
String resolveNameXText(NameXPtg ptg);
|
||||||
Ptg[] getFormulaTokens(EvaluationCell cell);
|
Ptg[] getFormulaTokens(EvaluationCell cell);
|
||||||
|
UDFFinder getUDFFinder();
|
||||||
|
|
||||||
class ExternalSheet {
|
class ExternalSheet {
|
||||||
private final String _workbookName;
|
private final String _workbookName;
|
||||||
|
|
|
@ -61,8 +61,8 @@ import org.apache.poi.ss.formula.eval.ValueEval;
|
||||||
import org.apache.poi.ss.formula.functions.Choose;
|
import org.apache.poi.ss.formula.functions.Choose;
|
||||||
import org.apache.poi.ss.formula.functions.FreeRefFunction;
|
import org.apache.poi.ss.formula.functions.FreeRefFunction;
|
||||||
import org.apache.poi.ss.formula.functions.IfFunc;
|
import org.apache.poi.ss.formula.functions.IfFunc;
|
||||||
|
import org.apache.poi.ss.formula.udf.AggregatingUDFFinder;
|
||||||
import org.apache.poi.ss.formula.udf.UDFFinder;
|
import org.apache.poi.ss.formula.udf.UDFFinder;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
|
|
||||||
import org.apache.poi.ss.util.CellReference;
|
import org.apache.poi.ss.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;
|
||||||
|
@ -91,7 +91,7 @@ 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;
|
private final AggregatingUDFFinder _udfFinder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param udfFinder pass <code>null</code> for default (AnalysisToolPak only)
|
* @param udfFinder pass <code>null</code> for default (AnalysisToolPak only)
|
||||||
|
@ -109,7 +109,13 @@ public final class WorkbookEvaluator {
|
||||||
_collaboratingWorkbookEnvironment = CollaboratingWorkbooksEnvironment.EMPTY;
|
_collaboratingWorkbookEnvironment = CollaboratingWorkbooksEnvironment.EMPTY;
|
||||||
_workbookIx = 0;
|
_workbookIx = 0;
|
||||||
_stabilityClassifier = stabilityClassifier;
|
_stabilityClassifier = stabilityClassifier;
|
||||||
_udfFinder = udfFinder == null ? UDFFinder.DEFAULT : udfFinder;
|
|
||||||
|
AggregatingUDFFinder defaultToolkit = // workbook can be null in unit tests
|
||||||
|
workbook == null ? null : (AggregatingUDFFinder)workbook.getUDFFinder();
|
||||||
|
if(defaultToolkit != null && udfFinder != null) {
|
||||||
|
defaultToolkit.add(udfFinder);
|
||||||
|
}
|
||||||
|
_udfFinder = defaultToolkit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -124,10 +130,7 @@ public final class WorkbookEvaluator {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ EvaluationName getName(String name, int sheetIndex) {
|
/* package */ EvaluationName getName(String name, int sheetIndex) {
|
||||||
NamePtg namePtg = null;
|
NamePtg namePtg = _workbook.getName(name, sheetIndex).createPtg();
|
||||||
if(_workbook instanceof HSSFEvaluationWorkbook){
|
|
||||||
namePtg =((HSSFEvaluationWorkbook)_workbook).getName(name, sheetIndex).createPtg();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(namePtg == null) {
|
if(namePtg == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -32,133 +32,150 @@ import org.apache.poi.ss.formula.eval.NotImplementedException;
|
||||||
*/
|
*/
|
||||||
public final class AnalysisToolPak implements UDFFinder {
|
public final class AnalysisToolPak implements UDFFinder {
|
||||||
|
|
||||||
public static final UDFFinder instance = new AnalysisToolPak();
|
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;
|
||||||
|
|
||||||
public NotImplemented(String functionName) {
|
public NotImplemented(String functionName) {
|
||||||
_functionName = functionName;
|
_functionName = functionName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
|
public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
|
||||||
throw new NotImplementedException(_functionName);
|
throw new NotImplementedException(_functionName);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
private final Map<String, FreeRefFunction> _functionsByName = createFunctionsMap();
|
;
|
||||||
|
|
||||||
|
private final Map<String, FreeRefFunction> _functionsByName = createFunctionsMap();
|
||||||
|
|
||||||
|
|
||||||
private AnalysisToolPak() {
|
private AnalysisToolPak() {
|
||||||
// enforce singleton
|
// 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>(108);
|
||||||
|
|
||||||
r(m, "ACCRINT", null);
|
r(m, "ACCRINT", null);
|
||||||
r(m, "ACCRINTM", null);
|
r(m, "ACCRINTM", null);
|
||||||
r(m, "AMORDEGRC", null);
|
r(m, "AMORDEGRC", null);
|
||||||
r(m, "AMORLINC", null);
|
r(m, "AMORLINC", null);
|
||||||
r(m, "BESSELI", null);
|
r(m, "AVERAGEIF", null);
|
||||||
r(m, "BESSELJ", null);
|
r(m, "AVERAGEIFS", null);
|
||||||
r(m, "BESSELK", null);
|
r(m, "BAHTTEXT", null);
|
||||||
r(m, "BESSELY", null);
|
r(m, "BESSELI", null);
|
||||||
r(m, "BIN2DEC", null);
|
r(m, "BESSELJ", null);
|
||||||
r(m, "BIN2HEX", null);
|
r(m, "BESSELK", null);
|
||||||
r(m, "BIN2OCT", null);
|
r(m, "BESSELY", null);
|
||||||
r(m, "CO MPLEX", null);
|
r(m, "BIN2DEC", null);
|
||||||
r(m, "CONVERT", null);
|
r(m, "BIN2HEX", null);
|
||||||
r(m, "COUPDAYBS", null);
|
r(m, "BIN2OCT", null);
|
||||||
r(m, "COUPDAYS", null);
|
r(m, "COMPLEX", null);
|
||||||
r(m, "COUPDAYSNC", null);
|
r(m, "CONVERT", null);
|
||||||
r(m, "COUPNCD", null);
|
r(m, "COUNTIFS", null);
|
||||||
r(m, "COUPNUM", null);
|
r(m, "COUPDAYBS", null);
|
||||||
r(m, "COUPPCD", null);
|
r(m, "COUPDAYS", null);
|
||||||
r(m, "CUMIPMT", null);
|
r(m, "COUPDAYSNC", null);
|
||||||
r(m, "CUMPRINC", null);
|
r(m, "COUPNCD", null);
|
||||||
r(m, "DEC2BIN", null);
|
r(m, "COUPNUM", null);
|
||||||
r(m, "DEC2HEX", null);
|
r(m, "COUPPCD", null);
|
||||||
r(m, "DEC2OCT", null);
|
r(m, "CUBEKPIMEMBER", null);
|
||||||
r(m, "DELTA", null);
|
r(m, "CUBEMEMBER", null);
|
||||||
r(m, "DISC", null);
|
r(m, "CUBEMEMBERPROPERTY", null);
|
||||||
r(m, "DOLLARDE", null);
|
r(m, "CUBERANKEDMEMBER", null);
|
||||||
r(m, "DOLLARFR", null);
|
r(m, "CUBESET", null);
|
||||||
r(m, "DURATION", null);
|
r(m, "CUBESETCOUNT", null);
|
||||||
r(m, "EDATE", null);
|
r(m, "CUBEVALUE", null);
|
||||||
r(m, "EFFECT", null);
|
r(m, "CUMIPMT", null);
|
||||||
r(m, "EOMONTH", null);
|
r(m, "CUMPRINC", null);
|
||||||
r(m, "ERF", null);
|
r(m, "DEC2BIN", null);
|
||||||
r(m, "ERFC", null);
|
r(m, "DEC2HEX", null);
|
||||||
r(m, "FACTDOUBLE", null);
|
r(m, "DEC2OCT", null);
|
||||||
r(m, "FVSCHEDULE", null);
|
r(m, "DELTA", null);
|
||||||
r(m, "GCD", null);
|
r(m, "DISC", null);
|
||||||
r(m, "GESTEP", null);
|
r(m, "DOLLARDE", null);
|
||||||
r(m, "HEX2BIN", null);
|
r(m, "DOLLARFR", null);
|
||||||
r(m, "HEX2DEC", null);
|
r(m, "DURATION", null);
|
||||||
r(m, "HEX2OCT", null);
|
r(m, "EDATE", null);
|
||||||
r(m, "IMABS", null);
|
r(m, "EFFECT", null);
|
||||||
r(m, "IMAGINARY", null);
|
r(m, "EOMONTH", null);
|
||||||
r(m, "IMARGUMENT", null);
|
r(m, "ERF", null);
|
||||||
r(m, "IMCONJUGATE", null);
|
r(m, "ERFC", null);
|
||||||
r(m, "IMCOS", null);
|
r(m, "FACTDOUBLE", null);
|
||||||
r(m, "IMDIV", null);
|
r(m, "FVSCHEDULE", null);
|
||||||
r(m, "IMEXP", null);
|
r(m, "GCD", null);
|
||||||
r(m, "IMLN", null);
|
r(m, "GESTEP", null);
|
||||||
r(m, "IMLOG10", null);
|
r(m, "HEX2BIN", null);
|
||||||
r(m, "IMLOG2", null);
|
r(m, "HEX2DEC", null);
|
||||||
r(m, "IMPOWER", null);
|
r(m, "HEX2OCT", null);
|
||||||
r(m, "IMPRODUCT", null);
|
r(m, "IFERROR", null);
|
||||||
r(m, "IMREAL", null);
|
r(m, "IMABS", null);
|
||||||
r(m, "IMSIN", null);
|
r(m, "IMAGINARY", null);
|
||||||
r(m, "IMSQRT", null);
|
r(m, "IMARGUMENT", null);
|
||||||
r(m, "IMSUB", null);
|
r(m, "IMCONJUGATE", null);
|
||||||
r(m, "IMSUM", null);
|
r(m, "IMCOS", null);
|
||||||
r(m, "INTRATE", null);
|
r(m, "IMDIV", null);
|
||||||
r(m, "ISEVEN", ParityFunction.IS_EVEN);
|
r(m, "IMEXP", null);
|
||||||
r(m, "ISODD", ParityFunction.IS_ODD);
|
r(m, "IMLN", null);
|
||||||
r(m, "LCM", null);
|
r(m, "IMLOG10", null);
|
||||||
r(m, "MDURATION", null);
|
r(m, "IMLOG2", null);
|
||||||
r(m, "MROUND", null);
|
r(m, "IMPOWER", null);
|
||||||
r(m, "MULTINOMIAL", null);
|
r(m, "IMPRODUCT", null);
|
||||||
r(m, "NETWORKDAYS", null);
|
r(m, "IMREAL", null);
|
||||||
r(m, "NOMINAL", null);
|
r(m, "IMSIN", null);
|
||||||
r(m, "OCT2BIN", null);
|
r(m, "IMSQRT", null);
|
||||||
r(m, "OCT2DEC", null);
|
r(m, "IMSUB", null);
|
||||||
r(m, "OCT2HEX", null);
|
r(m, "IMSUM", null);
|
||||||
r(m, "ODDFPRICE", null);
|
r(m, "INTRATE", null);
|
||||||
r(m, "ODDFYIELD", null);
|
r(m, "ISEVEN", ParityFunction.IS_EVEN);
|
||||||
r(m, "ODDLPRICE", null);
|
r(m, "ISODD", ParityFunction.IS_ODD);
|
||||||
r(m, "ODDLYIELD", null);
|
r(m, "JIS", null);
|
||||||
r(m, "PRICE", null);
|
r(m, "LCM", null);
|
||||||
r(m, "PRICEDISC", null);
|
r(m, "MDURATION", null);
|
||||||
r(m, "PRICEMAT", null);
|
r(m, "MROUND", null);
|
||||||
r(m, "QUOTIENT", null);
|
r(m, "MULTINOMIAL", null);
|
||||||
r(m, "RANDBETWEEN", RandBetween.instance);
|
r(m, "NETWORKDAYS", null);
|
||||||
r(m, "RECEIVED", null);
|
r(m, "NOMINAL", null);
|
||||||
r(m, "SERIESSUM", null);
|
r(m, "OCT2BIN", null);
|
||||||
r(m, "SQRTPI", null);
|
r(m, "OCT2DEC", null);
|
||||||
r(m, "TBILLEQ", null);
|
r(m, "OCT2HEX", null);
|
||||||
r(m, "TBILLPRICE", null);
|
r(m, "ODDFPRICE", null);
|
||||||
r(m, "TBILLYIELD", null);
|
r(m, "ODDFYIELD", null);
|
||||||
r(m, "WEEKNUM", null);
|
r(m, "ODDLPRICE", null);
|
||||||
r(m, "WORKDAY", null);
|
r(m, "ODDLYIELD", null);
|
||||||
r(m, "XIRR", null);
|
r(m, "PRICE", null);
|
||||||
r(m, "XNPV", null);
|
r(m, "PRICEDISC", null);
|
||||||
r(m, "YEARFRAC", YearFrac.instance);
|
r(m, "PRICEMAT", null);
|
||||||
r(m, "YIELD", null);
|
r(m, "QUOTIENT", null);
|
||||||
r(m, "YIELDDISC", null);
|
r(m, "RANDBETWEEN", RandBetween.instance);
|
||||||
r(m, "YIELDMAT", null);
|
r(m, "RECEIVED", null);
|
||||||
|
r(m, "RTD", null);
|
||||||
|
r(m, "SERIESSUM", null);
|
||||||
|
r(m, "SQRTPI", null);
|
||||||
|
r(m, "SUMIFS", null);
|
||||||
|
r(m, "TBILLEQ", null);
|
||||||
|
r(m, "TBILLPRICE", null);
|
||||||
|
r(m, "TBILLYIELD", null);
|
||||||
|
r(m, "WEEKNUM", null);
|
||||||
|
r(m, "WORKDAY", null);
|
||||||
|
r(m, "XIRR", null);
|
||||||
|
r(m, "XNPV", null);
|
||||||
|
r(m, "YEARFRAC", YearFrac.instance);
|
||||||
|
r(m, "YIELD", null);
|
||||||
|
r(m, "YIELDDISC", null);
|
||||||
|
r(m, "YIELDMAT", null);
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void r(Map<String, FreeRefFunction> m, String functionName, FreeRefFunction pFunc) {
|
private static void r(Map<String, FreeRefFunction> m, String functionName, FreeRefFunction pFunc) {
|
||||||
FreeRefFunction func = pFunc == null ? new NotImplemented(functionName) : pFunc;
|
FreeRefFunction func = pFunc == null ? new NotImplemented(functionName) : pFunc;
|
||||||
m.put(functionName, func);
|
m.put(functionName, func);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.apache.poi.ss.formula.EvaluationCell;
|
||||||
import org.apache.poi.ss.formula.EvaluationName;
|
import org.apache.poi.ss.formula.EvaluationName;
|
||||||
import org.apache.poi.ss.formula.EvaluationSheet;
|
import org.apache.poi.ss.formula.EvaluationSheet;
|
||||||
import org.apache.poi.ss.formula.EvaluationWorkbook;
|
import org.apache.poi.ss.formula.EvaluationWorkbook;
|
||||||
|
import org.apache.poi.ss.formula.udf.UDFFinder;
|
||||||
import org.apache.poi.ss.usermodel.Workbook;
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -102,6 +103,10 @@ final class ForkedEvaluationWorkbook implements EvaluationWorkbook {
|
||||||
return _masterBook.getName(namePtg);
|
return _masterBook.getName(namePtg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EvaluationName getName(String name, int sheetIndex){
|
||||||
|
return _masterBook.getName(name, sheetIndex);
|
||||||
|
}
|
||||||
|
|
||||||
public EvaluationSheet getSheet(int sheetIndex) {
|
public EvaluationSheet getSheet(int sheetIndex) {
|
||||||
return getSharedSheet(getSheetName(sheetIndex));
|
return getSharedSheet(getSheetName(sheetIndex));
|
||||||
}
|
}
|
||||||
|
@ -130,6 +135,10 @@ final class ForkedEvaluationWorkbook implements EvaluationWorkbook {
|
||||||
return _masterBook.resolveNameXText(ptg);
|
return _masterBook.resolveNameXText(ptg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UDFFinder getUDFFinder(){
|
||||||
|
return _masterBook.getUDFFinder();
|
||||||
|
}
|
||||||
|
|
||||||
private static final class OrderedSheet implements Comparable<OrderedSheet> {
|
private static final class OrderedSheet implements Comparable<OrderedSheet> {
|
||||||
private final String _sheetName;
|
private final String _sheetName;
|
||||||
private final int _index;
|
private final int _index;
|
||||||
|
|
|
@ -41,7 +41,7 @@ public final class FunctionMetadataRegistry {
|
||||||
private final FunctionMetadata[] _functionDataByIndex;
|
private final FunctionMetadata[] _functionDataByIndex;
|
||||||
private final Map<String, FunctionMetadata> _functionDataByName;
|
private final Map<String, FunctionMetadata> _functionDataByName;
|
||||||
|
|
||||||
private static FunctionMetadataRegistry getInstance() {
|
public static FunctionMetadataRegistry getInstance() {
|
||||||
if (_instance == null) {
|
if (_instance == null) {
|
||||||
_instance = FunctionMetadataReader.createRegistry();
|
_instance = FunctionMetadataReader.createRegistry();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,17 +19,22 @@ package org.apache.poi.ss.formula.udf;
|
||||||
|
|
||||||
import org.apache.poi.ss.formula.functions.FreeRefFunction;
|
import org.apache.poi.ss.formula.functions.FreeRefFunction;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collects add-in libraries and VB macro functions together into one UDF finder
|
* Collects add-in libraries and VB macro functions together into one UDF finder
|
||||||
*
|
*
|
||||||
* @author PUdalau
|
* @author PUdalau
|
||||||
*/
|
*/
|
||||||
public final class AggregatingUDFFinder implements UDFFinder {
|
public class AggregatingUDFFinder implements UDFFinder {
|
||||||
|
|
||||||
private final UDFFinder[] _usedToolPacks;
|
private final Collection<UDFFinder> _usedToolPacks;
|
||||||
|
|
||||||
public AggregatingUDFFinder(UDFFinder ... usedToolPacks) {
|
public AggregatingUDFFinder(UDFFinder ... usedToolPacks) {
|
||||||
_usedToolPacks = usedToolPacks.clone();
|
_usedToolPacks = new ArrayList<UDFFinder>(usedToolPacks.length);
|
||||||
|
_usedToolPacks.addAll(Arrays.asList(usedToolPacks));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -49,4 +54,13 @@ public final class AggregatingUDFFinder implements UDFFinder {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new toolpack
|
||||||
|
*
|
||||||
|
* @param toolPack the UDF toolpack to add
|
||||||
|
*/
|
||||||
|
public void add(UDFFinder toolPack){
|
||||||
|
_usedToolPacks.add(toolPack);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,12 +38,12 @@ public final class DefaultUDFFinder implements UDFFinder {
|
||||||
}
|
}
|
||||||
HashMap<String, FreeRefFunction> m = new HashMap<String, FreeRefFunction>(nFuncs * 3 / 2);
|
HashMap<String, FreeRefFunction> m = new HashMap<String, FreeRefFunction>(nFuncs * 3 / 2);
|
||||||
for (int i = 0; i < functionImpls.length; i++) {
|
for (int i = 0; i < functionImpls.length; i++) {
|
||||||
m.put(functionNames[i], functionImpls[i]);
|
m.put(functionNames[i].toUpperCase(), functionImpls[i]);
|
||||||
}
|
}
|
||||||
_functionsByName = m;
|
_functionsByName = m;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FreeRefFunction findFunction(String name) {
|
public FreeRefFunction findFunction(String name) {
|
||||||
return _functionsByName.get(name);
|
return _functionsByName.get(name.toUpperCase());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.poi.ss.formula.udf.UDFFinder;
|
||||||
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
|
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -496,4 +497,12 @@ public interface Workbook {
|
||||||
* @throws IllegalArgumentException if the supplied sheet index or state is invalid
|
* @throws IllegalArgumentException if the supplied sheet index or state is invalid
|
||||||
*/
|
*/
|
||||||
void setSheetHidden(int sheetIx, int hidden);
|
void setSheetHidden(int sheetIx, int hidden);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new toolpack in this workbook.
|
||||||
|
*
|
||||||
|
* @param toopack the toolpack to register
|
||||||
|
*/
|
||||||
|
void addToolPack(UDFFinder toopack);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/* ====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
==================================================================== */
|
||||||
|
package org.apache.poi.xssf.model;
|
||||||
|
|
||||||
|
import org.apache.poi.ss.formula.functions.FreeRefFunction;
|
||||||
|
import org.apache.poi.ss.formula.udf.AggregatingUDFFinder;
|
||||||
|
import org.apache.poi.ss.formula.udf.UDFFinder;
|
||||||
|
import org.apache.poi.util.Internal;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A UDFFinder that can retrieve functions both by name and by fake index.
|
||||||
|
*
|
||||||
|
* @author Yegor Kozlov
|
||||||
|
*/
|
||||||
|
@Internal
|
||||||
|
public final class IndexedUDFFinder extends AggregatingUDFFinder {
|
||||||
|
private final HashMap<Integer, String> _funcMap;
|
||||||
|
|
||||||
|
public IndexedUDFFinder(UDFFinder... usedToolPacks) {
|
||||||
|
super(usedToolPacks);
|
||||||
|
_funcMap = new HashMap<Integer, String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public FreeRefFunction findFunction(String name) {
|
||||||
|
FreeRefFunction func = super.findFunction(name);
|
||||||
|
if (func != null) {
|
||||||
|
int idx = getFunctionIndex(name);
|
||||||
|
_funcMap.put(idx, name);
|
||||||
|
}
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFunctionName(int idx) {
|
||||||
|
return _funcMap.get(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFunctionIndex(String name) {
|
||||||
|
return name.hashCode();
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package org.apache.poi.xssf.usermodel;
|
package org.apache.poi.xssf.usermodel;
|
||||||
|
|
||||||
|
import org.apache.poi.ss.formula.functions.FreeRefFunction;
|
||||||
import org.apache.poi.ss.formula.ptg.NamePtg;
|
import org.apache.poi.ss.formula.ptg.NamePtg;
|
||||||
import org.apache.poi.ss.formula.ptg.NameXPtg;
|
import org.apache.poi.ss.formula.ptg.NameXPtg;
|
||||||
import org.apache.poi.ss.formula.ptg.Ptg;
|
import org.apache.poi.ss.formula.ptg.Ptg;
|
||||||
|
@ -29,8 +30,12 @@ import org.apache.poi.ss.formula.FormulaParser;
|
||||||
import org.apache.poi.ss.formula.FormulaParsingWorkbook;
|
import org.apache.poi.ss.formula.FormulaParsingWorkbook;
|
||||||
import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
|
import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
|
||||||
import org.apache.poi.ss.formula.FormulaType;
|
import org.apache.poi.ss.formula.FormulaType;
|
||||||
|
import org.apache.poi.ss.formula.udf.UDFFinder;
|
||||||
|
import org.apache.poi.xssf.model.IndexedUDFFinder;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal POI use only
|
* Internal POI use only
|
||||||
*
|
*
|
||||||
|
@ -100,10 +105,18 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||||
}
|
}
|
||||||
|
|
||||||
public NameXPtg getNameXPtg(String name) {
|
public NameXPtg getNameXPtg(String name) {
|
||||||
// may require to return null to make tests pass
|
IndexedUDFFinder udfFinder = (IndexedUDFFinder)getUDFFinder();
|
||||||
throw new RuntimeException("Not implemented yet");
|
FreeRefFunction func = udfFinder.findFunction(name);
|
||||||
|
if(func == null) return null;
|
||||||
|
else return new NameXPtg(0, udfFinder.getFunctionIndex(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String resolveNameXText(NameXPtg n) {
|
||||||
|
int idx = n.getNameIndex();
|
||||||
|
IndexedUDFFinder udfFinder = (IndexedUDFFinder)getUDFFinder();
|
||||||
|
return udfFinder.getFunctionName(idx);
|
||||||
|
}
|
||||||
|
|
||||||
public EvaluationSheet getSheet(int sheetIndex) {
|
public EvaluationSheet getSheet(int sheetIndex) {
|
||||||
return new XSSFEvaluationSheet(_uBook.getSheetAt(sheetIndex));
|
return new XSSFEvaluationSheet(_uBook.getSheetAt(sheetIndex));
|
||||||
}
|
}
|
||||||
|
@ -119,14 +132,6 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||||
return _uBook.getSheetIndex(sheetName);
|
return _uBook.getSheetIndex(sheetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO - figure out what the hell this methods does in
|
|
||||||
* HSSF...
|
|
||||||
*/
|
|
||||||
public String resolveNameXText(NameXPtg n) {
|
|
||||||
throw new RuntimeException("method not implemented yet");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSheetNameByExternSheet(int externSheetIndex) {
|
public String getSheetNameByExternSheet(int externSheetIndex) {
|
||||||
int sheetIndex = convertFromExternalSheetIndex(externSheetIndex);
|
int sheetIndex = convertFromExternalSheetIndex(externSheetIndex);
|
||||||
return _uBook.getSheetName(sheetIndex);
|
return _uBook.getSheetName(sheetIndex);
|
||||||
|
@ -145,6 +150,10 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||||
return FormulaParser.parse(cell.getCellFormula(), frBook, FormulaType.CELL, _uBook.getSheetIndex(cell.getSheet()));
|
return FormulaParser.parse(cell.getCellFormula(), frBook, FormulaType.CELL, _uBook.getSheetIndex(cell.getSheet()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UDFFinder getUDFFinder(){
|
||||||
|
return _uBook.getUDFFinder();
|
||||||
|
}
|
||||||
|
|
||||||
private static final class Name implements EvaluationName {
|
private static final class Name implements EvaluationName {
|
||||||
|
|
||||||
private final XSSFName _nameRecord;
|
private final XSSFName _nameRecord;
|
||||||
|
|
|
@ -46,6 +46,8 @@ 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.formula.udf.AggregatingUDFFinder;
|
||||||
|
import org.apache.poi.ss.formula.udf.UDFFinder;
|
||||||
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;
|
||||||
|
@ -53,11 +55,7 @@ import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
|
||||||
import org.apache.poi.ss.util.CellReference;
|
import org.apache.poi.ss.util.CellReference;
|
||||||
import org.apache.poi.ss.util.WorkbookUtil;
|
import org.apache.poi.ss.util.WorkbookUtil;
|
||||||
import org.apache.poi.util.*;
|
import org.apache.poi.util.*;
|
||||||
import org.apache.poi.xssf.model.CalculationChain;
|
import org.apache.poi.xssf.model.*;
|
||||||
import org.apache.poi.xssf.model.MapInfo;
|
|
||||||
import org.apache.poi.xssf.model.SharedStringsTable;
|
|
||||||
import org.apache.poi.xssf.model.StylesTable;
|
|
||||||
import org.apache.poi.xssf.model.ThemesTable;
|
|
||||||
import org.apache.xmlbeans.XmlException;
|
import org.apache.xmlbeans.XmlException;
|
||||||
import org.apache.xmlbeans.XmlObject;
|
import org.apache.xmlbeans.XmlObject;
|
||||||
import org.apache.xmlbeans.XmlOptions;
|
import org.apache.xmlbeans.XmlOptions;
|
||||||
|
@ -123,6 +121,12 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
|
||||||
|
|
||||||
private ThemesTable theme;
|
private ThemesTable theme;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The locator of user-defined functions.
|
||||||
|
* By default includes functions from the Excel Analysis Toolpack
|
||||||
|
*/
|
||||||
|
private IndexedUDFFinder _udfFinder = new IndexedUDFFinder(UDFFinder.DEFAULT);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* TODO
|
||||||
*/
|
*/
|
||||||
|
@ -1492,4 +1496,31 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
|
||||||
workbook.setWorkbookProtection(CTWorkbookProtection.Factory.newInstance());
|
workbook.setWorkbookProtection(CTWorkbookProtection.Factory.newInstance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Returns the locator of user-defined functions.
|
||||||
|
* <p>
|
||||||
|
* The default instance extends the built-in functions with the Excel Analysis Tool Pack.
|
||||||
|
* To set / evaluate custom functions you need to register them as follows:
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* </p>
|
||||||
|
* @return wrapped instance of UDFFinder that allows seeking functions both by index and name
|
||||||
|
*/
|
||||||
|
/*package*/ UDFFinder getUDFFinder() {
|
||||||
|
return _udfFinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new toolpack in this workbook.
|
||||||
|
*
|
||||||
|
* @param toopack the toolpack to register
|
||||||
|
*/
|
||||||
|
public void addToolPack(UDFFinder toopack){
|
||||||
|
_udfFinder.add(toopack);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/* ====================================================================
|
||||||
|
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.xssf.usermodel;
|
||||||
|
|
||||||
|
import org.apache.poi.ss.formula.BaseTestExternalFunctions;
|
||||||
|
import org.apache.poi.xssf.XSSFITestDataProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests setting and evaluating user-defined functions in HSSF
|
||||||
|
*/
|
||||||
|
public final class TestXSSFExternalFunctions extends BaseTestExternalFunctions {
|
||||||
|
|
||||||
|
public TestXSSFExternalFunctions() {
|
||||||
|
super(XSSFITestDataProvider.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testATP(){
|
||||||
|
baseTestInvokeATP("atp.xlsx");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/* ====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
==================================================================== */
|
||||||
|
|
||||||
|
package org.apache.poi.hssf.usermodel;
|
||||||
|
|
||||||
|
import org.apache.poi.hssf.HSSFITestDataProvider;
|
||||||
|
import org.apache.poi.ss.formula.BaseTestExternalFunctions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests setting and evaluating user-defined functions in HSSF
|
||||||
|
*/
|
||||||
|
public final class TestHSSFExternalFunctions extends BaseTestExternalFunctions {
|
||||||
|
|
||||||
|
public TestHSSFExternalFunctions() {
|
||||||
|
super(HSSFITestDataProvider.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testATP(){
|
||||||
|
baseTestInvokeATP("atp.xls");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,144 @@
|
||||||
|
/* ====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
==================================================================== */
|
||||||
|
package org.apache.poi.ss.formula;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import org.apache.poi.ss.ITestDataProvider;
|
||||||
|
import org.apache.poi.ss.formula.eval.ErrorEval;
|
||||||
|
import org.apache.poi.ss.formula.eval.StringEval;
|
||||||
|
import org.apache.poi.ss.formula.eval.ValueEval;
|
||||||
|
import org.apache.poi.ss.formula.functions.FreeRefFunction;
|
||||||
|
import org.apache.poi.ss.formula.udf.DefaultUDFFinder;
|
||||||
|
import org.apache.poi.ss.formula.udf.UDFFinder;
|
||||||
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
|
import org.apache.poi.ss.usermodel.FormulaEvaluator;
|
||||||
|
import org.apache.poi.ss.usermodel.Sheet;
|
||||||
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test setting / evaluating of Analysis Toolpack and user-defined functions
|
||||||
|
*
|
||||||
|
* @author Yegor Kozlov
|
||||||
|
*/
|
||||||
|
public class BaseTestExternalFunctions extends TestCase {
|
||||||
|
// define two custom user-defined functions
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* register the two test UDFs in a UDF finder, to be passed to the workbook
|
||||||
|
*/
|
||||||
|
private static UDFFinder customToolpack = new DefaultUDFFinder(
|
||||||
|
new String[] { "myFunc", "myFunc2"},
|
||||||
|
new FreeRefFunction[] { new MyFunc(), new MyFunc2()}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
protected final ITestDataProvider _testDataProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param testDataProvider an object that provides test data in HSSF / XSSF specific way
|
||||||
|
*/
|
||||||
|
protected BaseTestExternalFunctions(ITestDataProvider testDataProvider) {
|
||||||
|
_testDataProvider = testDataProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testExternalFunctions() {
|
||||||
|
Workbook wb = _testDataProvider.createWorkbook();
|
||||||
|
|
||||||
|
Sheet sh = wb.createSheet();
|
||||||
|
|
||||||
|
Cell cell1 = sh.createRow(0).createCell(0);
|
||||||
|
cell1.setCellFormula("ISODD(1)+ISEVEN(2)"); // functions from the Excel Analysis Toolpack
|
||||||
|
assertEquals("ISODD(1)+ISEVEN(2)", cell1.getCellFormula());
|
||||||
|
|
||||||
|
Cell cell2 = sh.createRow(1).createCell(0);
|
||||||
|
try {
|
||||||
|
cell2.setCellFormula("MYFUNC(\"B1\")");
|
||||||
|
fail("Should fail because MYFUNC is an unknown function");
|
||||||
|
} catch (FormulaParseException e){
|
||||||
|
; //expected
|
||||||
|
}
|
||||||
|
|
||||||
|
wb.addToolPack(customToolpack);
|
||||||
|
|
||||||
|
cell2.setCellFormula("MYFUNC(\"B1\")");
|
||||||
|
assertEquals("MYFUNC(\"B1\")", cell2.getCellFormula());
|
||||||
|
|
||||||
|
Cell cell3 = sh.createRow(2).createCell(0);
|
||||||
|
cell3.setCellFormula("MYFUNC2(\"C1\")&\"-\"&A2"); //where A2 is defined above
|
||||||
|
assertEquals("MYFUNC2(\"C1\")&\"-\"&A2", cell3.getCellFormula());
|
||||||
|
|
||||||
|
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
|
||||||
|
assertEquals(2.0, evaluator.evaluate(cell1).getNumberValue());
|
||||||
|
assertEquals("B1abc", evaluator.evaluate(cell2).getStringValue());
|
||||||
|
assertEquals("C1abc2-B1abc", evaluator.evaluate(cell3).getStringValue());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test invoking saved ATP functions
|
||||||
|
*
|
||||||
|
* @param testFile either atp.xls or atp.xlsx
|
||||||
|
*/
|
||||||
|
public void baseTestInvokeATP(String testFile){
|
||||||
|
Workbook wb = _testDataProvider.openSampleWorkbook(testFile);
|
||||||
|
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
|
||||||
|
|
||||||
|
Sheet sh = wb.getSheetAt(0);
|
||||||
|
// these two are not imlemented in r
|
||||||
|
assertEquals("DELTA(1.3,1.5)", sh.getRow(0).getCell(1).getCellFormula());
|
||||||
|
assertEquals("COMPLEX(2,4)", sh.getRow(1).getCell(1).getCellFormula());
|
||||||
|
|
||||||
|
Cell cell2 = sh.getRow(2).getCell(1);
|
||||||
|
assertEquals("ISODD(2)", cell2.getCellFormula());
|
||||||
|
assertEquals(false, evaluator.evaluate(cell2).getBooleanValue());
|
||||||
|
assertEquals(Cell.CELL_TYPE_BOOLEAN, evaluator.evaluateFormulaCell(cell2));
|
||||||
|
|
||||||
|
Cell cell3 = sh.getRow(3).getCell(1);
|
||||||
|
assertEquals("ISEVEN(2)", cell3.getCellFormula());
|
||||||
|
assertEquals(true, evaluator.evaluate(cell3).getBooleanValue());
|
||||||
|
assertEquals(Cell.CELL_TYPE_BOOLEAN, evaluator.evaluateFormulaCell(cell3));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue