1    package org.apache.poi.hssf.record.formula;
2    
3    import java.util.List;
4    import java.util.ArrayList;
5    import java.util.Map;
6    import org.apache.poi.util.LittleEndian;
7    import org.apache.poi.util.BinaryTree;
8    /**
9     * This class provides functions with variable arguments.  
10    * @author  Avik Sengupta
11    * @author Andrew C. Oliver (acoliver at apache dot org)
12    * @version 
13    */
14   public class FunctionPtg extends OperationPtg {
15       public final static short sid  = 0x22;
16       private final static int  SIZE = 4;    
17       
18       private static BinaryTree map = produceHash(); 
19       
20       static { map=produceHash();}
21       
22       private byte field_1_num_args;
23       private short field_2_fnc_index;
24       
25           
26       /**Creates new function pointer from a byte array 
27        * usually called while reading an excel file. 
28        */
29       public FunctionPtg(byte[] data, int offset) {
30           offset++;
31           field_1_num_args = data[ offset + 0 ];
32           field_2_fnc_index  = LittleEndian.getShort(data,offset + 1 );
33           
34       }
35       
36       /**
37        * Create a function ptg from a string tokenised by the parser
38        */
39       protected FunctionPtg(String pName, byte pNumOperands) {
40           field_1_num_args = pNumOperands;
41           field_2_fnc_index = lookupIndex(pName);
42           
43       }
44       
45       public String toString() {
46           StringBuffer buffer = new StringBuffer();
47           buffer
48           .append("<FunctionPtg>").append("\n")
49           .append("   field_1_num_args=").append(field_1_num_args).append("\n")
50           .append("      name         =").append(lookupName(field_2_fnc_index)).append("\n")
51           .append("   field_2_fnc_index=").append(field_2_fnc_index).append("\n")
52           .append("</FunctionPtg>");
53           return buffer.toString();
54       }
55      
56       public int getType() {
57           return -1;
58       }   
59       
60       public int getNumberOfOperands() {
61           return field_1_num_args;
62       }
63       
64       public short getFunctionIndex() {
65           return field_2_fnc_index;
66       }
67       
68       public String getName() {
69           return lookupName(field_2_fnc_index);
70       }
71       
72       public String toFormulaString() {
73           return getName();
74       }
75       
76       public String toFormulaString(String[] operands) {
77           StringBuffer buf = new StringBuffer();
78           buf.append(getName()+"(");
79           if (operands.length >0) {
80               for (int i=0;i<operands.length;i++) {
81                   buf.append(operands[i]);
82                   buf.append(',');
83               }
84               buf.deleteCharAt(buf.length()-1);
85           }
86           buf.append(")");
87           return buf.toString();
88       }
89       
90       
91       public void writeBytes(byte[] array, int offset) {
92           array[offset+0]=sid;
93           array[offset+1]=field_1_num_args;
94           LittleEndian.putShort(array,offset+2,field_2_fnc_index);
95       }
96       
97       public int getSize() {
98           return SIZE;
99       }
100      
101      private String lookupName(short index) {
102          return ((String)map.get(new Integer(index))); //for now always return "SUM"
103      }
104      
105      private short lookupIndex(String name) {
106          return (short)((Integer)map.getKeyForValue(name)).intValue(); //for now just return SUM everytime...
107      }
108      
109      /**
110       * Produces the function table hashmap
111       */
112      private static BinaryTree produceHash() {
113          BinaryTree dmap = new BinaryTree();
114  
115          dmap.put(new Integer(0),"COUNT");
116          dmap.put(new Integer(2),"ISNA");
117          dmap.put(new Integer(3),"ISERROR");
118          dmap.put(new Integer(4),"SUM");
119          dmap.put(new Integer(5),"AVERAGE");
120          dmap.put(new Integer(6),"MIN");
121          dmap.put(new Integer(7),"MAX");
122          dmap.put(new Integer(8),"ROW");
123          dmap.put(new Integer(9),"COLUMN");
124          dmap.put(new Integer(10),"NA");
125          dmap.put(new Integer(11),"NPV");
126          dmap.put(new Integer(12),"STDEV");
127          dmap.put(new Integer(13),"DOLLAR");
128          dmap.put(new Integer(14),"FIXED");
129          dmap.put(new Integer(15),"SIN");
130          dmap.put(new Integer(16),"COS");
131          dmap.put(new Integer(17),"TAN");
132          dmap.put(new Integer(18),"ATAN");
133          dmap.put(new Integer(19),"PI");
134          dmap.put(new Integer(20),"SQRT");
135          dmap.put(new Integer(21),"EXP");
136          dmap.put(new Integer(22),"LN");
137          dmap.put(new Integer(23),"LOG10");
138          dmap.put(new Integer(24),"ABS");
139          dmap.put(new Integer(25),"INT");
140          dmap.put(new Integer(26),"SIGN");
141          dmap.put(new Integer(27),"ROUND");
142          dmap.put(new Integer(28),"LOOKUP");
143          dmap.put(new Integer(29),"INDEX");
144          dmap.put(new Integer(30),"REPT");
145          dmap.put(new Integer(31),"MID");
146          dmap.put(new Integer(32),"LEN");
147          dmap.put(new Integer(33),"VALUE");
148          dmap.put(new Integer(34),"TRUE");
149          dmap.put(new Integer(35),"FALSE");
150          dmap.put(new Integer(36),"AND");
151          dmap.put(new Integer(37),"OR");
152          dmap.put(new Integer(38),"NOT");
153          dmap.put(new Integer(39),"MOD");
154          dmap.put(new Integer(40),"DCOUNT");
155          dmap.put(new Integer(41),"DSUM");
156          dmap.put(new Integer(42),"DAVERAGE");
157          dmap.put(new Integer(43),"DMIN");
158          dmap.put(new Integer(44),"DMAX");
159          dmap.put(new Integer(45),"DSTDEV");
160          dmap.put(new Integer(46),"VAR");
161          dmap.put(new Integer(47),"DVAR");
162          dmap.put(new Integer(48),"TEXT");
163          dmap.put(new Integer(49),"LINEST");
164          dmap.put(new Integer(50),"TREND");
165          dmap.put(new Integer(51),"LOGEST");
166          dmap.put(new Integer(52),"GROWTH");
167          dmap.put(new Integer(53),"GOTO");
168          dmap.put(new Integer(54),"HALT");
169          dmap.put(new Integer(56),"PV");
170          dmap.put(new Integer(57),"FV");
171          dmap.put(new Integer(58),"NPER");
172          dmap.put(new Integer(59),"PMT");
173          dmap.put(new Integer(60),"RATE");
174          dmap.put(new Integer(61),"MIRR");
175          dmap.put(new Integer(62),"IRR");
176          dmap.put(new Integer(63),"RAND");
177          dmap.put(new Integer(64),"MATCH");
178          dmap.put(new Integer(65),"DATE");
179          dmap.put(new Integer(66),"TIME");
180          dmap.put(new Integer(67),"DAY");
181          dmap.put(new Integer(68),"MONTH");
182          dmap.put(new Integer(69),"YEAR");
183          dmap.put(new Integer(70),"WEEKDAY");
184          dmap.put(new Integer(71),"HOUR");
185          dmap.put(new Integer(72),"MINUTE");
186          dmap.put(new Integer(73),"SECOND");
187          dmap.put(new Integer(74),"NOW");
188          dmap.put(new Integer(75),"AREAS");
189          dmap.put(new Integer(76),"ROWS");
190          dmap.put(new Integer(77),"COLUMNS");
191          dmap.put(new Integer(78),"OFFSET");
192          dmap.put(new Integer(79),"ABSREF");
193          dmap.put(new Integer(80),"RELREF");
194          dmap.put(new Integer(81),"ARGUMENT");
195          dmap.put(new Integer(82),"SEARCH");
196          dmap.put(new Integer(83),"TRANSPOSE");
197          dmap.put(new Integer(84),"ERROR");
198          dmap.put(new Integer(85),"STEP");
199          dmap.put(new Integer(86),"TYPE");
200          dmap.put(new Integer(87),"ECHO");
201          dmap.put(new Integer(88),"SETNAME");
202          dmap.put(new Integer(89),"CALLER");
203          dmap.put(new Integer(90),"DEREF");
204          dmap.put(new Integer(91),"WINDOWS");
205          dmap.put(new Integer(92),"SERIES");
206          dmap.put(new Integer(93),"DOCUMENTS");
207          dmap.put(new Integer(94),"ACTIVECELL");
208          dmap.put(new Integer(95),"SELECTION");
209          dmap.put(new Integer(96),"RESULT");
210          dmap.put(new Integer(97),"ATAN2");
211          dmap.put(new Integer(98),"ASIN");
212          dmap.put(new Integer(99),"ACOS");
213          dmap.put(new Integer(100),"CHOOSE");
214          dmap.put(new Integer(101),"HLOOKUP");
215          dmap.put(new Integer(102),"VLOOKUP");
216          dmap.put(new Integer(103),"LINKS");
217          dmap.put(new Integer(104),"INPUT");
218          dmap.put(new Integer(105),"ISREF");
219          dmap.put(new Integer(106),"GETFORMULA");
220          dmap.put(new Integer(107),"GETNAME");
221          dmap.put(new Integer(108),"SETVALUE");
222          dmap.put(new Integer(109),"LOG");
223          dmap.put(new Integer(110),"EXEC");
224          dmap.put(new Integer(111),"CHAR");
225          dmap.put(new Integer(112),"LOWER");
226          dmap.put(new Integer(113),"UPPER");
227          dmap.put(new Integer(114),"PROPER");
228          dmap.put(new Integer(115),"LEFT");
229          dmap.put(new Integer(116),"RIGHT");
230          dmap.put(new Integer(117),"EXACT");
231          dmap.put(new Integer(118),"TRIM");
232          dmap.put(new Integer(119),"REPLACE");
233          dmap.put(new Integer(120),"SUBSTITUTE");
234          dmap.put(new Integer(121),"CODE");
235          dmap.put(new Integer(122),"NAMES");
236          dmap.put(new Integer(123),"DIRECTORY");
237          dmap.put(new Integer(124),"FIND");
238          dmap.put(new Integer(125),"CELL");
239          dmap.put(new Integer(126),"ISERR");
240          dmap.put(new Integer(127),"ISTEXT");
241          dmap.put(new Integer(128),"ISNUMBER");
242          dmap.put(new Integer(129),"ISBLANK");
243          dmap.put(new Integer(130),"T");
244          dmap.put(new Integer(131),"N");
245          dmap.put(new Integer(132),"FOPEN");
246          dmap.put(new Integer(133),"FCLOSE");
247          dmap.put(new Integer(134),"FSIZE");
248          dmap.put(new Integer(135),"FREADLN");
249          dmap.put(new Integer(136),"FREAD");
250          dmap.put(new Integer(137),"FWRITELN");
251          dmap.put(new Integer(138),"FWRITE");
252          dmap.put(new Integer(139),"FPOS");
253          dmap.put(new Integer(140),"DATEVALUE");
254          dmap.put(new Integer(141),"TIMEVALUE");
255          dmap.put(new Integer(142),"SLN");
256          dmap.put(new Integer(143),"SYD");
257          dmap.put(new Integer(144),"DDB");
258          dmap.put(new Integer(145),"GETDEF");
259          dmap.put(new Integer(146),"REFTEXT");
260          dmap.put(new Integer(147),"TEXTREF");
261          dmap.put(new Integer(148),"INDIRECT");
262          dmap.put(new Integer(149),"REGISTER");
263          dmap.put(new Integer(150),"CALL");
264          dmap.put(new Integer(151),"ADDBAR");
265          dmap.put(new Integer(152),"ADDMENU");
266          dmap.put(new Integer(153),"ADDCOMMAND");
267          dmap.put(new Integer(154),"ENABLECOMMAND");
268          dmap.put(new Integer(155),"CHECKCOMMAND");
269          dmap.put(new Integer(156),"RENAMECOMMAND");
270          dmap.put(new Integer(157),"SHOWBAR");
271          dmap.put(new Integer(158),"DELETEMENU");
272          dmap.put(new Integer(159),"DELETECOMMAND");
273          dmap.put(new Integer(160),"GETCHARTITEM");
274          dmap.put(new Integer(161),"DIALOGBOX");
275          dmap.put(new Integer(162),"CLEAN");
276          dmap.put(new Integer(163),"MDETERM");
277          dmap.put(new Integer(164),"MINVERSE");
278          dmap.put(new Integer(165),"MMULT");
279          dmap.put(new Integer(166),"FILES");
280          dmap.put(new Integer(167),"IPMT");
281          dmap.put(new Integer(168),"PPMT");
282          dmap.put(new Integer(169),"COUNTA");
283          dmap.put(new Integer(170),"CANCELKEY");
284          dmap.put(new Integer(175),"INITIATE");
285          dmap.put(new Integer(176),"REQUEST");
286          dmap.put(new Integer(177),"POKE");
287          dmap.put(new Integer(178),"EXECUTE");
288          dmap.put(new Integer(179),"TERMINATE");
289          dmap.put(new Integer(180),"RESTART");
290          dmap.put(new Integer(181),"HELP");
291          dmap.put(new Integer(182),"GETBAR");
292          dmap.put(new Integer(183),"PRODUCT");
293          dmap.put(new Integer(184),"FACT");
294          dmap.put(new Integer(185),"GETCELL");
295          dmap.put(new Integer(186),"GETWORKSPACE");
296          dmap.put(new Integer(187),"GETWINDOW");
297          dmap.put(new Integer(188),"GETDOCUMENT");
298          dmap.put(new Integer(189),"DPRODUCT");
299          dmap.put(new Integer(190),"ISNONTEXT");
300          dmap.put(new Integer(191),"GETNOTE");
301          dmap.put(new Integer(192),"NOTE");
302          dmap.put(new Integer(193),"STDEVP");
303          dmap.put(new Integer(194),"VARP");
304          dmap.put(new Integer(195),"DSTDEVP");
305          dmap.put(new Integer(196),"DVARP");
306          dmap.put(new Integer(197),"TRUNC");
307          dmap.put(new Integer(198),"ISLOGICAL");
308          dmap.put(new Integer(199),"DCOUNTA");
309          dmap.put(new Integer(200),"DELETEBAR");
310          dmap.put(new Integer(201),"UNREGISTER");
311          dmap.put(new Integer(204),"USDOLLAR");
312          dmap.put(new Integer(205),"FINDB");
313          dmap.put(new Integer(206),"SEARCHB");
314          dmap.put(new Integer(207),"REPLACEB");
315          dmap.put(new Integer(208),"LEFTB");
316          dmap.put(new Integer(209),"RIGHTB");
317          dmap.put(new Integer(210),"MIDB");
318          dmap.put(new Integer(211),"LENB");
319          dmap.put(new Integer(212),"ROUNDUP");
320          dmap.put(new Integer(213),"ROUNDDOWN");
321          dmap.put(new Integer(214),"ASC");
322          dmap.put(new Integer(215),"DBCS");
323          dmap.put(new Integer(216),"RANK");
324          dmap.put(new Integer(219),"ADDRESS");
325          dmap.put(new Integer(220),"DAYS360");
326          dmap.put(new Integer(221),"TODAY");
327          dmap.put(new Integer(222),"VDB");
328          dmap.put(new Integer(227),"MEDIAN");
329          dmap.put(new Integer(228),"SUMPRODUCT");
330          dmap.put(new Integer(229),"SINH");
331          dmap.put(new Integer(230),"COSH");
332          dmap.put(new Integer(231),"TANH");
333          dmap.put(new Integer(232),"ASINH");
334          dmap.put(new Integer(233),"ACOSH");
335          dmap.put(new Integer(234),"ATANH");
336          dmap.put(new Integer(235),"DGET");
337          dmap.put(new Integer(236),"CREATEOBJECT");
338          dmap.put(new Integer(237),"VOLATILE");
339          dmap.put(new Integer(238),"LASTERROR");
340          dmap.put(new Integer(239),"CUSTOMUNDO");
341          dmap.put(new Integer(240),"CUSTOMREPEAT");
342          dmap.put(new Integer(241),"FORMULACONVERT");
343          dmap.put(new Integer(242),"GETLINKINFO");
344          dmap.put(new Integer(243),"TEXTBOX");
345          dmap.put(new Integer(244),"INFO");
346          dmap.put(new Integer(245),"GROUP");
347          dmap.put(new Integer(246),"GETOBJECT");
348          dmap.put(new Integer(247),"DB");
349          dmap.put(new Integer(248),"PAUSE");
350          dmap.put(new Integer(250),"RESUME");
351          dmap.put(new Integer(252),"FREQUENCY");
352          dmap.put(new Integer(253),"ADDTOOLBAR");
353          dmap.put(new Integer(254),"DELETETOOLBAR");
354          dmap.put(new Integer(256),"RESETTOOLBAR");
355          dmap.put(new Integer(257),"EVALUATE");
356          dmap.put(new Integer(258),"GETTOOLBAR");
357          dmap.put(new Integer(259),"GETTOOL");
358          dmap.put(new Integer(260),"SPELLINGCHECK");
359          dmap.put(new Integer(261),"ERRORTYPE");
360          dmap.put(new Integer(262),"APPTITLE");
361          dmap.put(new Integer(263),"WINDOWTITLE");
362          dmap.put(new Integer(264),"SAVETOOLBAR");
363          dmap.put(new Integer(265),"ENABLETOOL");
364          dmap.put(new Integer(266),"PRESSTOOL");
365          dmap.put(new Integer(267),"REGISTERID");
366          dmap.put(new Integer(268),"GETWORKBOOK");
367          dmap.put(new Integer(269),"AVEDEV");
368          dmap.put(new Integer(270),"BETADIST");
369          dmap.put(new Integer(271),"GAMMALN");
370          dmap.put(new Integer(272),"BETAINV");
371          dmap.put(new Integer(273),"BINOMDIST");
372          dmap.put(new Integer(274),"CHIDIST");
373          dmap.put(new Integer(275),"CHIINV");
374          dmap.put(new Integer(276),"COMBIN");
375          dmap.put(new Integer(277),"CONFIDENCE");
376          dmap.put(new Integer(278),"CRITBINOM");
377          dmap.put(new Integer(279),"EVEN");
378          dmap.put(new Integer(280),"EXPONDIST");
379          dmap.put(new Integer(281),"FDIST");
380          dmap.put(new Integer(282),"FINV");
381          dmap.put(new Integer(283),"FISHER");
382          dmap.put(new Integer(284),"FISHERINV");
383          dmap.put(new Integer(285),"FLOOR");
384          dmap.put(new Integer(286),"GAMMADIST");
385          dmap.put(new Integer(287),"GAMMAINV");
386          dmap.put(new Integer(288),"CEILING");
387          dmap.put(new Integer(289),"HYPGEOMDIST");
388          dmap.put(new Integer(290),"LOGNORMDIST");
389          dmap.put(new Integer(291),"LOGINV");
390          dmap.put(new Integer(292),"NEGBINOMDIST");
391          dmap.put(new Integer(293),"NORMDIST");
392          dmap.put(new Integer(294),"NORMSDIST");
393          dmap.put(new Integer(295),"NORMINV");
394          dmap.put(new Integer(296),"NORMSINV");
395          dmap.put(new Integer(297),"STANDARDIZE");
396          dmap.put(new Integer(298),"ODD");
397          dmap.put(new Integer(299),"PERMUT");
398          dmap.put(new Integer(300),"POISSON");
399          dmap.put(new Integer(301),"TDIST");
400          dmap.put(new Integer(302),"WEIBULL");
401          dmap.put(new Integer(303),"SUMXMY2");
402          dmap.put(new Integer(304),"SUMX2MY2");
403          dmap.put(new Integer(305),"SUMX2PY2");
404          dmap.put(new Integer(306),"CHITEST");
405          dmap.put(new Integer(307),"CORREL");
406          dmap.put(new Integer(308),"COVAR");
407          dmap.put(new Integer(309),"FORECAST");
408          dmap.put(new Integer(310),"FTEST");
409          dmap.put(new Integer(311),"INTERCEPT");
410          dmap.put(new Integer(312),"PEARSON");
411          dmap.put(new Integer(313),"RSQ");
412          dmap.put(new Integer(314),"STEYX");
413          dmap.put(new Integer(315),"SLOPE");
414          dmap.put(new Integer(316),"TTEST");
415          dmap.put(new Integer(317),"PROB");
416          dmap.put(new Integer(318),"DEVSQ");
417          dmap.put(new Integer(319),"GEOMEAN");
418          dmap.put(new Integer(320),"HARMEAN");
419          dmap.put(new Integer(321),"SUMSQ");
420          dmap.put(new Integer(322),"KURT");
421          dmap.put(new Integer(323),"SKEW");
422          dmap.put(new Integer(324),"ZTEST");
423          dmap.put(new Integer(325),"LARGE");
424          dmap.put(new Integer(326),"SMALL");
425          dmap.put(new Integer(327),"QUARTILE");
426          dmap.put(new Integer(328),"PERCENTILE");
427          dmap.put(new Integer(329),"PERCENTRANK");
428          dmap.put(new Integer(330),"MODE");
429          dmap.put(new Integer(331),"TRIMMEAN");
430          dmap.put(new Integer(332),"TINV");
431          dmap.put(new Integer(334),"MOVIECOMMAND");
432          dmap.put(new Integer(335),"GETMOVIE");
433          dmap.put(new Integer(336),"CONCATENATE");
434          dmap.put(new Integer(337),"POWER");
435          dmap.put(new Integer(338),"PIVOTADDDATA");
436          dmap.put(new Integer(339),"GETPIVOTTABLE");
437          dmap.put(new Integer(340),"GETPIVOTFIELD");
438          dmap.put(new Integer(341),"GETPIVOTITEM");
439          dmap.put(new Integer(342),"RADIANS");
440          dmap.put(new Integer(343),"DEGREES");
441          dmap.put(new Integer(344),"SUBTOTAL");
442          dmap.put(new Integer(345),"SUMIF");
443          dmap.put(new Integer(346),"COUNTIF");
444          dmap.put(new Integer(347),"COUNTBLANK");
445          dmap.put(new Integer(348),"SCENARIOGET");
446          dmap.put(new Integer(349),"OPTIONSLISTSGET");
447          dmap.put(new Integer(350),"ISPMT");
448          dmap.put(new Integer(351),"DATEDIF");
449          dmap.put(new Integer(352),"DATESTRING");
450          dmap.put(new Integer(353),"NUMBERSTRING");
451          dmap.put(new Integer(354),"ROMAN");
452          dmap.put(new Integer(355),"OPENDIALOG");
453          dmap.put(new Integer(356),"SAVEDIALOG");
454          dmap.put(new Integer(357),"VIEWGET");
455          dmap.put(new Integer(358),"GETPIVOTDATA");
456          dmap.put(new Integer(359),"HYPERLINK");
457          dmap.put(new Integer(360),"PHONETIC");
458          dmap.put(new Integer(361),"AVERAGEA");
459          dmap.put(new Integer(362),"MAXA");
460          dmap.put(new Integer(363),"MINA");
461          dmap.put(new Integer(364),"STDEVPA");
462          dmap.put(new Integer(365),"VARPA");
463          dmap.put(new Integer(366),"STDEVA");
464          dmap.put(new Integer(367),"VARA");
465  
466          return dmap;
467      }
468  }
469