patch 44675 - made POI capable of recognising var-args functions. Some related fixes.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@641185 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2008-03-26 07:32:28 +00:00
parent 844d1de676
commit 579cf03070
20 changed files with 1832 additions and 787 deletions

View File

@ -67,7 +67,7 @@ under the License.
<property name="forrest.home" value="${env.FORREST_HOME}"/>
<!-- Main: -->
<property name="main.resource1.dir" value="src/resources/fontmetrics"/>
<property name="main.resource1.dir" value="src/resources/main"/>
<property name="main.src" location="src/java"/>
<property name="main.src.test" location="src/testcases"/>
<property name="main.documentation" value="src/documentation"/>

View File

@ -25,6 +25,8 @@ import java.util.regex.Pattern;
//import PTG's .. since we need everything, import *
import org.apache.poi.hssf.record.formula.*;
import org.apache.poi.hssf.record.formula.function.FunctionMetadata;
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
@ -369,7 +371,23 @@ public final class FormulaParser {
*/
private AbstractFunctionPtg getFunction(String name, int numArgs, List argumentPointers) {
AbstractFunctionPtg retval = new FuncVarPtg(name, (byte)numArgs);
boolean isVarArgs;
int funcIx;
FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByName(name.toUpperCase());
if(fm == null) {
// must be external function
isVarArgs = true;
funcIx = FunctionMetadataRegistry.FUNCTION_INDEX_EXTERNAL;
} else {
isVarArgs = !fm.hasFixedArgsLength();
funcIx = fm.getIndex();
}
AbstractFunctionPtg retval;
if(isVarArgs) {
retval = new FuncVarPtg(name, (byte)numArgs);
} else {
retval = new FuncPtg(funcIx, (byte)numArgs);
}
if (!name.equals(AbstractFunctionPtg.FUNCTION_NAME_IF)) {
// early return for everything else besides IF()
return retval;
@ -969,6 +987,10 @@ end;
// tAttrSpace comes *before* the operand it applies to, which may be consistent
// with how the formula text appears but is against the RPN ordering assumed here
}
if (attrPtg.isSemiVolatile()) {
// similar to tAttrSpace - RPN is violated
continue;
}
}
final OperationPtg o = (OperationPtg) ptg;
@ -979,7 +1001,7 @@ end;
if(stack.isEmpty()) {
String msg = "Too few arguments suppled to operation token ("
+ o.getClass().getName() + "). Expected (" + nOperands
+ ") operands but got (" + (nOperands - j + 1) + ")";
+ ") operands but got (" + (nOperands - j - 1) + ")";
throw new IllegalStateException(msg);
}
operands[j] = (String) stack.pop();

View File

@ -17,8 +17,9 @@
package org.apache.poi.hssf.record.formula;
import org.apache.poi.util.BinaryTree;
import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.formula.function.FunctionMetadata;
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
/**
@ -29,7 +30,7 @@ import org.apache.poi.hssf.model.Workbook;
* @author Andrew C. Oliver (acoliver at apache dot org)
*/
public abstract class AbstractFunctionPtg extends OperationPtg {
/**
* The name of the IF function (i.e. "IF"). Extracted as a constant for clarity.
*/
@ -37,8 +38,6 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
/** All external functions have function index 255 */
private static final short FUNCTION_INDEX_EXTERNAL = 255;
private static BinaryTree map = produceHash();
protected static Object[][] functionData = produceFunctionData();
protected byte returnClass;
protected byte[] paramClass;
@ -46,14 +45,11 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
protected short field_2_fnc_index;
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer
.append("<FunctionPtg>").append("\n")
.append(" field_1_num_args=").append(field_1_num_args).append("\n")
.append(" name =").append(lookupName(field_2_fnc_index)).append("\n")
.append(" field_2_fnc_index=").append(field_2_fnc_index).append("\n")
.append("</FunctionPtg>");
return buffer.toString();
StringBuffer sb = new StringBuffer(64);
sb.append(getClass().getName()).append(" [");
sb.append(field_2_fnc_index).append(" ").append(field_1_num_args);
sb.append("]");
return sb.toString();
}
public int getType() {
@ -117,11 +113,19 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
* <code>false</code> if the name should be assumed to be an external function.
*/
public static final boolean isInternalFunctionName(String name) {
return map.containsValue(name.toUpperCase());
short ix = FunctionMetadataRegistry.lookupIndexByName(name.toUpperCase());
return ix >= 0;
}
protected String lookupName(short index) {
return ((String)map.get(new Integer(index)));
if(index == FunctionMetadataRegistry.FUNCTION_INDEX_EXTERNAL) {
return "#external#";
}
FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByIndex(index);
if(fm == null) {
throw new RuntimeException("bad function index (" + index + ")");
}
return fm.getName();
}
/**
@ -131,729 +135,11 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
* @return the standard worksheet function index if found, otherwise <tt>FUNCTION_INDEX_EXTERNAL</tt>
*/
protected static short lookupIndex(String name) {
Integer index = (Integer) map.getKeyForValue(name.toUpperCase());
if (index != null) return index.shortValue();
return FUNCTION_INDEX_EXTERNAL;
}
/**
* Produces the function table hashmap
*/
private static BinaryTree produceHash() {
BinaryTree dmap = new BinaryTree();
dmap.put(new Integer(0),"COUNT");
dmap.put(new Integer(1),FUNCTION_NAME_IF);
dmap.put(new Integer(2),"ISNA");
dmap.put(new Integer(3),"ISERROR");
dmap.put(new Integer(4),"SUM");
dmap.put(new Integer(5),"AVERAGE");
dmap.put(new Integer(6),"MIN");
dmap.put(new Integer(7),"MAX");
dmap.put(new Integer(8),"ROW");
dmap.put(new Integer(9),"COLUMN");
dmap.put(new Integer(10),"NA");
dmap.put(new Integer(11),"NPV");
dmap.put(new Integer(12),"STDEV");
dmap.put(new Integer(13),"DOLLAR");
dmap.put(new Integer(14),"FIXED");
dmap.put(new Integer(15),"SIN");
dmap.put(new Integer(16),"COS");
dmap.put(new Integer(17),"TAN");
dmap.put(new Integer(18),"ATAN");
dmap.put(new Integer(19),"PI");
dmap.put(new Integer(20),"SQRT");
dmap.put(new Integer(21),"EXP");
dmap.put(new Integer(22),"LN");
dmap.put(new Integer(23),"LOG10");
dmap.put(new Integer(24),"ABS");
dmap.put(new Integer(25),"INT");
dmap.put(new Integer(26),"SIGN");
dmap.put(new Integer(27),"ROUND");
dmap.put(new Integer(28),"LOOKUP");
dmap.put(new Integer(29),"INDEX");
dmap.put(new Integer(30),"REPT");
dmap.put(new Integer(31),"MID");
dmap.put(new Integer(32),"LEN");
dmap.put(new Integer(33),"VALUE");
dmap.put(new Integer(34),"TRUE");
dmap.put(new Integer(35),"FALSE");
dmap.put(new Integer(36),"AND");
dmap.put(new Integer(37),"OR");
dmap.put(new Integer(38),"NOT");
dmap.put(new Integer(39),"MOD");
dmap.put(new Integer(40),"DCOUNT");
dmap.put(new Integer(41),"DSUM");
dmap.put(new Integer(42),"DAVERAGE");
dmap.put(new Integer(43),"DMIN");
dmap.put(new Integer(44),"DMAX");
dmap.put(new Integer(45),"DSTDEV");
dmap.put(new Integer(46),"VAR");
dmap.put(new Integer(47),"DVAR");
dmap.put(new Integer(48),"TEXT");
dmap.put(new Integer(49),"LINEST");
dmap.put(new Integer(50),"TREND");
dmap.put(new Integer(51),"LOGEST");
dmap.put(new Integer(52),"GROWTH");
dmap.put(new Integer(53),"GOTO");
dmap.put(new Integer(54),"HALT");
dmap.put(new Integer(56),"PV");
dmap.put(new Integer(57),"FV");
dmap.put(new Integer(58),"NPER");
dmap.put(new Integer(59),"PMT");
dmap.put(new Integer(60),"RATE");
dmap.put(new Integer(61),"MIRR");
dmap.put(new Integer(62),"IRR");
dmap.put(new Integer(63),"RAND");
dmap.put(new Integer(64),"MATCH");
dmap.put(new Integer(65),"DATE");
dmap.put(new Integer(66),"TIME");
dmap.put(new Integer(67),"DAY");
dmap.put(new Integer(68),"MONTH");
dmap.put(new Integer(69),"YEAR");
dmap.put(new Integer(70),"WEEKDAY");
dmap.put(new Integer(71),"HOUR");
dmap.put(new Integer(72),"MINUTE");
dmap.put(new Integer(73),"SECOND");
dmap.put(new Integer(74),"NOW");
dmap.put(new Integer(75),"AREAS");
dmap.put(new Integer(76),"ROWS");
dmap.put(new Integer(77),"COLUMNS");
dmap.put(new Integer(78),"OFFSET");
dmap.put(new Integer(79),"ABSREF");
dmap.put(new Integer(80),"RELREF");
dmap.put(new Integer(81),"ARGUMENT");
dmap.put(new Integer(82),"SEARCH");
dmap.put(new Integer(83),"TRANSPOSE");
dmap.put(new Integer(84),"ERROR");
dmap.put(new Integer(85),"STEP");
dmap.put(new Integer(86),"TYPE");
dmap.put(new Integer(87),"ECHO");
dmap.put(new Integer(88),"SETNAME");
dmap.put(new Integer(89),"CALLER");
dmap.put(new Integer(90),"DEREF");
dmap.put(new Integer(91),"WINDOWS");
dmap.put(new Integer(92),"SERIES");
dmap.put(new Integer(93),"DOCUMENTS");
dmap.put(new Integer(94),"ACTIVECELL");
dmap.put(new Integer(95),"SELECTION");
dmap.put(new Integer(96),"RESULT");
dmap.put(new Integer(97),"ATAN2");
dmap.put(new Integer(98),"ASIN");
dmap.put(new Integer(99),"ACOS");
dmap.put(new Integer(100),"CHOOSE");
dmap.put(new Integer(101),"HLOOKUP");
dmap.put(new Integer(102),"VLOOKUP");
dmap.put(new Integer(103),"LINKS");
dmap.put(new Integer(104),"INPUT");
dmap.put(new Integer(105),"ISREF");
dmap.put(new Integer(106),"GETFORMULA");
dmap.put(new Integer(107),"GETNAME");
dmap.put(new Integer(108),"SETVALUE");
dmap.put(new Integer(109),"LOG");
dmap.put(new Integer(110),"EXEC");
dmap.put(new Integer(111),"CHAR");
dmap.put(new Integer(112),"LOWER");
dmap.put(new Integer(113),"UPPER");
dmap.put(new Integer(114),"PROPER");
dmap.put(new Integer(115),"LEFT");
dmap.put(new Integer(116),"RIGHT");
dmap.put(new Integer(117),"EXACT");
dmap.put(new Integer(118),"TRIM");
dmap.put(new Integer(119),"REPLACE");
dmap.put(new Integer(120),"SUBSTITUTE");
dmap.put(new Integer(121),"CODE");
dmap.put(new Integer(122),"NAMES");
dmap.put(new Integer(123),"DIRECTORY");
dmap.put(new Integer(124),"FIND");
dmap.put(new Integer(125),"CELL");
dmap.put(new Integer(126),"ISERR");
dmap.put(new Integer(127),"ISTEXT");
dmap.put(new Integer(128),"ISNUMBER");
dmap.put(new Integer(129),"ISBLANK");
dmap.put(new Integer(130),"T");
dmap.put(new Integer(131),"N");
dmap.put(new Integer(132),"FOPEN");
dmap.put(new Integer(133),"FCLOSE");
dmap.put(new Integer(134),"FSIZE");
dmap.put(new Integer(135),"FREADLN");
dmap.put(new Integer(136),"FREAD");
dmap.put(new Integer(137),"FWRITELN");
dmap.put(new Integer(138),"FWRITE");
dmap.put(new Integer(139),"FPOS");
dmap.put(new Integer(140),"DATEVALUE");
dmap.put(new Integer(141),"TIMEVALUE");
dmap.put(new Integer(142),"SLN");
dmap.put(new Integer(143),"SYD");
dmap.put(new Integer(144),"DDB");
dmap.put(new Integer(145),"GETDEF");
dmap.put(new Integer(146),"REFTEXT");
dmap.put(new Integer(147),"TEXTREF");
dmap.put(new Integer(148),"INDIRECT");
dmap.put(new Integer(149),"REGISTER");
dmap.put(new Integer(150),"CALL");
dmap.put(new Integer(151),"ADDBAR");
dmap.put(new Integer(152),"ADDMENU");
dmap.put(new Integer(153),"ADDCOMMAND");
dmap.put(new Integer(154),"ENABLECOMMAND");
dmap.put(new Integer(155),"CHECKCOMMAND");
dmap.put(new Integer(156),"RENAMECOMMAND");
dmap.put(new Integer(157),"SHOWBAR");
dmap.put(new Integer(158),"DELETEMENU");
dmap.put(new Integer(159),"DELETECOMMAND");
dmap.put(new Integer(160),"GETCHARTITEM");
dmap.put(new Integer(161),"DIALOGBOX");
dmap.put(new Integer(162),"CLEAN");
dmap.put(new Integer(163),"MDETERM");
dmap.put(new Integer(164),"MINVERSE");
dmap.put(new Integer(165),"MMULT");
dmap.put(new Integer(166),"FILES");
dmap.put(new Integer(167),"IPMT");
dmap.put(new Integer(168),"PPMT");
dmap.put(new Integer(169),"COUNTA");
dmap.put(new Integer(170),"CANCELKEY");
dmap.put(new Integer(175),"INITIATE");
dmap.put(new Integer(176),"REQUEST");
dmap.put(new Integer(177),"POKE");
dmap.put(new Integer(178),"EXECUTE");
dmap.put(new Integer(179),"TERMINATE");
dmap.put(new Integer(180),"RESTART");
dmap.put(new Integer(181),"HELP");
dmap.put(new Integer(182),"GETBAR");
dmap.put(new Integer(183),"PRODUCT");
dmap.put(new Integer(184),"FACT");
dmap.put(new Integer(185),"GETCELL");
dmap.put(new Integer(186),"GETWORKSPACE");
dmap.put(new Integer(187),"GETWINDOW");
dmap.put(new Integer(188),"GETDOCUMENT");
dmap.put(new Integer(189),"DPRODUCT");
dmap.put(new Integer(190),"ISNONTEXT");
dmap.put(new Integer(191),"GETNOTE");
dmap.put(new Integer(192),"NOTE");
dmap.put(new Integer(193),"STDEVP");
dmap.put(new Integer(194),"VARP");
dmap.put(new Integer(195),"DSTDEVP");
dmap.put(new Integer(196),"DVARP");
dmap.put(new Integer(197),"TRUNC");
dmap.put(new Integer(198),"ISLOGICAL");
dmap.put(new Integer(199),"DCOUNTA");
dmap.put(new Integer(200),"DELETEBAR");
dmap.put(new Integer(201),"UNREGISTER");
dmap.put(new Integer(204),"USDOLLAR");
dmap.put(new Integer(205),"FINDB");
dmap.put(new Integer(206),"SEARCHB");
dmap.put(new Integer(207),"REPLACEB");
dmap.put(new Integer(208),"LEFTB");
dmap.put(new Integer(209),"RIGHTB");
dmap.put(new Integer(210),"MIDB");
dmap.put(new Integer(211),"LENB");
dmap.put(new Integer(212),"ROUNDUP");
dmap.put(new Integer(213),"ROUNDDOWN");
dmap.put(new Integer(214),"ASC");
dmap.put(new Integer(215),"DBCS");
dmap.put(new Integer(216),"RANK");
dmap.put(new Integer(219),"ADDRESS");
dmap.put(new Integer(220),"DAYS360");
dmap.put(new Integer(221),"TODAY");
dmap.put(new Integer(222),"VDB");
dmap.put(new Integer(227),"MEDIAN");
dmap.put(new Integer(228),"SUMPRODUCT");
dmap.put(new Integer(229),"SINH");
dmap.put(new Integer(230),"COSH");
dmap.put(new Integer(231),"TANH");
dmap.put(new Integer(232),"ASINH");
dmap.put(new Integer(233),"ACOSH");
dmap.put(new Integer(234),"ATANH");
dmap.put(new Integer(235),"DGET");
dmap.put(new Integer(236),"CREATEOBJECT");
dmap.put(new Integer(237),"VOLATILE");
dmap.put(new Integer(238),"LASTERROR");
dmap.put(new Integer(239),"CUSTOMUNDO");
dmap.put(new Integer(240),"CUSTOMREPEAT");
dmap.put(new Integer(241),"FORMULACONVERT");
dmap.put(new Integer(242),"GETLINKINFO");
dmap.put(new Integer(243),"TEXTBOX");
dmap.put(new Integer(244),"INFO");
dmap.put(new Integer(245),"GROUP");
dmap.put(new Integer(246),"GETOBJECT");
dmap.put(new Integer(247),"DB");
dmap.put(new Integer(248),"PAUSE");
dmap.put(new Integer(250),"RESUME");
dmap.put(new Integer(252),"FREQUENCY");
dmap.put(new Integer(253),"ADDTOOLBAR");
dmap.put(new Integer(254),"DELETETOOLBAR");
dmap.put(new Integer(FUNCTION_INDEX_EXTERNAL),"externalflag");
dmap.put(new Integer(256),"RESETTOOLBAR");
dmap.put(new Integer(257),"EVALUATE");
dmap.put(new Integer(258),"GETTOOLBAR");
dmap.put(new Integer(259),"GETTOOL");
dmap.put(new Integer(260),"SPELLINGCHECK");
dmap.put(new Integer(261),"ERROR.TYPE");
dmap.put(new Integer(262),"APPTITLE");
dmap.put(new Integer(263),"WINDOWTITLE");
dmap.put(new Integer(264),"SAVETOOLBAR");
dmap.put(new Integer(265),"ENABLETOOL");
dmap.put(new Integer(266),"PRESSTOOL");
dmap.put(new Integer(267),"REGISTERID");
dmap.put(new Integer(268),"GETWORKBOOK");
dmap.put(new Integer(269),"AVEDEV");
dmap.put(new Integer(270),"BETADIST");
dmap.put(new Integer(271),"GAMMALN");
dmap.put(new Integer(272),"BETAINV");
dmap.put(new Integer(273),"BINOMDIST");
dmap.put(new Integer(274),"CHIDIST");
dmap.put(new Integer(275),"CHIINV");
dmap.put(new Integer(276),"COMBIN");
dmap.put(new Integer(277),"CONFIDENCE");
dmap.put(new Integer(278),"CRITBINOM");
dmap.put(new Integer(279),"EVEN");
dmap.put(new Integer(280),"EXPONDIST");
dmap.put(new Integer(281),"FDIST");
dmap.put(new Integer(282),"FINV");
dmap.put(new Integer(283),"FISHER");
dmap.put(new Integer(284),"FISHERINV");
dmap.put(new Integer(285),"FLOOR");
dmap.put(new Integer(286),"GAMMADIST");
dmap.put(new Integer(287),"GAMMAINV");
dmap.put(new Integer(288),"CEILING");
dmap.put(new Integer(289),"HYPGEOMDIST");
dmap.put(new Integer(290),"LOGNORMDIST");
dmap.put(new Integer(291),"LOGINV");
dmap.put(new Integer(292),"NEGBINOMDIST");
dmap.put(new Integer(293),"NORMDIST");
dmap.put(new Integer(294),"NORMSDIST");
dmap.put(new Integer(295),"NORMINV");
dmap.put(new Integer(296),"NORMSINV");
dmap.put(new Integer(297),"STANDARDIZE");
dmap.put(new Integer(298),"ODD");
dmap.put(new Integer(299),"PERMUT");
dmap.put(new Integer(300),"POISSON");
dmap.put(new Integer(301),"TDIST");
dmap.put(new Integer(302),"WEIBULL");
dmap.put(new Integer(303),"SUMXMY2");
dmap.put(new Integer(304),"SUMX2MY2");
dmap.put(new Integer(305),"SUMX2PY2");
dmap.put(new Integer(306),"CHITEST");
dmap.put(new Integer(307),"CORREL");
dmap.put(new Integer(308),"COVAR");
dmap.put(new Integer(309),"FORECAST");
dmap.put(new Integer(310),"FTEST");
dmap.put(new Integer(311),"INTERCEPT");
dmap.put(new Integer(312),"PEARSON");
dmap.put(new Integer(313),"RSQ");
dmap.put(new Integer(314),"STEYX");
dmap.put(new Integer(315),"SLOPE");
dmap.put(new Integer(316),"TTEST");
dmap.put(new Integer(317),"PROB");
dmap.put(new Integer(318),"DEVSQ");
dmap.put(new Integer(319),"GEOMEAN");
dmap.put(new Integer(320),"HARMEAN");
dmap.put(new Integer(321),"SUMSQ");
dmap.put(new Integer(322),"KURT");
dmap.put(new Integer(323),"SKEW");
dmap.put(new Integer(324),"ZTEST");
dmap.put(new Integer(325),"LARGE");
dmap.put(new Integer(326),"SMALL");
dmap.put(new Integer(327),"QUARTILE");
dmap.put(new Integer(328),"PERCENTILE");
dmap.put(new Integer(329),"PERCENTRANK");
dmap.put(new Integer(330),"MODE");
dmap.put(new Integer(331),"TRIMMEAN");
dmap.put(new Integer(332),"TINV");
dmap.put(new Integer(334),"MOVIECOMMAND");
dmap.put(new Integer(335),"GETMOVIE");
dmap.put(new Integer(336),"CONCATENATE");
dmap.put(new Integer(337),"POWER");
dmap.put(new Integer(338),"PIVOTADDDATA");
dmap.put(new Integer(339),"GETPIVOTTABLE");
dmap.put(new Integer(340),"GETPIVOTFIELD");
dmap.put(new Integer(341),"GETPIVOTITEM");
dmap.put(new Integer(342),"RADIANS");
dmap.put(new Integer(343),"DEGREES");
dmap.put(new Integer(344),"SUBTOTAL");
dmap.put(new Integer(345),"SUMIF");
dmap.put(new Integer(346),"COUNTIF");
dmap.put(new Integer(347),"COUNTBLANK");
dmap.put(new Integer(348),"SCENARIOGET");
dmap.put(new Integer(349),"OPTIONSLISTSGET");
dmap.put(new Integer(350),"ISPMT");
dmap.put(new Integer(351),"DATEDIF");
dmap.put(new Integer(352),"DATESTRING");
dmap.put(new Integer(353),"NUMBERSTRING");
dmap.put(new Integer(354),"ROMAN");
dmap.put(new Integer(355),"OPENDIALOG");
dmap.put(new Integer(356),"SAVEDIALOG");
dmap.put(new Integer(357),"VIEWGET");
dmap.put(new Integer(358),"GETPIVOTDATA");
dmap.put(new Integer(359),"HYPERLINK");
dmap.put(new Integer(360),"PHONETIC");
dmap.put(new Integer(361),"AVERAGEA");
dmap.put(new Integer(362),"MAXA");
dmap.put(new Integer(363),"MINA");
dmap.put(new Integer(364),"STDEVPA");
dmap.put(new Integer(365),"VARPA");
dmap.put(new Integer(366),"STDEVA");
dmap.put(new Integer(367),"VARA");
return dmap;
}
private static Object[][] produceFunctionData() {
Object [][] functionData = new Object[368][3];
//return Class // Param Class //Num Params
functionData[0][0]=new Byte(Ptg.CLASS_VALUE);functionData[0][1]=new byte[] {Ptg.CLASS_REF};functionData[0][2]=new Integer(-1);
functionData[2][0]=new Byte(Ptg.CLASS_VALUE);functionData[2][1]=new byte[] {Ptg.CLASS_VALUE};functionData[2][2]=new Integer(1);
functionData[3][0]=new Byte(Ptg.CLASS_VALUE);functionData[3][1]=new byte[] {Ptg.CLASS_VALUE};functionData[3][2]=new Integer(1);
functionData[4][0]=new Byte(Ptg.CLASS_VALUE);functionData[4][1]=new byte[] {Ptg.CLASS_REF};functionData[4][2]=new Integer(-1);
functionData[5][0]=new Byte(Ptg.CLASS_VALUE);functionData[5][1]=new byte[] {Ptg.CLASS_REF};functionData[5][2]=new Integer(-1);
functionData[6][0]=new Byte(Ptg.CLASS_VALUE);functionData[6][1]=new byte[] {Ptg.CLASS_REF};functionData[6][2]=new Integer(-1);
functionData[7][0]=new Byte(Ptg.CLASS_VALUE);functionData[7][1]=new byte[] {Ptg.CLASS_REF};functionData[7][2]=new Integer(-1);
functionData[8][0]=new Byte(Ptg.CLASS_VALUE);functionData[8][1]=new byte[] {Ptg.CLASS_REF};functionData[8][2]=new Integer(-1);
functionData[9][0]=new Byte(Ptg.CLASS_VALUE);functionData[9][1]=new byte[] {Ptg.CLASS_REF};functionData[9][2]=new Integer(-1);
functionData[10][0]=new Byte(Ptg.CLASS_VALUE);functionData[10][1]=new byte[] {Ptg.CLASS_VALUE};functionData[10][2]=new Integer(0);
functionData[11][0]=new Byte(Ptg.CLASS_VALUE);functionData[11][1]=new byte[] {Ptg.CLASS_REF};functionData[11][2]=new Integer(-1);
functionData[12][0]=new Byte(Ptg.CLASS_VALUE);functionData[12][1]=new byte[] {Ptg.CLASS_REF};functionData[12][2]=new Integer(-1);
functionData[13][0]=new Byte(Ptg.CLASS_VALUE);functionData[13][1]=new byte[] {Ptg.CLASS_VALUE};functionData[13][2]=new Integer(-1);
functionData[14][0]=new Byte(Ptg.CLASS_VALUE);functionData[14][1]=new byte[] {Ptg.CLASS_VALUE};functionData[14][2]=new Integer(-1);
functionData[15][0]=new Byte(Ptg.CLASS_VALUE);functionData[15][1]=new byte[] {Ptg.CLASS_VALUE};functionData[15][2]=new Integer(1);
functionData[16][0]=new Byte(Ptg.CLASS_VALUE);functionData[16][1]=new byte[] {Ptg.CLASS_VALUE};functionData[16][2]=new Integer(1);
functionData[17][0]=new Byte(Ptg.CLASS_VALUE);functionData[17][1]=new byte[] {Ptg.CLASS_VALUE};functionData[17][2]=new Integer(1);
functionData[18][0]=new Byte(Ptg.CLASS_VALUE);functionData[18][1]=new byte[] {Ptg.CLASS_VALUE};functionData[18][2]=new Integer(1);
functionData[19][0]=new Byte(Ptg.CLASS_VALUE);functionData[19][1]=new byte[] {Ptg.CLASS_VALUE};functionData[19][2]=new Integer(0);
functionData[20][0]=new Byte(Ptg.CLASS_VALUE);functionData[20][1]=new byte[] {Ptg.CLASS_VALUE};functionData[20][2]=new Integer(1);
functionData[21][0]=new Byte(Ptg.CLASS_VALUE);functionData[21][1]=new byte[] {Ptg.CLASS_VALUE};functionData[21][2]=new Integer(1);
functionData[22][0]=new Byte(Ptg.CLASS_VALUE);functionData[22][1]=new byte[] {Ptg.CLASS_VALUE};functionData[22][2]=new Integer(1);
functionData[23][0]=new Byte(Ptg.CLASS_VALUE);functionData[23][1]=new byte[] {Ptg.CLASS_VALUE};functionData[23][2]=new Integer(1);
functionData[24][0]=new Byte(Ptg.CLASS_VALUE);functionData[24][1]=new byte[] {Ptg.CLASS_VALUE};functionData[24][2]=new Integer(1);
functionData[25][0]=new Byte(Ptg.CLASS_VALUE);functionData[25][1]=new byte[] {Ptg.CLASS_VALUE};functionData[25][2]=new Integer(1);
functionData[26][0]=new Byte(Ptg.CLASS_VALUE);functionData[26][1]=new byte[] {Ptg.CLASS_VALUE};functionData[26][2]=new Integer(1);
functionData[27][0]=new Byte(Ptg.CLASS_VALUE);functionData[27][1]=new byte[] {Ptg.CLASS_VALUE};functionData[27][2]=new Integer(2);
functionData[28][0]=new Byte(Ptg.CLASS_VALUE);functionData[28][1]=new byte[] {Ptg.CLASS_VALUE, Ptg.CLASS_REF};functionData[28][2]=new Integer(-1);
functionData[29][0]=new Byte(Ptg.CLASS_VALUE);functionData[29][1]=new byte[] {Ptg.CLASS_REF};functionData[29][2]=new Integer(-1);
functionData[30][0]=new Byte(Ptg.CLASS_VALUE);functionData[30][1]=new byte[] {Ptg.CLASS_VALUE};functionData[30][2]=new Integer(2);
functionData[31][0]=new Byte(Ptg.CLASS_VALUE);functionData[31][1]=new byte[] {Ptg.CLASS_VALUE};functionData[31][2]=new Integer(3);
functionData[32][0]=new Byte(Ptg.CLASS_VALUE);functionData[32][1]=new byte[] {Ptg.CLASS_VALUE};functionData[32][2]=new Integer(1);
functionData[33][0]=new Byte(Ptg.CLASS_VALUE);functionData[33][1]=new byte[] {Ptg.CLASS_VALUE};functionData[33][2]=new Integer(1);
functionData[34][0]=new Byte(Ptg.CLASS_VALUE);functionData[34][1]=new byte[] {Ptg.CLASS_VALUE};functionData[34][2]=new Integer(0);
functionData[35][0]=new Byte(Ptg.CLASS_VALUE);functionData[35][1]=new byte[] {Ptg.CLASS_VALUE};functionData[35][2]=new Integer(0);
functionData[36][0]=new Byte(Ptg.CLASS_VALUE);functionData[36][1]=new byte[] {Ptg.CLASS_REF};functionData[36][2]=new Integer(-1);
functionData[37][0]=new Byte(Ptg.CLASS_VALUE);functionData[37][1]=new byte[] {Ptg.CLASS_REF};functionData[37][2]=new Integer(-1);
functionData[38][0]=new Byte(Ptg.CLASS_VALUE);functionData[38][1]=new byte[] {Ptg.CLASS_VALUE};functionData[38][2]=new Integer(1);
functionData[39][0]=new Byte(Ptg.CLASS_VALUE);functionData[39][1]=new byte[] {Ptg.CLASS_VALUE};functionData[39][2]=new Integer(2);
functionData[40][0]=new Byte(Ptg.CLASS_VALUE);functionData[40][1]=new byte[] {Ptg.CLASS_REF};functionData[40][2]=new Integer(3);
functionData[41][0]=new Byte(Ptg.CLASS_VALUE);functionData[41][1]=new byte[] {Ptg.CLASS_REF};functionData[41][2]=new Integer(3);
functionData[42][0]=new Byte(Ptg.CLASS_VALUE);functionData[42][1]=new byte[] {Ptg.CLASS_REF};functionData[42][2]=new Integer(3);
functionData[43][0]=new Byte(Ptg.CLASS_VALUE);functionData[43][1]=new byte[] {Ptg.CLASS_REF};functionData[43][2]=new Integer(3);
functionData[44][0]=new Byte(Ptg.CLASS_VALUE);functionData[44][1]=new byte[] {Ptg.CLASS_REF};functionData[44][2]=new Integer(3);
functionData[45][0]=new Byte(Ptg.CLASS_VALUE);functionData[45][1]=new byte[] {Ptg.CLASS_REF};functionData[45][2]=new Integer(3);
functionData[46][0]=new Byte(Ptg.CLASS_VALUE);functionData[46][1]=new byte[] {Ptg.CLASS_REF};functionData[46][2]=new Integer(-1);
functionData[47][0]=new Byte(Ptg.CLASS_VALUE);functionData[47][1]=new byte[] {Ptg.CLASS_REF};functionData[47][2]=new Integer(3);
functionData[48][0]=new Byte(Ptg.CLASS_VALUE);functionData[48][1]=new byte[] {Ptg.CLASS_VALUE};functionData[48][2]=new Integer(2);
functionData[49][0]=new Byte(Ptg.CLASS_VALUE);functionData[49][1]=new byte[] {Ptg.CLASS_REF};functionData[49][2]=new Integer(-1);
functionData[50][0]=new Byte(Ptg.CLASS_VALUE);functionData[50][1]=new byte[] {Ptg.CLASS_REF};functionData[50][2]=new Integer(-1);
functionData[51][0]=new Byte(Ptg.CLASS_VALUE);functionData[51][1]=new byte[] {Ptg.CLASS_REF};functionData[51][2]=new Integer(-1);
functionData[52][0]=new Byte(Ptg.CLASS_VALUE);functionData[52][1]=new byte[] {Ptg.CLASS_REF};functionData[52][2]=new Integer(-1);
functionData[56][0]=new Byte(Ptg.CLASS_VALUE);functionData[56][1]=new byte[] {Ptg.CLASS_VALUE};functionData[56][2]=new Integer(-1);
functionData[57][0]=new Byte(Ptg.CLASS_VALUE);functionData[57][1]=new byte[] {Ptg.CLASS_VALUE};functionData[57][2]=new Integer(-1);
functionData[58][0]=new Byte(Ptg.CLASS_VALUE);functionData[58][1]=new byte[] {Ptg.CLASS_VALUE};functionData[58][2]=new Integer(-1);
functionData[59][0]=new Byte(Ptg.CLASS_VALUE);functionData[59][1]=new byte[] {Ptg.CLASS_VALUE};functionData[59][2]=new Integer(-1);
functionData[60][0]=new Byte(Ptg.CLASS_VALUE);functionData[60][1]=new byte[] {Ptg.CLASS_VALUE};functionData[60][2]=new Integer(-1);
functionData[61][0]=new Byte(Ptg.CLASS_VALUE);functionData[61][1]=new byte[] {Ptg.CLASS_VALUE};functionData[61][2]=new Integer(3);
functionData[62][0]=new Byte(Ptg.CLASS_VALUE);functionData[62][1]=new byte[] {Ptg.CLASS_REF};functionData[62][2]=new Integer(-1);
functionData[63][0]=new Byte(Ptg.CLASS_VALUE);functionData[63][1]=new byte[] {Ptg.CLASS_REF};functionData[63][2]=new Integer(1);
functionData[64][0]=new Byte(Ptg.CLASS_VALUE);functionData[64][1]=new byte[] {Ptg.CLASS_VALUE, Ptg.CLASS_REF};functionData[64][2]=new Integer(-1);
functionData[65][0]=new Byte(Ptg.CLASS_VALUE);functionData[65][1]=new byte[] {Ptg.CLASS_VALUE};functionData[65][2]=new Integer(3);
functionData[66][0]=new Byte(Ptg.CLASS_VALUE);functionData[66][1]=new byte[] {Ptg.CLASS_VALUE};functionData[66][2]=new Integer(3);
functionData[67][0]=new Byte(Ptg.CLASS_VALUE);functionData[67][1]=new byte[] {Ptg.CLASS_VALUE};functionData[67][2]=new Integer(1);
functionData[68][0]=new Byte(Ptg.CLASS_VALUE);functionData[68][1]=new byte[] {Ptg.CLASS_VALUE};functionData[68][2]=new Integer(1);
functionData[69][0]=new Byte(Ptg.CLASS_VALUE);functionData[69][1]=new byte[] {Ptg.CLASS_VALUE};functionData[69][2]=new Integer(1);
functionData[70][0]=new Byte(Ptg.CLASS_VALUE);functionData[70][1]=new byte[] {Ptg.CLASS_VALUE};functionData[70][2]=new Integer(-1);
functionData[71][0]=new Byte(Ptg.CLASS_VALUE);functionData[71][1]=new byte[] {Ptg.CLASS_VALUE};functionData[71][2]=new Integer(1);
functionData[72][0]=new Byte(Ptg.CLASS_VALUE);functionData[72][1]=new byte[] {Ptg.CLASS_VALUE};functionData[72][2]=new Integer(1);
functionData[73][0]=new Byte(Ptg.CLASS_VALUE);functionData[73][1]=new byte[] {Ptg.CLASS_VALUE};functionData[73][2]=new Integer(1);
functionData[74][0]=new Byte(Ptg.CLASS_VALUE);functionData[74][1]=new byte[] {Ptg.CLASS_REF};functionData[74][2]=new Integer(1);
functionData[75][0]=new Byte(Ptg.CLASS_VALUE);functionData[75][1]=new byte[] {Ptg.CLASS_REF};functionData[75][2]=new Integer(1);
functionData[76][0]=new Byte(Ptg.CLASS_VALUE);functionData[76][1]=new byte[] {Ptg.CLASS_REF};functionData[76][2]=new Integer(1);
functionData[77][0]=new Byte(Ptg.CLASS_VALUE);functionData[77][1]=new byte[] {Ptg.CLASS_REF};functionData[77][2]=new Integer(1);
functionData[78][0]=new Byte(Ptg.CLASS_VALUE);functionData[78][1]=new byte[] {Ptg.CLASS_VALUE};functionData[78][2]=new Integer(-1);
functionData[82][0]=new Byte(Ptg.CLASS_VALUE);functionData[82][1]=new byte[] {Ptg.CLASS_VALUE};functionData[82][2]=new Integer(-1);
functionData[83][0]=new Byte(Ptg.CLASS_VALUE);functionData[83][1]=new byte[] {Ptg.CLASS_VALUE};functionData[83][2]=new Integer(1);
functionData[86][0]=new Byte(Ptg.CLASS_VALUE);functionData[86][1]=new byte[] {Ptg.CLASS_VALUE};functionData[86][2]=new Integer(1);
functionData[97][0]=new Byte(Ptg.CLASS_VALUE);functionData[97][1]=new byte[] {Ptg.CLASS_VALUE};functionData[97][2]=new Integer(2);
functionData[98][0]=new Byte(Ptg.CLASS_VALUE);functionData[98][1]=new byte[] {Ptg.CLASS_VALUE};functionData[98][2]=new Integer(1);
functionData[99][0]=new Byte(Ptg.CLASS_VALUE);functionData[99][1]=new byte[] {Ptg.CLASS_VALUE};functionData[99][2]=new Integer(1);
functionData[101][0]=new Byte(Ptg.CLASS_VALUE);functionData[101][1]=new byte[] {Ptg.CLASS_REF};functionData[101][2]=new Integer(-1);
functionData[102][0]=new Byte(Ptg.CLASS_VALUE);functionData[102][1]=new byte[] {Ptg.CLASS_REF};functionData[102][2]=new Integer(-1);
functionData[105][0]=new Byte(Ptg.CLASS_VALUE);functionData[105][1]=new byte[] {Ptg.CLASS_REF};functionData[105][2]=new Integer(1);
functionData[109][0]=new Byte(Ptg.CLASS_VALUE);functionData[109][1]=new byte[] {Ptg.CLASS_VALUE};functionData[109][2]=new Integer(-1);
functionData[111][0]=new Byte(Ptg.CLASS_VALUE);functionData[111][1]=new byte[] {Ptg.CLASS_VALUE};functionData[111][2]=new Integer(1);
functionData[112][0]=new Byte(Ptg.CLASS_VALUE);functionData[112][1]=new byte[] {Ptg.CLASS_VALUE};functionData[112][2]=new Integer(1);
functionData[113][0]=new Byte(Ptg.CLASS_VALUE);functionData[113][1]=new byte[] {Ptg.CLASS_VALUE};functionData[113][2]=new Integer(1);
functionData[114][0]=new Byte(Ptg.CLASS_VALUE);functionData[114][1]=new byte[] {Ptg.CLASS_VALUE};functionData[114][2]=new Integer(1);
functionData[115][0]=new Byte(Ptg.CLASS_VALUE);functionData[115][1]=new byte[] {Ptg.CLASS_VALUE};functionData[115][2]=new Integer(-1);
functionData[116][0]=new Byte(Ptg.CLASS_VALUE);functionData[116][1]=new byte[] {Ptg.CLASS_VALUE};functionData[116][2]=new Integer(-1);
functionData[117][0]=new Byte(Ptg.CLASS_VALUE);functionData[117][1]=new byte[] {Ptg.CLASS_VALUE};functionData[117][2]=new Integer(2);
functionData[118][0]=new Byte(Ptg.CLASS_VALUE);functionData[118][1]=new byte[] {Ptg.CLASS_VALUE};functionData[118][2]=new Integer(1);
functionData[119][0]=new Byte(Ptg.CLASS_VALUE);functionData[119][1]=new byte[] {Ptg.CLASS_VALUE};functionData[119][2]=new Integer(4);
functionData[120][0]=new Byte(Ptg.CLASS_VALUE);functionData[120][1]=new byte[] {Ptg.CLASS_VALUE};functionData[120][2]=new Integer(-1);
functionData[121][0]=new Byte(Ptg.CLASS_VALUE);functionData[121][1]=new byte[] {Ptg.CLASS_VALUE};functionData[121][2]=new Integer(1);
functionData[124][0]=new Byte(Ptg.CLASS_VALUE);functionData[124][1]=new byte[] {Ptg.CLASS_VALUE};functionData[124][2]=new Integer(-1);
functionData[125][0]=new Byte(Ptg.CLASS_VALUE);functionData[125][1]=new byte[] {Ptg.CLASS_VALUE};functionData[125][2]=new Integer(-1);
functionData[126][0]=new Byte(Ptg.CLASS_VALUE);functionData[126][1]=new byte[] {Ptg.CLASS_VALUE};functionData[126][2]=new Integer(1);
functionData[127][0]=new Byte(Ptg.CLASS_VALUE);functionData[127][1]=new byte[] {Ptg.CLASS_VALUE};functionData[127][2]=new Integer(1);
functionData[128][0]=new Byte(Ptg.CLASS_VALUE);functionData[128][1]=new byte[] {Ptg.CLASS_VALUE};functionData[128][2]=new Integer(1);
functionData[129][0]=new Byte(Ptg.CLASS_VALUE);functionData[129][1]=new byte[] {Ptg.CLASS_VALUE};functionData[129][2]=new Integer(1);
functionData[130][0]=new Byte(Ptg.CLASS_VALUE);functionData[130][1]=new byte[] {Ptg.CLASS_REF};functionData[130][2]=new Integer(1);
functionData[131][0]=new Byte(Ptg.CLASS_VALUE);functionData[131][1]=new byte[] {Ptg.CLASS_REF};functionData[131][2]=new Integer(1);
functionData[140][0]=new Byte(Ptg.CLASS_VALUE);functionData[140][1]=new byte[] {Ptg.CLASS_VALUE};functionData[140][2]=new Integer(1);
functionData[141][0]=new Byte(Ptg.CLASS_VALUE);functionData[141][1]=new byte[] {Ptg.CLASS_VALUE};functionData[141][2]=new Integer(1);
functionData[142][0]=new Byte(Ptg.CLASS_VALUE);functionData[142][1]=new byte[] {Ptg.CLASS_VALUE};functionData[142][2]=new Integer(3);
functionData[148][0]=new Byte(Ptg.CLASS_VALUE);functionData[148][1]=new byte[] {Ptg.CLASS_VALUE};functionData[148][2]=new Integer(-1);
functionData[150][0]=new Byte(Ptg.CLASS_VALUE);functionData[150][1]=new byte[] {Ptg.CLASS_VALUE};functionData[150][2]=new Integer(-1);
functionData[162][0]=new Byte(Ptg.CLASS_VALUE);functionData[162][1]=new byte[] {Ptg.CLASS_VALUE};functionData[162][2]=new Integer(1);
functionData[163][0]=new Byte(Ptg.CLASS_VALUE);functionData[163][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[163][2]=new Integer(1);
functionData[164][0]=new Byte(Ptg.CLASS_VALUE);functionData[164][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[164][2]=new Integer(1);
functionData[165][0]=new Byte(Ptg.CLASS_VALUE);functionData[165][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[165][2]=new Integer(2);
functionData[166][0]=new Byte(Ptg.CLASS_VALUE);functionData[166][1]=new byte[] {Ptg.CLASS_VALUE};functionData[166][2]=new Integer(-1);
functionData[167][0]=new Byte(Ptg.CLASS_VALUE);functionData[167][1]=new byte[] {Ptg.CLASS_VALUE};functionData[167][2]=new Integer(-1);
functionData[168][0]=new Byte(Ptg.CLASS_VALUE);functionData[168][1]=new byte[] {Ptg.CLASS_REF};functionData[168][2]=new Integer(-1);
functionData[183][0]=new Byte(Ptg.CLASS_VALUE);functionData[183][1]=new byte[] {Ptg.CLASS_REF};functionData[183][2]=new Integer(-1);
functionData[184][0]=new Byte(Ptg.CLASS_VALUE);functionData[184][1]=new byte[] {Ptg.CLASS_VALUE};functionData[184][2]=new Integer(1);
functionData[189][0]=new Byte(Ptg.CLASS_VALUE);functionData[189][1]=new byte[] {Ptg.CLASS_REF};functionData[189][2]=new Integer(3);
functionData[190][0]=new Byte(Ptg.CLASS_VALUE);functionData[190][1]=new byte[] {Ptg.CLASS_VALUE};functionData[190][2]=new Integer(1);
functionData[193][0]=new Byte(Ptg.CLASS_VALUE);functionData[193][1]=new byte[] {Ptg.CLASS_REF};functionData[193][2]=new Integer(-1);
functionData[194][0]=new Byte(Ptg.CLASS_VALUE);functionData[194][1]=new byte[] {Ptg.CLASS_REF};functionData[194][2]=new Integer(-1);
functionData[195][0]=new Byte(Ptg.CLASS_VALUE);functionData[195][1]=new byte[] {Ptg.CLASS_REF};functionData[195][2]=new Integer(3);
functionData[196][0]=new Byte(Ptg.CLASS_VALUE);functionData[196][1]=new byte[] {Ptg.CLASS_REF};functionData[196][2]=new Integer(3);
functionData[197][0]=new Byte(Ptg.CLASS_VALUE);functionData[197][1]=new byte[] {Ptg.CLASS_VALUE};functionData[197][2]=new Integer(-1);
functionData[198][0]=new Byte(Ptg.CLASS_VALUE);functionData[198][1]=new byte[] {Ptg.CLASS_VALUE};functionData[198][2]=new Integer(1);
functionData[199][0]=new Byte(Ptg.CLASS_VALUE);functionData[199][1]=new byte[] {Ptg.CLASS_REF};functionData[199][2]=new Integer(3);
functionData[204][0]=new Byte(Ptg.CLASS_VALUE);functionData[204][1]=new byte[] {Ptg.CLASS_VALUE};functionData[204][2]=new Integer(-1);
functionData[205][0]=new Byte(Ptg.CLASS_VALUE);functionData[205][1]=new byte[] {Ptg.CLASS_VALUE};functionData[205][2]=new Integer(-1);
functionData[206][0]=new Byte(Ptg.CLASS_VALUE);functionData[206][1]=new byte[] {Ptg.CLASS_VALUE};functionData[206][2]=new Integer(-1);
functionData[207][0]=new Byte(Ptg.CLASS_VALUE);functionData[207][1]=new byte[] {Ptg.CLASS_VALUE};functionData[207][2]=new Integer(3);
functionData[208][0]=new Byte(Ptg.CLASS_VALUE);functionData[208][1]=new byte[] {Ptg.CLASS_VALUE};functionData[208][2]=new Integer(1);
functionData[209][0]=new Byte(Ptg.CLASS_VALUE);functionData[209][1]=new byte[] {Ptg.CLASS_VALUE};functionData[209][2]=new Integer(2);
functionData[210][0]=new Byte(Ptg.CLASS_VALUE);functionData[210][1]=new byte[] {Ptg.CLASS_VALUE};functionData[210][2]=new Integer(2);
functionData[211][0]=new Byte(Ptg.CLASS_VALUE);functionData[211][1]=new byte[] {Ptg.CLASS_VALUE};functionData[211][2]=new Integer(1);
functionData[212][0]=new Byte(Ptg.CLASS_VALUE);functionData[212][1]=new byte[] {Ptg.CLASS_VALUE};functionData[212][2]=new Integer(2);
functionData[213][0]=new Byte(Ptg.CLASS_VALUE);functionData[213][1]=new byte[] {Ptg.CLASS_REF};functionData[213][2]=new Integer(2);
functionData[214][0]=new Byte(Ptg.CLASS_VALUE);functionData[214][1]=new byte[] {Ptg.CLASS_VALUE};functionData[214][2]=new Integer(-1);
functionData[221][0]=new Byte(Ptg.CLASS_VALUE);functionData[221][1]=new byte[] {Ptg.CLASS_REF};functionData[221][2]=new Integer(1);
functionData[222][0]=new Byte(Ptg.CLASS_VALUE);functionData[222][1]=new byte[] {Ptg.CLASS_VALUE};functionData[222][2]=new Integer(-1);
functionData[227][0]=new Byte(Ptg.CLASS_VALUE);functionData[227][1]=new byte[] {Ptg.CLASS_REF};functionData[227][2]=new Integer(-1);
functionData[228][0]=new Byte(Ptg.CLASS_VALUE);functionData[228][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[228][2]=new Integer(-1);
functionData[229][0]=new Byte(Ptg.CLASS_VALUE);functionData[229][1]=new byte[] {Ptg.CLASS_VALUE};functionData[229][2]=new Integer(1);
functionData[230][0]=new Byte(Ptg.CLASS_VALUE);functionData[230][1]=new byte[] {Ptg.CLASS_VALUE};functionData[230][2]=new Integer(1);
functionData[231][0]=new Byte(Ptg.CLASS_VALUE);functionData[231][1]=new byte[] {Ptg.CLASS_VALUE};functionData[231][2]=new Integer(1);
functionData[232][0]=new Byte(Ptg.CLASS_VALUE);functionData[232][1]=new byte[] {Ptg.CLASS_VALUE};functionData[232][2]=new Integer(1);
functionData[233][0]=new Byte(Ptg.CLASS_VALUE);functionData[233][1]=new byte[] {Ptg.CLASS_VALUE};functionData[233][2]=new Integer(1);
functionData[234][0]=new Byte(Ptg.CLASS_VALUE);functionData[234][1]=new byte[] {Ptg.CLASS_VALUE};functionData[234][2]=new Integer(1);
functionData[235][0]=new Byte(Ptg.CLASS_VALUE);functionData[235][1]=new byte[] {Ptg.CLASS_REF};functionData[235][2]=new Integer(3);
functionData[244][0]=new Byte(Ptg.CLASS_VALUE);functionData[244][1]=new byte[] {Ptg.CLASS_VALUE};functionData[244][2]=new Integer(2);
functionData[252][0]=new Byte(Ptg.CLASS_VALUE);functionData[252][1]=new byte[] {Ptg.CLASS_REF};functionData[252][2]=new Integer(2);
functionData[261][0]=new Byte(Ptg.CLASS_VALUE);functionData[261][1]=new byte[] {Ptg.CLASS_VALUE};functionData[261][2]=new Integer(1);
functionData[269][0]=new Byte(Ptg.CLASS_VALUE);functionData[269][1]=new byte[] {Ptg.CLASS_REF};functionData[269][2]=new Integer(-1);
functionData[270][0]=new Byte(Ptg.CLASS_VALUE);functionData[270][1]=new byte[] {Ptg.CLASS_VALUE};functionData[270][2]=new Integer(-1);
functionData[271][0]=new Byte(Ptg.CLASS_VALUE);functionData[271][1]=new byte[] {Ptg.CLASS_VALUE};functionData[271][2]=new Integer(1);
functionData[272][0]=new Byte(Ptg.CLASS_VALUE);functionData[272][1]=new byte[] {Ptg.CLASS_VALUE};functionData[272][2]=new Integer(-1);
functionData[273][0]=new Byte(Ptg.CLASS_VALUE);functionData[273][1]=new byte[] {Ptg.CLASS_VALUE};functionData[273][2]=new Integer(4);
functionData[274][0]=new Byte(Ptg.CLASS_VALUE);functionData[274][1]=new byte[] {Ptg.CLASS_VALUE};functionData[274][2]=new Integer(2);
functionData[275][0]=new Byte(Ptg.CLASS_VALUE);functionData[275][1]=new byte[] {Ptg.CLASS_VALUE};functionData[275][2]=new Integer(2);
functionData[276][0]=new Byte(Ptg.CLASS_VALUE);functionData[276][1]=new byte[] {Ptg.CLASS_VALUE};functionData[276][2]=new Integer(2);
functionData[277][0]=new Byte(Ptg.CLASS_VALUE);functionData[277][1]=new byte[] {Ptg.CLASS_VALUE};functionData[277][2]=new Integer(3);
functionData[278][0]=new Byte(Ptg.CLASS_VALUE);functionData[278][1]=new byte[] {Ptg.CLASS_VALUE};functionData[278][2]=new Integer(3);
functionData[279][0]=new Byte(Ptg.CLASS_VALUE);functionData[279][1]=new byte[] {Ptg.CLASS_VALUE};functionData[279][2]=new Integer(1);
functionData[280][0]=new Byte(Ptg.CLASS_VALUE);functionData[280][1]=new byte[] {Ptg.CLASS_VALUE};functionData[280][2]=new Integer(3);
functionData[281][0]=new Byte(Ptg.CLASS_VALUE);functionData[281][1]=new byte[] {Ptg.CLASS_VALUE};functionData[281][2]=new Integer(3);
functionData[282][0]=new Byte(Ptg.CLASS_VALUE);functionData[282][1]=new byte[] {Ptg.CLASS_VALUE};functionData[282][2]=new Integer(3);
functionData[283][0]=new Byte(Ptg.CLASS_VALUE);functionData[283][1]=new byte[] {Ptg.CLASS_VALUE};functionData[283][2]=new Integer(1);
functionData[284][0]=new Byte(Ptg.CLASS_VALUE);functionData[284][1]=new byte[] {Ptg.CLASS_VALUE};functionData[284][2]=new Integer(1);
functionData[285][0]=new Byte(Ptg.CLASS_VALUE);functionData[285][1]=new byte[] {Ptg.CLASS_VALUE};functionData[285][2]=new Integer(2);
functionData[286][0]=new Byte(Ptg.CLASS_VALUE);functionData[286][1]=new byte[] {Ptg.CLASS_VALUE};functionData[286][2]=new Integer(4);
functionData[287][0]=new Byte(Ptg.CLASS_VALUE);functionData[287][1]=new byte[] {Ptg.CLASS_VALUE};functionData[287][2]=new Integer(3);
functionData[288][0]=new Byte(Ptg.CLASS_VALUE);functionData[288][1]=new byte[] {Ptg.CLASS_VALUE};functionData[288][2]=new Integer(2);
functionData[289][0]=new Byte(Ptg.CLASS_VALUE);functionData[289][1]=new byte[] {Ptg.CLASS_VALUE};functionData[289][2]=new Integer(4);
functionData[290][0]=new Byte(Ptg.CLASS_VALUE);functionData[290][1]=new byte[] {Ptg.CLASS_VALUE};functionData[290][2]=new Integer(3);
functionData[291][0]=new Byte(Ptg.CLASS_VALUE);functionData[291][1]=new byte[] {Ptg.CLASS_VALUE};functionData[291][2]=new Integer(3);
functionData[292][0]=new Byte(Ptg.CLASS_VALUE);functionData[292][1]=new byte[] {Ptg.CLASS_VALUE};functionData[292][2]=new Integer(3);
functionData[293][0]=new Byte(Ptg.CLASS_VALUE);functionData[293][1]=new byte[] {Ptg.CLASS_VALUE};functionData[293][2]=new Integer(4);
functionData[294][0]=new Byte(Ptg.CLASS_VALUE);functionData[294][1]=new byte[] {Ptg.CLASS_VALUE};functionData[294][2]=new Integer(1);
functionData[295][0]=new Byte(Ptg.CLASS_VALUE);functionData[295][1]=new byte[] {Ptg.CLASS_VALUE};functionData[295][2]=new Integer(3);
functionData[296][0]=new Byte(Ptg.CLASS_VALUE);functionData[296][1]=new byte[] {Ptg.CLASS_VALUE};functionData[296][2]=new Integer(1);
functionData[297][0]=new Byte(Ptg.CLASS_VALUE);functionData[297][1]=new byte[] {Ptg.CLASS_VALUE};functionData[297][2]=new Integer(3);
functionData[298][0]=new Byte(Ptg.CLASS_VALUE);functionData[298][1]=new byte[] {Ptg.CLASS_VALUE};functionData[298][2]=new Integer(1);
functionData[299][0]=new Byte(Ptg.CLASS_VALUE);functionData[299][1]=new byte[] {Ptg.CLASS_VALUE};functionData[299][2]=new Integer(2);
functionData[300][0]=new Byte(Ptg.CLASS_VALUE);functionData[300][1]=new byte[] {Ptg.CLASS_VALUE};functionData[300][2]=new Integer(3);
functionData[301][0]=new Byte(Ptg.CLASS_VALUE);functionData[301][1]=new byte[] {Ptg.CLASS_VALUE};functionData[301][2]=new Integer(3);
functionData[302][0]=new Byte(Ptg.CLASS_VALUE);functionData[302][1]=new byte[] {Ptg.CLASS_VALUE};functionData[302][2]=new Integer(4);
functionData[303][0]=new Byte(Ptg.CLASS_VALUE);functionData[303][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[303][2]=new Integer(2);
functionData[304][0]=new Byte(Ptg.CLASS_VALUE);functionData[304][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[304][2]=new Integer(2);
functionData[305][0]=new Byte(Ptg.CLASS_VALUE);functionData[305][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[305][2]=new Integer(2);
functionData[306][0]=new Byte(Ptg.CLASS_VALUE);functionData[306][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[306][2]=new Integer(2);
functionData[307][0]=new Byte(Ptg.CLASS_VALUE);functionData[307][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[307][2]=new Integer(2);
functionData[308][0]=new Byte(Ptg.CLASS_VALUE);functionData[308][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[308][2]=new Integer(2);
functionData[309][0]=new Byte(Ptg.CLASS_VALUE);functionData[309][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[309][2]=new Integer(3);
functionData[310][0]=new Byte(Ptg.CLASS_VALUE);functionData[310][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[310][2]=new Integer(2);
functionData[311][0]=new Byte(Ptg.CLASS_VALUE);functionData[311][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[311][2]=new Integer(2);
functionData[312][0]=new Byte(Ptg.CLASS_VALUE);functionData[312][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[312][2]=new Integer(2);
functionData[313][0]=new Byte(Ptg.CLASS_VALUE);functionData[313][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[313][2]=new Integer(2);
functionData[314][0]=new Byte(Ptg.CLASS_VALUE);functionData[314][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[314][2]=new Integer(2);
functionData[315][0]=new Byte(Ptg.CLASS_VALUE);functionData[315][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[315][2]=new Integer(2);
functionData[316][0]=new Byte(Ptg.CLASS_VALUE);functionData[316][1]=new byte[] {Ptg.CLASS_VALUE};functionData[316][2]=new Integer(4);
functionData[317][0]=new Byte(Ptg.CLASS_VALUE);functionData[317][1]=new byte[] {Ptg.CLASS_VALUE};functionData[317][2]=new Integer(-1);
functionData[318][0]=new Byte(Ptg.CLASS_VALUE);functionData[318][1]=new byte[] {Ptg.CLASS_REF};functionData[318][2]=new Integer(-1);
functionData[319][0]=new Byte(Ptg.CLASS_VALUE);functionData[319][1]=new byte[] {Ptg.CLASS_REF};functionData[319][2]=new Integer(-1);
functionData[320][0]=new Byte(Ptg.CLASS_VALUE);functionData[320][1]=new byte[] {Ptg.CLASS_REF};functionData[320][2]=new Integer(-1);
functionData[321][0]=new Byte(Ptg.CLASS_VALUE);functionData[321][1]=new byte[] {Ptg.CLASS_REF};functionData[321][2]=new Integer(-1);
functionData[322][0]=new Byte(Ptg.CLASS_VALUE);functionData[322][1]=new byte[] {Ptg.CLASS_REF};functionData[322][2]=new Integer(-1);
functionData[323][0]=new Byte(Ptg.CLASS_VALUE);functionData[323][1]=new byte[] {Ptg.CLASS_REF};functionData[323][2]=new Integer(-1);
functionData[324][0]=new Byte(Ptg.CLASS_VALUE);functionData[324][1]=new byte[] {Ptg.CLASS_VALUE};functionData[324][2]=new Integer(-1);
functionData[325][0]=new Byte(Ptg.CLASS_VALUE);functionData[325][1]=new byte[] {Ptg.CLASS_VALUE};functionData[325][2]=new Integer(2);
functionData[326][0]=new Byte(Ptg.CLASS_VALUE);functionData[326][1]=new byte[] {Ptg.CLASS_VALUE};functionData[326][2]=new Integer(2);
functionData[327][0]=new Byte(Ptg.CLASS_VALUE);functionData[327][1]=new byte[] {Ptg.CLASS_VALUE};functionData[327][2]=new Integer(2);
functionData[328][0]=new Byte(Ptg.CLASS_VALUE);functionData[328][1]=new byte[] {Ptg.CLASS_VALUE};functionData[328][2]=new Integer(2);
functionData[329][0]=new Byte(Ptg.CLASS_VALUE);functionData[329][1]=new byte[] {Ptg.CLASS_VALUE};functionData[329][2]=new Integer(-1);
functionData[330][0]=new Byte(Ptg.CLASS_VALUE);functionData[330][1]=new byte[] {Ptg.CLASS_ARRAY};functionData[330][2]=new Integer(-1);
functionData[331][0]=new Byte(Ptg.CLASS_VALUE);functionData[331][1]=new byte[] {Ptg.CLASS_VALUE};functionData[331][2]=new Integer(2);
functionData[332][0]=new Byte(Ptg.CLASS_VALUE);functionData[332][1]=new byte[] {Ptg.CLASS_VALUE};functionData[332][2]=new Integer(2);
functionData[336][0]=new Byte(Ptg.CLASS_VALUE);functionData[336][1]=new byte[] {Ptg.CLASS_VALUE};functionData[336][2]=new Integer(-1);
functionData[337][0]=new Byte(Ptg.CLASS_VALUE);functionData[337][1]=new byte[] {Ptg.CLASS_VALUE};functionData[337][2]=new Integer(2);
functionData[342][0]=new Byte(Ptg.CLASS_VALUE);functionData[342][1]=new byte[] {Ptg.CLASS_VALUE};functionData[342][2]=new Integer(1);
functionData[343][0]=new Byte(Ptg.CLASS_VALUE);functionData[343][1]=new byte[] {Ptg.CLASS_VALUE};functionData[343][2]=new Integer(1);
functionData[344][0]=new Byte(Ptg.CLASS_VALUE);functionData[344][1]=new byte[] {Ptg.CLASS_REF};functionData[344][2]=new Integer(-1);
functionData[345][0]=new Byte(Ptg.CLASS_VALUE);functionData[345][1]=new byte[] {Ptg.CLASS_REF};functionData[345][2]=new Integer(-1);
functionData[346][0]=new Byte(Ptg.CLASS_VALUE);functionData[346][1]=new byte[] {Ptg.CLASS_VALUE};functionData[346][2]=new Integer(2);
functionData[347][0]=new Byte(Ptg.CLASS_VALUE);functionData[347][1]=new byte[] {Ptg.CLASS_REF};functionData[347][2]=new Integer(1);
functionData[350][0]=new Byte(Ptg.CLASS_VALUE);functionData[350][1]=new byte[] {Ptg.CLASS_VALUE};functionData[350][2]=new Integer(4);
functionData[352][0]=new Byte(Ptg.CLASS_VALUE);functionData[352][1]=new byte[] {Ptg.CLASS_VALUE};functionData[352][2]=new Integer(1);
functionData[354][0]=new Byte(Ptg.CLASS_VALUE);functionData[354][1]=new byte[] {Ptg.CLASS_VALUE};functionData[354][2]=new Integer(-1);
functionData[358][0]=new Byte(Ptg.CLASS_VALUE);functionData[358][1]=new byte[] {Ptg.CLASS_VALUE};functionData[358][2]=new Integer(2);
functionData[359][0]=new Byte(Ptg.CLASS_VALUE);functionData[359][1]=new byte[] {Ptg.CLASS_VALUE};functionData[359][2]=new Integer(-1);
functionData[360][0]=new Byte(Ptg.CLASS_VALUE);functionData[360][1]=new byte[] {Ptg.CLASS_REF};functionData[360][2]=new Integer(1);
functionData[361][0]=new Byte(Ptg.CLASS_VALUE);functionData[361][1]=new byte[] {Ptg.CLASS_REF};functionData[361][2]=new Integer(-1);
functionData[362][0]=new Byte(Ptg.CLASS_VALUE);functionData[362][1]=new byte[] {Ptg.CLASS_REF};functionData[362][2]=new Integer(-1);
functionData[363][0]=new Byte(Ptg.CLASS_VALUE);functionData[363][1]=new byte[] {Ptg.CLASS_REF};functionData[363][2]=new Integer(-1);
functionData[364][0]=new Byte(Ptg.CLASS_VALUE);functionData[364][1]=new byte[] {Ptg.CLASS_REF};functionData[364][2]=new Integer(-1);
functionData[365][0]=new Byte(Ptg.CLASS_VALUE);functionData[365][1]=new byte[] {Ptg.CLASS_REF};functionData[365][2]=new Integer(-1);
functionData[366][0]=new Byte(Ptg.CLASS_VALUE);functionData[366][1]=new byte[] {Ptg.CLASS_REF};functionData[366][2]=new Integer(-1);
functionData[367][0]=new Byte(Ptg.CLASS_VALUE);functionData[367][1]=new byte[] {Ptg.CLASS_REF};functionData[367][2]=new Integer(-1);
return functionData;
short ix = FunctionMetadataRegistry.lookupIndexByName(name.toUpperCase());
if (ix < 0) {
return FUNCTION_INDEX_EXTERNAL;
}
return ix;
}
public byte getDefaultOperandClass() {

View File

@ -15,17 +15,18 @@
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.formula;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.formula.function.FunctionMetadata;
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
/**
* @author aviks
* @author Jason Height (jheight at chariot dot net dot au)
* @author Danny Mui (dmui at apache dot org) (Leftover handling)
*/
public class FuncPtg extends AbstractFunctionPtg{
public final class FuncPtg extends AbstractFunctionPtg {
public final static byte sid = 0x21;
public final static int SIZE = 3;
@ -50,34 +51,24 @@ public class FuncPtg extends AbstractFunctionPtg{
//field_1_num_args = data[ offset + 0 ];
field_2_fnc_index = in.readShort();
/*
if (data.length - offset > 2) { //save left overs if there are any
leftOvers = new byte[2];
System.arraycopy(data, offset+1, leftOvers, 0, leftOvers.length);
FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByIndex(field_2_fnc_index);
if(fm == null) {
throw new RuntimeException("Invalid built-in function index (" + field_2_fnc_index + ")");
}
*/
try {
numParams = ( (Integer)functionData[field_2_fnc_index][2]).intValue();
} catch (NullPointerException npe) {
numParams=0;
}
numParams = fm.getMinParams();
}
public FuncPtg(int functionIndex, int numberOfParameters) {
field_2_fnc_index = (short) functionIndex;
numParams = numberOfParameters;
paramClass = new byte[] { Ptg.CLASS_VALUE, }; // TODO
}
public void writeBytes(byte[] array, int offset) {
public void writeBytes(byte[] array, int offset) {
array[offset+0]= (byte) (sid + ptgClass);
//array[offset+1]=field_1_num_args;
LittleEndian.putShort(array,offset+1,field_2_fnc_index);
/**if (leftOvers != null) {
System.arraycopy(leftOvers, 0, array, offset+2, leftOvers.length);
}**/
}
public int getNumberOfOperands() {
public int getNumberOfOperands() {
return numParams;
}
@ -94,13 +85,11 @@ public class FuncPtg extends AbstractFunctionPtg{
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer
.append("<FunctionPtg>").append("\n")
.append(" numArgs(internal)=").append(this.numParams).append("\n")
.append(" name =").append(lookupName(field_2_fnc_index)).append("\n")
.append(" field_2_fnc_index=").append(field_2_fnc_index).append("\n")
.append("</FunctionPtg>");
return buffer.toString();
StringBuffer sb = new StringBuffer(64);
sb.append(getClass().getName()).append(" [");
sb.append(lookupName(field_2_fnc_index));
sb.append(" nArgs=").append(numParams);
sb.append("]");
return sb.toString();
}
}

View File

@ -19,12 +19,14 @@
package org.apache.poi.hssf.record.formula;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.formula.function.FunctionMetadata;
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
/**
*
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class FuncVarPtg extends AbstractFunctionPtg{
public final class FuncVarPtg extends AbstractFunctionPtg{
public final static byte sid = 0x22;
private final static int SIZE = 4;
@ -47,10 +49,12 @@ public class FuncVarPtg extends AbstractFunctionPtg{
public FuncVarPtg(String pName, byte pNumOperands) {
field_1_num_args = pNumOperands;
field_2_fnc_index = lookupIndex(pName);
try{
returnClass = ( (Byte) functionData[field_2_fnc_index][0]).byteValue();
paramClass = (byte[]) functionData[field_2_fnc_index][1];
} catch (NullPointerException npe ) {
FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByIndex(field_2_fnc_index);
if(fm == null) {
// Happens only as a result of a call to FormulaParser.parse(), with a non-built-in function name
returnClass = Ptg.CLASS_VALUE;
paramClass = new byte[] {Ptg.CLASS_VALUE};
} else {
returnClass = Ptg.CLASS_VALUE;
paramClass = new byte[] {Ptg.CLASS_VALUE};
}
@ -79,15 +83,11 @@ public class FuncVarPtg extends AbstractFunctionPtg{
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer
.append("<FunctionVarPtg>").append("\n")
.append(" field_1_num_args=").append(field_1_num_args).append("\n")
.append(" name =").append(lookupName(field_2_fnc_index)).append("\n")
.append(" field_2_fnc_index=").append(field_2_fnc_index).append("\n")
.append("</FunctionPtg>");
return buffer.toString();
StringBuffer sb = new StringBuffer(64);
sb.append(getClass().getName()).append(" [");
sb.append(lookupName(field_2_fnc_index));
sb.append(" nArgs=").append(field_1_num_args);
sb.append("]");
return sb.toString();
}
}

View File

@ -0,0 +1,89 @@
/* ====================================================================
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.function;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Temporarily collects <tt>FunctionMetadata</tt> instances for creation of a
* <tt>FunctionMetadataRegistry</tt>.
*
* @author Josh Micich
*/
final class FunctionDataBuilder {
private int _maxFunctionIndex;
private final Map _functionDataByName;
private final Map _functionDataByIndex;
/** stores indexes of all functions with footnotes (i.e. whose definitions might change) */
private final Set _mutatingFunctionIndexes;
public FunctionDataBuilder(int sizeEstimate) {
_maxFunctionIndex = -1;
_functionDataByName = new HashMap(sizeEstimate * 3 / 2);
_functionDataByIndex = new HashMap(sizeEstimate * 3 / 2);
_mutatingFunctionIndexes = new HashSet();
}
public void add(int functionIndex, String functionName, int minParams, int maxParams, boolean hasFootnote) {
FunctionMetadata fm = new FunctionMetadata(functionIndex, functionName, minParams, maxParams);
Integer indexKey = new Integer(functionIndex);
if(functionIndex > _maxFunctionIndex) {
_maxFunctionIndex = functionIndex;
}
// allow function definitions to change only if both previous and the new items have footnotes
FunctionMetadata prevFM;
prevFM = (FunctionMetadata) _functionDataByName.get(functionName);
if(prevFM != null) {
if(!hasFootnote || !_mutatingFunctionIndexes.contains(indexKey)) {
throw new RuntimeException("Multiple entries for function name '" + functionName + "'");
}
_functionDataByIndex.remove(new Integer(prevFM.getIndex()));
}
prevFM = (FunctionMetadata) _functionDataByIndex.get(indexKey);
if(prevFM != null) {
if(!hasFootnote || !_mutatingFunctionIndexes.contains(indexKey)) {
throw new RuntimeException("Multiple entries for function index (" + functionIndex + ")");
}
_functionDataByName.remove(prevFM.getName());
}
if(hasFootnote) {
_mutatingFunctionIndexes.add(indexKey);
}
_functionDataByIndex.put(indexKey, fm);
_functionDataByName.put(functionName, fm);
}
public FunctionMetadataRegistry build() {
FunctionMetadata[] jumbledArray = new FunctionMetadata[_functionDataByName.size()];
_functionDataByName.values().toArray(jumbledArray);
FunctionMetadata[] fdIndexArray = new FunctionMetadata[_maxFunctionIndex+1];
for (int i = 0; i < jumbledArray.length; i++) {
FunctionMetadata fd = jumbledArray[i];
fdIndexArray[fd.getIndex()] = fd;
}
return new FunctionMetadataRegistry(fdIndexArray, _functionDataByName);
}
}

View File

@ -0,0 +1,58 @@
/* ====================================================================
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.function;
/**
*
* @author Josh Micich
*/
public final class FunctionMetadata {
private final int _index;
private final String _name;
private final int _minParams;
private final int _maxParams;
/* package */ FunctionMetadata(int index, String name, int minParams, int maxParams) {
_index = index;
_name = name;
_minParams = minParams;
_maxParams = maxParams;
}
public int getIndex() {
return _index;
}
public String getName() {
return _name;
}
public int getMinParams() {
return _minParams;
}
public int getMaxParams() {
return _maxParams;
}
public boolean hasFixedArgsLength() {
return _minParams == _maxParams;
}
public String toString() {
StringBuffer sb = new StringBuffer(64);
sb.append(getClass().getName()).append(" [");
sb.append(_index).append(" ").append(_name);
sb.append("]");
return sb.toString();
}
}

View File

@ -0,0 +1,129 @@
/* ====================================================================
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.function;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
/**
* Converts the text meta-data file into a <tt>FunctionMetadataRegistry</tt>
*
* @author Josh Micich
*/
final class FunctionMetadataReader {
private static final String METADATA_FILE_NAME = "functionMetadata.txt";
private static final Pattern TAB_DELIM_PATTERN = Pattern.compile("\t");
private static final String[] DIGIT_ENDING_FUNCTION_NAMES = {
// Digits at the end of a function might be due to a left-over footnote marker.
// except in these cases
"LOG10", "ATAN2", "DAYS360", "SUMXMY2", "SUMX2MY2", "SUMX2PY2",
};
private static final Set DIGIT_ENDING_FUNCTION_NAMES_SET = new HashSet(Arrays.asList(DIGIT_ENDING_FUNCTION_NAMES));
public static FunctionMetadataRegistry createRegistry() {
InputStream is = FunctionMetadataReader.class.getResourceAsStream(METADATA_FILE_NAME);
if(is == null) {
throw new RuntimeException("resource '" + METADATA_FILE_NAME + "' not found");
}
BufferedReader br = new BufferedReader(new InputStreamReader(is));
FunctionDataBuilder fdb = new FunctionDataBuilder(400);
try {
while (true) {
String line = br.readLine();
if (line == null) {
break;
}
if (line.length() < 1 || line.charAt(0) == '#') {
continue;
}
String trimLine = line.trim();
if (trimLine.length() < 1) {
continue;
}
processLine(fdb, line);
}
br.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
return fdb.build();
}
private static void processLine(FunctionDataBuilder fdb, String line) {
String[] parts = TAB_DELIM_PATTERN.split(line, -2);
if(parts.length != 8) {
throw new RuntimeException("Bad line format '" + line + "' - expected 8 data fields");
}
int functionIndex = parseInt(parts[0]);
String functionName = parts[1];
int minParams = parseInt(parts[2]);
int maxParams = parseInt(parts[3]);
// 4 returnClass
// 5 parameterClasses
// 6 isVolatile
boolean hasNote = parts[7].length() > 0;
validateFunctionName(functionName);
// TODO - make POI use returnClass, parameterClasses, isVolatile
fdb.add(functionIndex, functionName, minParams, maxParams, hasNote);
}
/**
* Makes sure that footnote digits from the original OOO document have not been accidentally
* left behind
*/
private static void validateFunctionName(String functionName) {
int len = functionName.length();
int ix = len - 1;
if (!Character.isDigit(functionName.charAt(ix))) {
return;
}
while(ix >= 0) {
if (!Character.isDigit(functionName.charAt(ix))) {
break;
}
ix--;
}
if(DIGIT_ENDING_FUNCTION_NAMES_SET.contains(functionName)) {
return;
}
throw new RuntimeException("Invalid function name '" + functionName
+ "' (is footnote number incorrectly appended)");
}
private static int parseInt(String valStr) {
try {
return Integer.parseInt(valStr);
} catch (NumberFormatException e) {
throw new RuntimeException("Value '" + valStr + "' could not be parsed as an integer");
}
}
}

View File

@ -0,0 +1,82 @@
/* ====================================================================
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.function;
import java.util.Map;
import java.util.Set;
public final class FunctionMetadataRegistry {
/**
* The name of the IF function (i.e. "IF"). Extracted as a constant for clarity.
*/
public static final String FUNCTION_NAME_IF = "IF";
public static final short FUNCTION_INDEX_EXTERNAL = 255;
private static FunctionMetadataRegistry _instance;
private final FunctionMetadata[] _functionDataByIndex;
private final Map _functionDataByName;
private static FunctionMetadataRegistry getInstance() {
if (_instance == null) {
_instance = FunctionMetadataReader.createRegistry();
// _instance = POIFunctionMetadataCreator.createInstance();
}
return _instance;
}
/* package */ FunctionMetadataRegistry(FunctionMetadata[] functionDataByIndex, Map functionDataByName) {
_functionDataByIndex = functionDataByIndex;
_functionDataByName = functionDataByName;
}
/* package */ Set getAllFunctionNames() {
return _functionDataByName.keySet();
}
public static FunctionMetadata getFunctionByIndex(int index) {
return getInstance().getFunctionByIndexInternal(index);
}
private FunctionMetadata getFunctionByIndexInternal(int index) {
return _functionDataByIndex[index];
}
/**
* Resolves a built-in function index.
* @param name uppercase function name
* @return a negative value if the function name is not found.
* This typically occurs for external functions.
*/
public static short lookupIndexByName(String name) {
FunctionMetadata fd = getInstance().getFunctionByNameInternal(name);
if (fd == null) {
return -1;
}
return (short) fd.getIndex();
}
private FunctionMetadata getFunctionByNameInternal(String name) {
return (FunctionMetadata) _functionDataByName.get(name);
}
public static FunctionMetadata getFunctionByName(String name) {
return getInstance().getFunctionByNameInternal(name);
}
}

View File

@ -0,0 +1,283 @@
# 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.
# Created by (org.apache.poi.hssf.record.formula.function.ExcelFileFormatDocFunctionExtractor)
# from source file 'excelfileformat.odt' (size=355750, crc=0x2FAEA65A)
#
#Columns: (index, name, minParams, maxParams, returnClass, paramClasses, isVolatile, hasFootnote )
# Built-In Sheet Functions in BIFF2
0 COUNT 0 30 V R
1 IF 2 3 R V R R
2 ISNA 1 1 V V
3 ISERROR 1 1 V V
4 SUM 0 30 V R
5 AVERAGE 1 30 V R
6 MIN 1 30 V R
7 MAX 1 30 V R
8 ROW 0 1 V R
9 COLUMN 0 1 V R
10 NA 0 0 V
11 NPV 2 30 V V R
12 STDEV 1 30 V R
13 DOLLAR 1 2 V V V
14 FIXED 2 2 V V V x
15 SIN 1 1 V V
16 COS 1 1 V V
17 TAN 1 1 V V
18 ARCTAN 1 1 V V
19 PI 0 0 V
20 SQRT 1 1 V V
21 EXP 1 1 V V
22 LN 1 1 V V
23 LOG10 1 1 V V
24 ABS 1 1 V V
25 INT 1 1 V V
26 SIGN 1 1 V V
27 ROUND 2 2 V V V
28 LOOKUP 2 3 V V R R
29 INDEX 2 4 R R V V V
30 REPT 2 2 V V V
31 MID 3 3 V V V V
32 LEN 1 1 V V
33 VALUE 1 1 V V
34 TRUE 0 0 V
35 FALSE 0 0 V
36 AND 1 30 V R
37 OR 1 30 V R
38 NOT 1 1 V V
39 MOD 2 2 V V V
40 DCOUNT 3 3 V R R R
41 DSUM 3 3 V R R R
42 DAVERAGE 3 3 V R R R
43 DMIN 3 3 V R R R
44 DMAX 3 3 V R R R
45 DSTDEV 3 3 V R R R
46 VAR 1 30 V R
47 DVAR 3 3 V R R R
48 TEXT 2 2 V V V
49 LINEST 1 2 A R R x
50 TREND 1 3 A R R R x
51 LOGEST 1 2 A R R x
52 GROWTH 1 3 A R R R x
56 PV 3 5 V V V V V V
# Built-In Sheet Functions in BIFF2
57 FV 3 5 V V V V V V
58 NPER 3 5 V V V V V V
59 PMT 3 5 V V V V V V
60 RATE 3 6 V V V V V V V
61 MIRR 3 3 V R V V
62 IRR 1 2 V R V
63 RAND 0 0 V x
64 MATCH 2 3 V V R R
65 DATE 3 3 V V V V
66 TIME 3 3 V V V V
67 DAY 1 1 V V
68 MONTH 1 1 V V
69 YEAR 1 1 V V
70 WEEKDAY 1 1 V V x
71 HOUR 1 1 V V
72 MINUTE 1 1 V V
73 SECOND 1 1 V V
74 NOW 0 0 V x
75 AREAS 1 1 V R
76 ROWS 1 1 V R
77 COLUMNS 1 1 V R
78 OFFSET 3 5 R R V V V V x
82 SEARCH 2 3 V V V V
83 TRANSPOSE 1 1 A A
86 TYPE 1 1 V V
97 ATAN2 2 2 V V V
98 ASIN 1 1 V V
99 ACOS 1 1 V V
100 CHOOSE 2 30 R V R
101 HLOOKUP 3 3 V V R R x
102 VLOOKUP 3 3 V V R R x
105 ISREF 1 1 V R
109 LOG 1 2 V V V
111 CHAR 1 1 V V
112 LOWER 1 1 V V
113 UPPER 1 1 V V
114 PROPER 1 1 V V
115 LEFT 1 2 V V V
116 RIGHT 1 2 V V V
117 EXACT 2 2 V V V
118 TRIM 1 1 V V
119 REPLACE 4 4 V V V V V
120 SUBSTITUTE 3 4 V V V V V
121 CODE 1 1 V V
124 FIND 2 3 V V V V
125 CELL 1 2 V V R x
126 ISERR 1 1 V V
127 ISTEXT 1 1 V V
128 ISNUMBER 1 1 V V
129 ISBLANK 1 1 V V
130 T 1 1 V R
131 N 1 1 V R
140 DATEVALUE 1 1 V V
141 TIMEVALUE 1 1 V V
142 SLN 3 3 V V V V
143 SYD 4 4 V V V V V
144 DDB 4 5 V V V V V V
148 INDIRECT 1 2 R V V x
162 CLEAN 1 1 V V
163 MDETERM 1 1 V A
164 MINVERSE 1 1 A A
165 MMULT 2 2 A A A
167 IPMT 4 6 V V V V V V V
168 PPMT 4 6 V V V V V V V
169 COUNTA 0 30 V R
183 PRODUCT 0 30 V R
184 FACT 1 1 V V
191 DPRODUCT 3 3 V R R R
192 ISNONTEXT 1 1 V V
193 STDEVP 1 30 V R
194 VARP 1 30 V R
195 DSTDEVP 3 3 V R R R
196 DVARP 3 3 V R R R
197 TRUNC 1 1 V V x
198 ISLOGICAL 1 1 V V
199 DCOUNTA 3 3 V R R R
# New Built-In Sheet Functions in BIFF3
49 LINEST 1 4 A R R V V x
50 TREND 1 4 A R R R V x
51 LOGEST 1 4 A R R V V x
52 GROWTH 1 4 A R R R V x
197 TRUNC 1 2 V V V x
204 YEN 1 2 V V V x
205 FINDB 2 3 V V V V
206 SEARCHB 2 3 V V V V
207 REPLACEB 4 4 V V V V V
208 LEFTB 1 2 V V V
209 RIGHTB 1 2 V V V
210 MIDB 3 3 V V V V
211 LENB 1 1 V V
212 ROUNDUP 2 2 V V V
213 ROUNDDOWN 2 2 V V V
214 ASC 1 1 V V
215 JIS 1 1 V V x
219 ADDRESS 2 5 V V V V V V
220 DAYS360 2 2 V V V x
221 TODAY 0 0 V x
222 VDB 5 7 V V V V V V V V
227 MEDIAN 1 30 V R …
228 SUMPRODUCT 1 30 V A …
229 SINH 1 1 V V
230 COSH 1 1 V V
231 TANH 1 1 V V
232 ASINH 1 1 V V
233 ACOSH 1 1 V V
234 ATANH 1 1 V V
235 DGET 3 3 V R R R
244 INFO 1 1 V V
# New Built-In Sheet Functions in BIFF4
14 FIXED 2 3 V V V V x
216 RANK 2 3 V V R V
247 DB 4 5 V V V V V V
252 FREQUENCY 2 2 A R R
261 ERROR.TYPE 1 1 V V
269 AVEDEV 1 30 V R …
270 BETADIST 3 5 V V V V V V
271 GAMMALN 1 1 V V
272 BETAINV 3 5 V V V V V V
273 BINOMDIST 4 4 V V V V V
274 CHIDIST 2 2 V V V
275 CHIINV 2 2 V V V
276 COMBIN 2 2 V V V
277 CONFIDENCE 3 3 V V V V
278 CRITBINOM 3 3 V V V V
279 EVEN 1 1 V V
280 EXPONDIST 3 3 V V V V
281 FDIST 3 3 V V V V
282 FINV 3 3 V V V V
283 FISHER 1 1 V V
284 FISHERINV 1 1 V V
285 FLOOR 2 2 V V V
286 GAMMADIST 4 4 V V V V V
287 GAMMAINV 3 3 V V V V
288 CEILING 2 2 V V V
289 HYPGEOMDIST 4 4 V V V V V
290 LOGNORMDIST 3 3 V V V V
291 LOGINV 3 3 V V V V
292 NEGBINOMDIST 3 3 V V V V
293 NORMDIST 4 4 V V V V V
294 NORMSDIST 1 1 V V
295 NORMINV 3 3 V V V V
296 NORMSINV 1 1 V V
297 STANDARDIZE 3 3 V V V V
298 ODD 1 1 V V
299 PERMUT 2 2 V V V
300 POISSON 3 3 V V V V
301 TDIST 3 3 V V V V
302 WEIBULL 4 4 V V V V V
303 SUMXMY2 2 2 V A A
304 SUMX2MY2 2 2 V A A
305 SUMX2PY2 2 2 V A A
306 CHITEST 2 2 V A A
307 CORREL 2 2 V A A
308 COVAR 2 2 V A A
309 FORECAST 3 3 V V A A
310 FTEST 2 2 V A A
311 INTERCEPT 2 2 V A A
312 PEARSON 2 2 V A A
313 RSQ 2 2 V A A
314 STEYX 2 2 V A A
315 SLOPE 2 2 V A A
316 TTEST 4 4 V A A V V
317 PROB 3 4 V A A V V
318 DEVSQ 1 30 V R …
319 GEOMEAN 1 30 V R …
320 HARMEAN 1 30 V R …
321 SUMSQ 0 30 V R …
322 KURT 1 30 V R …
323 SKEW 1 30 V R …
324 ZTEST 2 3 V R V V
325 LARGE 2 2 V R V
326 SMALL 2 2 V R V
327 QUARTILE 2 2 V R V
328 PERCENTILE 2 2 V R V
329 PERCENTRANK 2 3 V R V V
330 MODE 1 30 V A
331 TRIMMEAN 2 2 V R V
332 TINV 2 2 V V V
# New Built-In Sheet Functions in BIFF5
70 WEEKDAY 1 2 V V V x
101 HLOOKUP 3 4 V V R R V x
102 VLOOKUP 3 4 V V R R V x
220 DAYS360 2 3 V V V V x
336 CONCATENATE 0 30 V V
337 POWER 2 2 V V V
342 RADIANS 1 1 V V
343 DEGREES 1 1 V V
344 SUBTOTAL 2 30 V V R
345 SUMIF 2 3 V R V R
346 COUNTIF 2 2 V R V
347 COUNTBLANK 1 1 V R
350 ISPMT 4 4 V V V V V
351 DATEDIF 3 3 V V V V
352 DATESTRING 1 1 V V
353 NUMBERSTRING 2 2 V V V
354 ROMAN 1 2 V V V
# New Built-In Sheet Functions in BIFF8
358 GETPIVOTDATA 2 30
359 HYPERLINK 1 2 V V V
360 PHONETIC 1 1 V R
361 AVERAGEA 1 30 V R …
362 MAXA 1 30 V R …
363 MINA 1 30 V R …
364 STDEVPA 1 30 V R …
365 VARPA 1 30 V R …
366 STDEVA 1 30 V R …
367 VARA 1 30 V R …

View File

@ -0,0 +1,287 @@
# 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.
# Created by (org.apache.poi.hssf.record.formula.function.ExcelFileFormatDocFunctionExtractor)
# from source file 'excelfileformat.odt' (size=355750, crc=0x2FAEA65A)
#
#Columns: (index, name, minParams, maxParams, returnClass, paramClasses, isVolatile, hasFootnote )
#
# + some manual edits !
# Built-In Sheet Functions in BIFF2
0 COUNT 0 30 V R
1 IF 2 3 R V R R
2 ISNA 1 1 V V
3 ISERROR 1 1 V V
4 SUM 0 30 V R
5 AVERAGE 1 30 V R
6 MIN 1 30 V R
7 MAX 1 30 V R
8 ROW 0 1 V R
9 COLUMN 0 1 V R
10 NA 0 0 V
11 NPV 2 30 V V R
12 STDEV 1 30 V R
13 DOLLAR 1 2 V V V
14 FIXED 2 2 V V V x
15 SIN 1 1 V V
16 COS 1 1 V V
17 TAN 1 1 V V
18 ATAN 1 1 V V
19 PI 0 0 V
20 SQRT 1 1 V V
21 EXP 1 1 V V
22 LN 1 1 V V
23 LOG10 1 1 V V
24 ABS 1 1 V V
25 INT 1 1 V V
26 SIGN 1 1 V V
27 ROUND 2 2 V V V
28 LOOKUP 2 3 V V R R
29 INDEX 2 4 R R V V V
30 REPT 2 2 V V V
31 MID 3 3 V V V V
32 LEN 1 1 V V
33 VALUE 1 1 V V
34 TRUE 0 0 V
35 FALSE 0 0 V
36 AND 1 30 V R
37 OR 1 30 V R
38 NOT 1 1 V V
39 MOD 2 2 V V V
40 DCOUNT 3 3 V R R R
41 DSUM 3 3 V R R R
42 DAVERAGE 3 3 V R R R
43 DMIN 3 3 V R R R
44 DMAX 3 3 V R R R
45 DSTDEV 3 3 V R R R
46 VAR 1 30 V R
47 DVAR 3 3 V R R R
48 TEXT 2 2 V V V
49 LINEST 1 2 A R R x
50 TREND 1 3 A R R R x
51 LOGEST 1 2 A R R x
52 GROWTH 1 3 A R R R x
56 PV 3 5 V V V V V V
# Built-In Sheet Functions in BIFF2
57 FV 3 5 V V V V V V
58 NPER 3 5 V V V V V V
59 PMT 3 5 V V V V V V
60 RATE 3 6 V V V V V V V
61 MIRR 3 3 V R V V
62 IRR 1 2 V R V
63 RAND 0 0 V x
64 MATCH 2 3 V V R R
65 DATE 3 3 V V V V
66 TIME 3 3 V V V V
67 DAY 1 1 V V
68 MONTH 1 1 V V
69 YEAR 1 1 V V
70 WEEKDAY 1 1 V V x
71 HOUR 1 1 V V
72 MINUTE 1 1 V V
73 SECOND 1 1 V V
74 NOW 0 0 V x
75 AREAS 1 1 V R
76 ROWS 1 1 V R
77 COLUMNS 1 1 V R
78 OFFSET 3 5 R R V V V V x
82 SEARCH 2 3 V V V V
83 TRANSPOSE 1 1 A A
86 TYPE 1 1 V V
97 ATAN2 2 2 V V V
98 ASIN 1 1 V V
99 ACOS 1 1 V V
100 CHOOSE 2 30 R V R
101 HLOOKUP 3 3 V V R R x
102 VLOOKUP 3 3 V V R R x
105 ISREF 1 1 V R
109 LOG 1 2 V V V
111 CHAR 1 1 V V
112 LOWER 1 1 V V
113 UPPER 1 1 V V
114 PROPER 1 1 V V
115 LEFT 1 2 V V V
116 RIGHT 1 2 V V V
117 EXACT 2 2 V V V
118 TRIM 1 1 V V
119 REPLACE 4 4 V V V V V
120 SUBSTITUTE 3 4 V V V V V
121 CODE 1 1 V V
124 FIND 2 3 V V V V
125 CELL 1 2 V V R x
126 ISERR 1 1 V V
127 ISTEXT 1 1 V V
128 ISNUMBER 1 1 V V
129 ISBLANK 1 1 V V
130 T 1 1 V R
131 N 1 1 V R
140 DATEVALUE 1 1 V V
141 TIMEVALUE 1 1 V V
142 SLN 3 3 V V V V
143 SYD 4 4 V V V V V
144 DDB 4 5 V V V V V V
148 INDIRECT 1 2 R V V x
162 CLEAN 1 1 V V
163 MDETERM 1 1 V A
164 MINVERSE 1 1 A A
165 MMULT 2 2 A A A
167 IPMT 4 6 V V V V V V V
168 PPMT 4 6 V V V V V V V
169 COUNTA 0 30 V R
183 PRODUCT 0 30 V R
184 FACT 1 1 V V
190 ISNONTEXT 1 1 V V
191 DPRODUCT 3 3 V R R R
193 STDEVP 1 30 V R
194 VARP 1 30 V R
195 DSTDEVP 3 3 V R R R
196 DVARP 3 3 V R R R
197 TRUNC 1 1 V V x
198 ISLOGICAL 1 1 V V
199 DCOUNTA 3 3 V R R R
# New Built-In Sheet Functions in BIFF3
49 LINEST 1 4 A R R V V x
50 TREND 1 4 A R R R V x
51 LOGEST 1 4 A R R V V x
52 GROWTH 1 4 A R R R V x
197 TRUNC 1 2 V V V x
204 YEN 1 2 V V V x
205 FINDB 2 3 V V V V
206 SEARCHB 2 3 V V V V
207 REPLACEB 4 4 V V V V V
208 LEFTB 1 2 V V V
209 RIGHTB 1 2 V V V
210 MIDB 3 3 V V V V
211 LENB 1 1 V V
212 ROUNDUP 2 2 V V V
213 ROUNDDOWN 2 2 V V V
214 ASC 1 1 V V
215 JIS 1 1 V V x
219 ADDRESS 2 5 V V V V V V
220 DAYS360 2 2 V V V x
221 TODAY 0 0 V x
222 VDB 5 7 V V V V V V V V
227 MEDIAN 1 30 V R …
228 SUMPRODUCT 1 30 V A …
229 SINH 1 1 V V
230 COSH 1 1 V V
231 TANH 1 1 V V
232 ASINH 1 1 V V
233 ACOSH 1 1 V V
234 ATANH 1 1 V V
235 DGET 3 3 V R R R
244 INFO 1 1 V V
# New Built-In Sheet Functions in BIFF4
14 FIXED 2 3 V V V V x
204 USDOLLAR 1 1 V V x
215 DBCS 1 1 V V x
216 RANK 2 3 V V R V
247 DB 4 5 V V V V V V
252 FREQUENCY 2 2 A R R
261 ERROR.TYPE 1 1 V V
269 AVEDEV 1 30 V R …
270 BETADIST 3 5 V V V V V V
271 GAMMALN 1 1 V V
272 BETAINV 3 5 V V V V V V
273 BINOMDIST 4 4 V V V V V
274 CHIDIST 2 2 V V V
275 CHIINV 2 2 V V V
276 COMBIN 2 2 V V V
277 CONFIDENCE 3 3 V V V V
278 CRITBINOM 3 3 V V V V
279 EVEN 1 1 V V
280 EXPONDIST 3 3 V V V V
281 FDIST 3 3 V V V V
282 FINV 3 3 V V V V
283 FISHER 1 1 V V
284 FISHERINV 1 1 V V
285 FLOOR 2 2 V V V
286 GAMMADIST 4 4 V V V V V
287 GAMMAINV 3 3 V V V V
288 CEILING 2 2 V V V
289 HYPGEOMDIST 4 4 V V V V V
290 LOGNORMDIST 3 3 V V V V
291 LOGINV 3 3 V V V V
292 NEGBINOMDIST 3 3 V V V V
293 NORMDIST 4 4 V V V V V
294 NORMSDIST 1 1 V V
295 NORMINV 3 3 V V V V
296 NORMSINV 1 1 V V
297 STANDARDIZE 3 3 V V V V
298 ODD 1 1 V V
299 PERMUT 2 2 V V V
300 POISSON 3 3 V V V V
301 TDIST 3 3 V V V V
302 WEIBULL 4 4 V V V V V
303 SUMXMY2 2 2 V A A
304 SUMX2MY2 2 2 V A A
305 SUMX2PY2 2 2 V A A
306 CHITEST 2 2 V A A
307 CORREL 2 2 V A A
308 COVAR 2 2 V A A
309 FORECAST 3 3 V V A A
310 FTEST 2 2 V A A
311 INTERCEPT 2 2 V A A
312 PEARSON 2 2 V A A
313 RSQ 2 2 V A A
314 STEYX 2 2 V A A
315 SLOPE 2 2 V A A
316 TTEST 4 4 V A A V V
317 PROB 3 4 V A A V V
318 DEVSQ 1 30 V R …
319 GEOMEAN 1 30 V R …
320 HARMEAN 1 30 V R …
321 SUMSQ 0 30 V R …
322 KURT 1 30 V R …
323 SKEW 1 30 V R …
324 ZTEST 2 3 V R V V
325 LARGE 2 2 V R V
326 SMALL 2 2 V R V
327 QUARTILE 2 2 V R V
328 PERCENTILE 2 2 V R V
329 PERCENTRANK 2 3 V R V V
330 MODE 1 30 V A
331 TRIMMEAN 2 2 V R V
332 TINV 2 2 V V V
# New Built-In Sheet Functions in BIFF5
70 WEEKDAY 1 2 V V V x
101 HLOOKUP 3 4 V V R R V x
102 VLOOKUP 3 4 V V R R V x
220 DAYS360 2 3 V V V V x
336 CONCATENATE 0 30 V V
337 POWER 2 2 V V V
342 RADIANS 1 1 V V
343 DEGREES 1 1 V V
344 SUBTOTAL 2 30 V V R
345 SUMIF 2 3 V R V R
346 COUNTIF 2 2 V R V
347 COUNTBLANK 1 1 V R
350 ISPMT 4 4 V V V V V
351 DATEDIF 3 3 V V V V
352 DATESTRING 1 1 V V
353 NUMBERSTRING 2 2 V V V
354 ROMAN 1 2 V V V
# New Built-In Sheet Functions in BIFF8
358 GETPIVOTDATA 2 30
359 HYPERLINK 1 2 V V V
360 PHONETIC 1 1 V R
361 AVERAGEA 1 30 V R …
362 MAXA 1 30 V R …
363 MINA 1 30 V R …
364 STDEVPA 1 30 V R …
365 VARPA 1 30 V R …
366 STDEVA 1 30 V R …
367 VARA 1 30 V R …

View File

@ -293,7 +293,7 @@ public final class TestFormulaParser extends TestCase {
assertEquals("FOO", tname.toFormulaString(w));
AbstractFunctionPtg tfunc = (AbstractFunctionPtg) ptg[1];
assertEquals("externalflag", tfunc.getName());
assertTrue(tfunc.isExternalFunction());
}
public void testEmbeddedSlash() {
@ -888,4 +888,17 @@ public final class TestFormulaParser extends TestCase {
assertTrue(e.getMessage().startsWith("Too few arguments suppled to operation token"));
}
}
public void testFuncPtgSelection() {
Workbook book = Workbook.createWorkbook();
Ptg[] ptgs;
ptgs = FormulaParser.parse("countif(A1:A2, 1)", book);
assertEquals(3, ptgs.length);
if(FuncVarPtg.class == ptgs[2].getClass()) {
throw new AssertionFailedError("Identified bug 44675");
}
assertEquals(FuncPtg.class, ptgs[2].getClass());
ptgs = FormulaParser.parse("sin(1)", book);
assertEquals(2, ptgs.length);
assertEquals(FuncPtg.class, ptgs[1].getClass());
}
}

View File

@ -17,6 +17,8 @@
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.record.formula.function.AllFormulaFunctionTests;
import junit.framework.Test;
import junit.framework.TestSuite;
@ -28,12 +30,12 @@ import junit.framework.TestSuite;
public class AllFormulaTests {
public static Test suite() {
TestSuite result = new TestSuite("Tests for org.apache.poi.hssf.record.formula");
TestSuite result = new TestSuite(AllFormulaTests.class.getName());
result.addTestSuite(TestArea3DPtg.class);
result.addTestSuite(TestAreaErrPtg.class);
result.addTestSuite(TestAreaPtg.class);
result.addTestSuite(TestErrPtg.class);
result.addTestSuite(TestExternalFunctionFormulas.class);
result.addTestSuite(TestAreaPtg.class);
result.addTestSuite(TestErrPtg.class);
result.addTestSuite(TestExternalFunctionFormulas.class);
result.addTestSuite(TestFuncPtg.class);
result.addTestSuite(TestIntersectionPtg.class);
result.addTestSuite(TestPercentPtg.class);
@ -42,6 +44,7 @@ public class AllFormulaTests {
result.addTestSuite(TestReferencePtg.class);
result.addTestSuite(TestSheetNameFormatter.class);
result.addTestSuite(TestUnionPtg.class);
result.addTest(AllFormulaFunctionTests.suite());
return result;
}
}

View File

@ -0,0 +1,37 @@
/* ====================================================================
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.function;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Collects all tests for this package.
*
* @author Josh Micich
*/
public class AllFormulaFunctionTests {
public static Test suite() {
TestSuite result = new TestSuite(AllFormulaFunctionTests.class.getName());
result.addTestSuite(TestFunctionMetadataRegistry.class);
result.addTestSuite(TestParseMissingBuiltInFuncs.class);
result.addTestSuite(TestReadMissingBuiltInFuncs.class);
return result;
}
}

View File

@ -0,0 +1,503 @@
/* ====================================================================
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.function;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.zip.CRC32;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* This class is not used during normal POI run-time but is used at development time to generate
* the file 'functionMetadata.txt'. There are more than 300 built-in functions in Excel and the
* intention of this class is to make it easier to maintain the metadata, by extracting it from
* a reliable source.
*
* @author Josh Micich
*/
public class ExcelFileFormatDocFunctionExtractor {
private static final String SOURCE_DOC_FILE_NAME = "excelfileformat.odt";
private static final class FunctionData {
private final int _index;
private final boolean _hasFootnote;
private final String _name;
private final int _minParams;
private final int _maxParams;
private final String _returnClass;
private final String _paramClasses;
private final boolean _isVolatile;
public FunctionData(int funcIx, boolean hasFootnote, String funcName, int minParams, int maxParams,
String returnClass, String paramClasses, boolean isVolatile) {
_index = funcIx;
_hasFootnote = hasFootnote;
_name = funcName;
_minParams = minParams;
_maxParams = maxParams;
_returnClass = returnClass;
_paramClasses = paramClasses;
_isVolatile = isVolatile;
}
public int getIndex() {
return _index;
}
public String getName() {
return _name;
}
public boolean hasFootnote() {
return _hasFootnote;
}
public String formatAsDataLine() {
return _index + "\t" + _name + "\t" + _minParams + "\t"
+ _maxParams + "\t" + _returnClass + "\t" + _paramClasses
+ "\t" + checkMark(_isVolatile) + "\t" + checkMark(_hasFootnote);
}
private static String checkMark(boolean b) {
return b ? "x" : "";
}
}
private static final class FunctionDataCollector {
private final Map _allFunctionsByIndex;
private final Map _allFunctionsByName;
private final Set _groupFunctionIndexes;
private final Set _groupFunctionNames;
private final PrintStream _ps;
public FunctionDataCollector(PrintStream ps) {
_ps = ps;
_allFunctionsByIndex = new HashMap();
_allFunctionsByName = new HashMap();
_groupFunctionIndexes = new HashSet();
_groupFunctionNames = new HashSet();
}
public void addFuntion(int funcIx, boolean hasFootnote, String funcName, int minParams, int maxParams,
String returnClass, String paramClasses, String volatileFlagStr) {
boolean isVolatile = volatileFlagStr.length() > 0;
Integer funcIxKey = new Integer(funcIx);
if(!_groupFunctionIndexes.add(funcIxKey)) {
throw new RuntimeException("Duplicate function index (" + funcIx + ")");
}
if(!_groupFunctionNames.add(funcName)) {
throw new RuntimeException("Duplicate function name '" + funcName + "'");
}
checkRedefinedFunction(hasFootnote, funcName, funcIxKey);
FunctionData fd = new FunctionData(funcIx, hasFootnote, funcName,
minParams, maxParams, returnClass, paramClasses, isVolatile);
_allFunctionsByIndex.put(funcIxKey, fd);
_allFunctionsByName.put(funcName, fd);
}
private void checkRedefinedFunction(boolean hasNote, String funcName, Integer funcIxKey) {
FunctionData fdPrev;
fdPrev = (FunctionData) _allFunctionsByIndex.get(funcIxKey);
if(fdPrev != null) {
if(fdPrev.hasFootnote() && hasNote) {
// func def can change if both have a foot-note
_allFunctionsByName.remove(fdPrev.getName());
} else {
throw new RuntimeException("changing function definition without foot-note");
}
}
fdPrev = (FunctionData) _allFunctionsByName.get(funcName);
if(fdPrev != null) {
if(fdPrev.hasFootnote() && hasNote) {
// func def can change if both have a foot-note
_allFunctionsByIndex.remove(new Integer(fdPrev.getIndex()));
} else {
throw new RuntimeException("changing function definition without foot-note");
}
}
}
public void endTableGroup(String headingText) {
Integer[] keys = new Integer[_groupFunctionIndexes.size()];
_groupFunctionIndexes.toArray(keys);
_groupFunctionIndexes.clear();
_groupFunctionNames.clear();
Arrays.sort(keys);
_ps.println("# " + headingText);
for (int i = 0; i < keys.length; i++) {
FunctionData fd = (FunctionData) _allFunctionsByIndex.get(keys[i]);
_ps.println(fd.formatAsDataLine());
}
}
}
/**
* To avoid drag-in - parse XML using only JDK.
*/
private static class EFFDocHandler implements ContentHandler {
private static final String[] HEADING_PATH_NAMES = {
"office:document-content", "office:body", "office:text", "text:h",
};
private static final String[] TABLE_BASE_PATH_NAMES = {
"office:document-content", "office:body", "office:text", "table:table",
};
private static final String[] TABLE_ROW_RELPATH_NAMES = {
"table:table-row",
};
private static final String[] TABLE_CELL_RELPATH_NAMES = {
"table:table-row", "table:table-cell", "text:p",
};
private static final String[] NOTE_REF_RELPATH_NAMES = {
"table:table-row", "table:table-cell", "text:p", "text:span", "text:note-ref",
};
private final Stack _elemNameStack;
/** <code>true</code> only when parsing the target tables */
private boolean _isInsideTable;
private final List _rowData;
private final StringBuffer _textNodeBuffer;
private final List _rowNoteFlags;
private boolean _cellHasNote;
private final FunctionDataCollector _fdc;
private String _lastHeadingText;
public EFFDocHandler(FunctionDataCollector fdc) {
_fdc = fdc;
_elemNameStack = new Stack();
_isInsideTable = false;
_rowData = new ArrayList();
_textNodeBuffer = new StringBuffer();
_rowNoteFlags = new ArrayList();
}
private boolean matchesTargetPath() {
return matchesPath(0, TABLE_BASE_PATH_NAMES);
}
private boolean matchesRelPath(String[] pathNames) {
return matchesPath(TABLE_BASE_PATH_NAMES.length, pathNames);
}
private boolean matchesPath(int baseStackIndex, String[] pathNames) {
if(_elemNameStack.size() != baseStackIndex + pathNames.length) {
return false;
}
for (int i = 0; i < pathNames.length; i++) {
if(!_elemNameStack.get(baseStackIndex + i).equals(pathNames[i])) {
return false;
}
}
return true;
}
public void characters(char[] ch, int start, int length) {
// only 2 text nodes where text is collected:
if(matchesRelPath(TABLE_CELL_RELPATH_NAMES) || matchesPath(0, HEADING_PATH_NAMES)) {
_textNodeBuffer.append(ch, start, length);
}
}
public void endElement(String namespaceURI, String localName, String name) {
String expectedName = (String) _elemNameStack.peek();
if(expectedName != name) {
throw new RuntimeException("close tag mismatch");
}
if(matchesPath(0, HEADING_PATH_NAMES)) {
_lastHeadingText = _textNodeBuffer.toString().trim();
_textNodeBuffer.setLength(0);
}
if(_isInsideTable) {
if(matchesTargetPath()) {
_fdc.endTableGroup(_lastHeadingText);
_isInsideTable = false;
} else if(matchesRelPath(TABLE_ROW_RELPATH_NAMES)) {
String[] cellData = new String[_rowData.size()];
_rowData.toArray(cellData);
_rowData.clear();
Boolean[] noteFlags = new Boolean[_rowNoteFlags.size()];
_rowNoteFlags.toArray(noteFlags);
_rowNoteFlags.clear();
processTableRow(cellData, noteFlags);
} else if(matchesRelPath(TABLE_CELL_RELPATH_NAMES)) {
_rowData.add(_textNodeBuffer.toString().trim());
_rowNoteFlags.add(Boolean.valueOf(_cellHasNote));
_textNodeBuffer.setLength(0);
}
}
_elemNameStack.pop();
}
private void processTableRow(String[] cellData, Boolean[] noteFlags) {
// each table row of the document contains data for two functions
if(cellData.length != 15) {
throw new RuntimeException("Bad table row size");
}
processFunction(cellData, noteFlags, 0);
processFunction(cellData, noteFlags, 8);
}
public void processFunction(String[] cellData, Boolean[] noteFlags, int i) {
String funcIxStr = cellData[i + 0];
if (funcIxStr.length() < 1) {
// empty (happens on the right hand side when there is an odd number of functions)
return;
}
int funcIx = parseInt(funcIxStr);
boolean hasFootnote = noteFlags[i + 1].booleanValue();
String funcName = cellData[i + 1];
int minParams = parseInt(cellData[i + 2]);
int maxParams = parseInt(cellData[i + 3]);
String returnClass = cellData[i + 4];
String paramClasses = cellData[i + 5];
String volatileFlagStr = cellData[i + 6];
_fdc.addFuntion(funcIx, hasFootnote, funcName, minParams, maxParams, returnClass, paramClasses, volatileFlagStr);
}
private static int parseInt(String valStr) {
try {
return Integer.parseInt(valStr);
} catch (NumberFormatException e) {
throw new RuntimeException("Value '" + valStr + "' could not be parsed as an integer");
}
}
public void startElement(String namespaceURI, String localName, String name, Attributes atts) {
_elemNameStack.add(name);
if(matchesTargetPath()) {
String tableName = atts.getValue("table:name");
if(tableName.startsWith("tab_fml_func") && !tableName.equals("tab_fml_func0")) {
_isInsideTable = true;
}
return;
}
if(matchesPath(0, HEADING_PATH_NAMES)) {
_textNodeBuffer.setLength(0);
} else if(matchesRelPath(TABLE_ROW_RELPATH_NAMES)) {
_rowData.clear();
_rowNoteFlags.clear();
} else if(matchesRelPath(TABLE_CELL_RELPATH_NAMES)) {
_textNodeBuffer.setLength(0);
_cellHasNote = false;
} else if(matchesRelPath(NOTE_REF_RELPATH_NAMES)) {
_cellHasNote = true;
}
}
public void endDocument() {
// do nothing
}
public void endPrefixMapping(String prefix) {
// do nothing
}
public void ignorableWhitespace(char[] ch, int start, int length) {
// do nothing
}
public void processingInstruction(String target, String data) {
// do nothing
}
public void setDocumentLocator(Locator locator) {
// do nothing
}
public void skippedEntity(String name) {
// do nothing
}
public void startDocument() {
// do nothing
}
public void startPrefixMapping(String prefix, String uri) {
// do nothing
}
}
private static void extractFunctionData(FunctionDataCollector fdc, InputStream is) {
System.setProperty("org.xml.sax.driver", "org.apache.crimson.parser.XMLReaderImpl");
XMLReader xr;
try {
xr = XMLReaderFactory.createXMLReader();
} catch (SAXException e) {
throw new RuntimeException(e);
}
xr.setContentHandler(new EFFDocHandler(fdc));
InputSource inSrc = new InputSource(is);
try {
xr.parse(inSrc);
is.close();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (SAXException e) {
throw new RuntimeException(e);
}
}
private static void processFile(File effDocFile, File outFile) {
OutputStream os;
try {
os = new FileOutputStream(outFile);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
PrintStream ps = new PrintStream(os);
outputLicenseHeader(ps);
Class genClass = ExcelFileFormatDocFunctionExtractor.class;
ps.println("# Created by (" + genClass.getName() + ")");
// identify the source file
ps.print("# from source file '" + SOURCE_DOC_FILE_NAME + "'");
ps.println(" (size=" + effDocFile.length() + ", crc=" + getFileCRC(effDocFile) + ")");
ps.println("#");
ps.println("#Columns: (index, name, minParams, maxParams, returnClass, paramClasses, isVolatile, hasFootnote )");
ps.println("");
try {
ZipFile zf = new ZipFile(effDocFile);
InputStream is = zf.getInputStream(zf.getEntry("content.xml"));
extractFunctionData(new FunctionDataCollector(ps), is);
zf.close();
} catch (ZipException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
ps.close();
}
private static void outputLicenseHeader(PrintStream ps) {
String[] lines= {
"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.",
};
for (int i = 0; i < lines.length; i++) {
ps.print("# ");
ps.println(lines[i]);
}
ps.println();
}
/**
* Helps identify the source file
*/
private static String getFileCRC(File f) {
CRC32 crc = new CRC32();
byte[]buf = new byte[2048];
try {
InputStream is = new FileInputStream(f);
while(true) {
int bytesRead = is.read(buf);
if(bytesRead<1) {
break;
}
crc.update(buf, 0, bytesRead);
}
is.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
return "0x" + Long.toHexString(crc.getValue()).toUpperCase();
}
private static File getSourceFile() {
if (true) {
File dir = new File("c:/josh/ref-docs");
File effDocFile = new File(dir, SOURCE_DOC_FILE_NAME);
return effDocFile;
}
URL url;
try {
url = new URL("http://sc.openoffice.org/" + SOURCE_DOC_FILE_NAME);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
File result;
byte[]buf = new byte[2048];
try {
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();
System.out.println("downloading " + url.toExternalForm());
result = File.createTempFile("excelfileformat", "odt");
OutputStream os = new FileOutputStream(result);
while(true) {
int bytesRead = is.read(buf);
if(bytesRead<1) {
break;
}
os.write(buf, 0, bytesRead);
}
is.close();
os.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
System.out.println("file downloaded ok");
return result;
}
public static void main(String[] args) {
File effDocFile = getSourceFile();
if(!effDocFile.exists()) {
throw new RuntimeException("file '" + effDocFile.getAbsolutePath() + "' does not exist");
}
File outFile = new File("functionMetadata-asGenerated.txt");
processFile(effDocFile, outFile);
}
}

View File

@ -0,0 +1,43 @@
/* ====================================================================
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.function;
import junit.framework.TestCase;
/**
*
* @author Josh Micich
*/
public final class TestFunctionMetadataRegistry extends TestCase {
public void testWellKnownFunctions() {
confirmFunction(0, "COUNT");
confirmFunction(1, "IF");
}
private static void confirmFunction(int index, String funcName) {
FunctionMetadata fm;
fm = FunctionMetadataRegistry.getFunctionByIndex(index);
assertNotNull(fm);
assertEquals(funcName, fm.getName());
fm = FunctionMetadataRegistry.getFunctionByName(funcName);
assertNotNull(fm);
assertEquals(index, fm.getIndex());
}
}

View File

@ -0,0 +1,79 @@
/* ====================================================================
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.function;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.apache.poi.hssf.model.FormulaParser;
import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.formula.AbstractFunctionPtg;
import org.apache.poi.hssf.record.formula.FuncPtg;
import org.apache.poi.hssf.record.formula.FuncVarPtg;
import org.apache.poi.hssf.record.formula.Ptg;
/**
* @author Josh Micich
*/
public final class TestParseMissingBuiltInFuncs extends TestCase {
private static Ptg[] parse(String formula) {
Workbook book = Workbook.createWorkbook();
return FormulaParser.parse(formula, book);
}
private static void confirmFunc(String formula, int expPtgArraySize, boolean isVarArgFunc, int funcIx) {
Ptg[] ptgs = parse(formula);
Ptg ptgF = ptgs[ptgs.length-1]; // func is last RPN token in all these formulas
if(!(ptgF instanceof AbstractFunctionPtg)) {
throw new RuntimeException("function token missing");
}
AbstractFunctionPtg func = (AbstractFunctionPtg) ptgF;
if(func.getFunctionIndex() == 255) {
throw new AssertionFailedError("Failed to recognise built-in function in formula '"
+ formula + "'");
}
assertEquals(expPtgArraySize, ptgs.length);
assertEquals(funcIx, func.getFunctionIndex());
Class expCls = isVarArgFunc ? FuncVarPtg.class : FuncPtg.class;
assertEquals(expCls, ptgF.getClass());
}
public void testDatedif() {
int expSize = 4; // NB would be 5 if POI added tAttrVolatile properly
confirmFunc("DATEDIF(NOW(),NOW(),\"d\")", expSize, false, 351);
}
public void testDdb() {
confirmFunc("DDB(1,1,1,1,1)", 6, true, 144);
}
public void testAtan() {
confirmFunc("ATAN(1)", 2, false, 18);
}
public void testUsdollar() {
confirmFunc("USDOLLAR(1)", 2, false, 204);
}
public void testDBCS() {
confirmFunc("DBCS(\"abc\")", 2, false, 215);
}
public void testIsnontext() {
confirmFunc("ISNONTEXT(\"abc\")", 2, false, 190);
}
}

View File

@ -0,0 +1,142 @@
/* ====================================================================
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.function;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
/**
* Tests reading from a sample spreadsheet some built-in functions that were not properly
* registered in POI as bug #44675 (March 2008).
*
* @author Josh Micich
*/
public final class TestReadMissingBuiltInFuncs extends TestCase {
private HSSFSheet sht;
protected void setUp() {
String cwd = System.getProperty("HSSF.testdata.path");
HSSFWorkbook wb;
try {
InputStream is = new FileInputStream(new File(cwd, "missingFuncs44675.xls"));
wb = new HSSFWorkbook(is);
} catch (IOException e) {
throw new RuntimeException(e);
}
sht = wb.getSheetAt(0);
}
public void testDatedif() {
String formula;
try {
formula = getCellFormula(0);
} catch (IllegalStateException e) {
if(e.getMessage().startsWith("Too few arguments")) {
if(e.getMessage().indexOf("AttrPtg") > 0) {
throw afe("tAttrVolatile not supported in FormulaParser.toFormulaString");
}
throw afe("NOW() registered with 1 arg instead of 0");
}
if(e.getMessage().startsWith("too much stuff")) {
throw afe("DATEDIF() not registered");
}
// some other unexpected error
throw e;
}
assertEquals("DATEDIF(NOW(),NOW(),\"d\")", formula);
}
public void testDdb() {
String formula = getCellFormula(1);
if("externalflag(1,1,1,1,1)".equals(formula)) {
throw afe("DDB() not registered");
}
assertEquals("DDB(1,1,1,1,1)", formula);
}
public void testAtan() {
String formula = getCellFormula(2);
if(formula.equals("ARCTAN(1)")) {
throw afe("func ix 18 registered as ARCTAN() instead of ATAN()");
}
assertEquals("ATAN(1)", formula);
}
public void testUsdollar() {
String formula = getCellFormula(3);
if(formula.equals("YEN(1)")) {
throw afe("func ix 204 registered as YEN() instead of USDOLLAR()");
}
assertEquals("USDOLLAR(1)", formula);
}
public void testDBCS() {
String formula;
try {
formula = getCellFormula(4);
} catch (IllegalStateException e) {
if(e.getMessage().startsWith("too much stuff")) {
throw afe("DBCS() not registered");
}
// some other unexpected error
throw e;
} catch (NegativeArraySizeException e) {
throw afe("found err- DBCS() registered with -1 args");
}
if(formula.equals("JIS(\"abc\")")) {
throw afe("func ix 215 registered as JIS() instead of DBCS()");
}
assertEquals("DBCS(\"abc\")", formula);
}
public void testIsnontext() {
String formula;
try {
formula = getCellFormula(5);
} catch (IllegalStateException e) {
if(e.getMessage().startsWith("too much stuff")) {
throw afe("ISNONTEXT() registered with wrong index");
}
// some other unexpected error
throw e;
}
assertEquals("ISNONTEXT(\"abc\")", formula);
}
private String getCellFormula(int rowIx) {
String result = sht.getRow(rowIx).getCell((short)0).getCellFormula();
if (false) {
System.err.println(result);
}
return result;
}
private static AssertionFailedError afe(String msg) {
return new AssertionFailedError(msg);
}
}