source: sourcecode/application/libraries/PHPExcel/Calculation.php @ 1

Last change on this file since 1 was 1, checked in by dungnv, 11 years ago
File size: 171.1 KB
Line 
1<?php
2/**
3 * PHPExcel
4 *
5 * Copyright (c) 2006 - 2014 PHPExcel
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20 *
21 * @category   PHPExcel
22 * @package    PHPExcel_Calculation
23 * @copyright  Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
24 * @license     http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt   LGPL
25 * @version     1.8.0, 2014-03-02
26 */
27
28
29/** PHPExcel root directory */
30if (!defined('PHPEXCEL_ROOT')) {
31        /**
32         * @ignore
33         */
34        define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../');
35        require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
36}
37
38
39if (!defined('CALCULATION_REGEXP_CELLREF')) {
40        //      Test for support of \P (multibyte options) in PCRE
41        if(defined('PREG_BAD_UTF8_ERROR')) {
42                //      Cell reference (cell or range of cells, with or without a sheet reference)
43                define('CALCULATION_REGEXP_CELLREF','((([^\s,!&%^\/\*\+<>=-]*)|(\'[^\']*\')|(\"[^\"]*\"))!)?\$?([a-z]{1,3})\$?(\d{1,7})');
44                //      Named Range of cells
45                define('CALCULATION_REGEXP_NAMEDRANGE','((([^\s,!&%^\/\*\+<>=-]*)|(\'[^\']*\')|(\"[^\"]*\"))!)?([_A-Z][_A-Z0-9\.]*)');
46        } else {
47                //      Cell reference (cell or range of cells, with or without a sheet reference)
48                define('CALCULATION_REGEXP_CELLREF','(((\w*)|(\'[^\']*\')|(\"[^\"]*\"))!)?\$?([a-z]{1,3})\$?(\d+)');
49                //      Named Range of cells
50                define('CALCULATION_REGEXP_NAMEDRANGE','(((\w*)|(\'.*\')|(\".*\"))!)?([_A-Z][_A-Z0-9\.]*)');
51        }
52}
53
54
55/**
56 * PHPExcel_Calculation (Multiton)
57 *
58 * @category    PHPExcel
59 * @package             PHPExcel_Calculation
60 * @copyright   Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
61 */
62class PHPExcel_Calculation {
63
64        /** Constants                           */
65        /** Regular Expressions         */
66        //      Numeric operand
67        const CALCULATION_REGEXP_NUMBER         = '[-+]?\d*\.?\d+(e[-+]?\d+)?';
68        //      String operand
69        const CALCULATION_REGEXP_STRING         = '"(?:[^"]|"")*"';
70        //      Opening bracket
71        const CALCULATION_REGEXP_OPENBRACE      = '\(';
72        //      Function (allow for the old @ symbol that could be used to prefix a function, but we'll ignore it)
73        const CALCULATION_REGEXP_FUNCTION       = '@?([A-Z][A-Z0-9\.]*)[\s]*\(';
74        //      Cell reference (cell or range of cells, with or without a sheet reference)
75        const CALCULATION_REGEXP_CELLREF        = CALCULATION_REGEXP_CELLREF;
76        //      Named Range of cells
77        const CALCULATION_REGEXP_NAMEDRANGE     = CALCULATION_REGEXP_NAMEDRANGE;
78        //      Error
79        const CALCULATION_REGEXP_ERROR          = '\#[A-Z][A-Z0_\/]*[!\?]?';
80
81
82        /** constants */
83        const RETURN_ARRAY_AS_ERROR = 'error';
84        const RETURN_ARRAY_AS_VALUE = 'value';
85        const RETURN_ARRAY_AS_ARRAY = 'array';
86
87        private static $returnArrayAsType       = self::RETURN_ARRAY_AS_VALUE;
88
89
90        /**
91         * Instance of this class
92         *
93         * @access      private
94         * @var PHPExcel_Calculation
95         */
96        private static $_instance;
97
98
99        /**
100         * Instance of the workbook this Calculation Engine is using
101         *
102         * @access      private
103         * @var PHPExcel
104         */
105    private $_workbook;
106
107        /**
108         * List of instances of the calculation engine that we've instantiated for individual workbooks
109         *
110         * @access      private
111         * @var PHPExcel_Calculation[]
112         */
113    private static $_workbookSets;
114
115        /**
116         * Calculation cache
117         *
118         * @access      private
119         * @var array
120         */
121        private $_calculationCache = array ();
122
123
124        /**
125         * Calculation cache enabled
126         *
127         * @access      private
128         * @var boolean
129         */
130        private $_calculationCacheEnabled = TRUE;
131
132
133        /**
134         * List of operators that can be used within formulae
135         * The true/false value indicates whether it is a binary operator or a unary operator
136         *
137         * @access      private
138         * @var array
139         */
140        private static $_operators                      = array('+' => TRUE,    '-' => TRUE,    '*' => TRUE,    '/' => TRUE,
141                                                                                                '^' => TRUE,    '&' => TRUE,    '%' => FALSE,   '~' => FALSE,
142                                                                                                '>' => TRUE,    '<' => TRUE,    '=' => TRUE,    '>=' => TRUE,
143                                                                                                '<=' => TRUE,   '<>' => TRUE,   '|' => TRUE,    ':' => TRUE
144                                                                                           );
145
146
147        /**
148         * List of binary operators (those that expect two operands)
149         *
150         * @access      private
151         * @var array
152         */
153        private static $_binaryOperators        = array('+' => TRUE,    '-' => TRUE,    '*' => TRUE,    '/' => TRUE,
154                                                                                                '^' => TRUE,    '&' => TRUE,    '>' => TRUE,    '<' => TRUE,
155                                                                                                '=' => TRUE,    '>=' => TRUE,   '<=' => TRUE,   '<>' => TRUE,
156                                                                                                '|' => TRUE,    ':' => TRUE
157                                                                                           );
158
159        /**
160         * The debug log generated by the calculation engine
161         *
162         * @access      private
163         * @var PHPExcel_CalcEngine_Logger
164         *
165         */
166        private $debugLog;
167
168        /**
169         * Flag to determine how formula errors should be handled
170         *              If true, then a user error will be triggered
171         *              If false, then an exception will be thrown
172         *
173         * @access      public
174         * @var boolean
175         *
176         */
177        public $suppressFormulaErrors = FALSE;
178
179        /**
180         * Error message for any error that was raised/thrown by the calculation engine
181         *
182         * @access      public
183         * @var string
184         *
185         */
186        public $formulaError = NULL;
187
188        /**
189         * An array of the nested cell references accessed by the calculation engine, used for the debug log
190         *
191         * @access      private
192         * @var array of string
193         *
194         */
195        private $_cyclicReferenceStack;
196
197        /**
198         * Current iteration counter for cyclic formulae
199         * If the value is 0 (or less) then cyclic formulae will throw an exception,
200         *    otherwise they will iterate to the limit defined here before returning a result
201         *
202         * @var integer
203         *
204         */
205        private $_cyclicFormulaCount = 0;
206
207        private $_cyclicFormulaCell = '';
208
209        /**
210         * Number of iterations for cyclic formulae
211         *
212         * @var integer
213         *
214         */
215        public $cyclicFormulaCount = 0;
216
217        /**
218         * Precision used for calculations
219         *
220         * @var integer
221         *
222         */
223        private $_savedPrecision        = 14;
224
225
226        /**
227         * The current locale setting
228         *
229         * @var string
230         *
231         */
232        private static $_localeLanguage = 'en_us';                                      //      US English      (default locale)
233
234        /**
235         * List of available locale settings
236         * Note that this is read for the locale subdirectory only when requested
237         *
238         * @var string[]
239         *
240         */
241        private static $_validLocaleLanguages = array(  'en'            //      English         (default language)
242                                                                                                 );
243        /**
244         * Locale-specific argument separator for function arguments
245         *
246         * @var string
247         *
248         */
249        private static $_localeArgumentSeparator = ',';
250        private static $_localeFunctions = array();
251
252        /**
253         * Locale-specific translations for Excel constants (True, False and Null)
254         *
255         * @var string[]
256         *
257         */
258        public static $_localeBoolean = array(  'TRUE'  => 'TRUE',
259                                                                                        'FALSE' => 'FALSE',
260                                                                                        'NULL'  => 'NULL'
261                                                                                  );
262
263
264        /**
265         * Excel constant string translations to their PHP equivalents
266         * Constant conversion from text name/value to actual (datatyped) value
267         *
268         * @var string[]
269         *
270         */
271        private static $_ExcelConstants = array('TRUE'  => TRUE,
272                                                                                        'FALSE' => FALSE,
273                                                                                        'NULL'  => NULL
274                                                                                   );
275
276        //      PHPExcel functions
277        private static $_PHPExcelFunctions = array(     // PHPExcel functions
278                                'ABS'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
279                                                                                                 'functionCall'         =>      'abs',
280                                                                                                 'argumentCount'        =>      '1'
281                                                                                                ),
282                                'ACCRINT'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
283                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::ACCRINT',
284                                                                                                 'argumentCount'        =>      '4-7'
285                                                                                                ),
286                                'ACCRINTM'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
287                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::ACCRINTM',
288                                                                                                 'argumentCount'        =>      '3-5'
289                                                                                                ),
290                                'ACOS'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
291                                                                                                 'functionCall'         =>      'acos',
292                                                                                                 'argumentCount'        =>      '1'
293                                                                                                ),
294                                'ACOSH'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
295                                                                                                 'functionCall'         =>      'acosh',
296                                                                                                 'argumentCount'        =>      '1'
297                                                                                                ),
298                                'ADDRESS'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
299                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_LookupRef::CELL_ADDRESS',
300                                                                                                 'argumentCount'        =>      '2-5'
301                                                                                                ),
302                                'AMORDEGRC'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
303                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::AMORDEGRC',
304                                                                                                 'argumentCount'        =>      '6,7'
305                                                                                                ),
306                                'AMORLINC'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
307                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::AMORLINC',
308                                                                                                 'argumentCount'        =>      '6,7'
309                                                                                                ),
310                                'AND'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOGICAL,
311                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Logical::LOGICAL_AND',
312                                                                                                 'argumentCount'        =>      '1+'
313                                                                                                ),
314                                'AREAS'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
315                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
316                                                                                                 'argumentCount'        =>      '1'
317                                                                                                ),
318                                'ASC'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
319                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
320                                                                                                 'argumentCount'        =>      '1'
321                                                                                                ),
322                                'ASIN'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
323                                                                                                 'functionCall'         =>      'asin',
324                                                                                                 'argumentCount'        =>      '1'
325                                                                                                ),
326                                'ASINH'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
327                                                                                                 'functionCall'         =>      'asinh',
328                                                                                                 'argumentCount'        =>      '1'
329                                                                                                ),
330                                'ATAN'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
331                                                                                                 'functionCall'         =>      'atan',
332                                                                                                 'argumentCount'        =>      '1'
333                                                                                                ),
334                                'ATAN2'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
335                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::ATAN2',
336                                                                                                 'argumentCount'        =>      '2'
337                                                                                                ),
338                                'ATANH'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
339                                                                                                 'functionCall'         =>      'atanh',
340                                                                                                 'argumentCount'        =>      '1'
341                                                                                                ),
342                                'AVEDEV'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
343                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::AVEDEV',
344                                                                                                 'argumentCount'        =>      '1+'
345                                                                                                ),
346                                'AVERAGE'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
347                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::AVERAGE',
348                                                                                                 'argumentCount'        =>      '1+'
349                                                                                                ),
350                                'AVERAGEA'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
351                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::AVERAGEA',
352                                                                                                 'argumentCount'        =>      '1+'
353                                                                                                ),
354                                'AVERAGEIF'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
355                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::AVERAGEIF',
356                                                                                                 'argumentCount'        =>      '2,3'
357                                                                                                ),
358                                'AVERAGEIFS'                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
359                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
360                                                                                                 'argumentCount'        =>      '3+'
361                                                                                                ),
362                                'BAHTTEXT'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
363                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
364                                                                                                 'argumentCount'        =>      '1'
365                                                                                                ),
366                                'BESSELI'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
367                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::BESSELI',
368                                                                                                 'argumentCount'        =>      '2'
369                                                                                                ),
370                                'BESSELJ'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
371                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::BESSELJ',
372                                                                                                 'argumentCount'        =>      '2'
373                                                                                                ),
374                                'BESSELK'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
375                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::BESSELK',
376                                                                                                 'argumentCount'        =>      '2'
377                                                                                                ),
378                                'BESSELY'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
379                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::BESSELY',
380                                                                                                 'argumentCount'        =>      '2'
381                                                                                                ),
382                                'BETADIST'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
383                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::BETADIST',
384                                                                                                 'argumentCount'        =>      '3-5'
385                                                                                                ),
386                                'BETAINV'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
387                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::BETAINV',
388                                                                                                 'argumentCount'        =>      '3-5'
389                                                                                                ),
390                                'BIN2DEC'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
391                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::BINTODEC',
392                                                                                                 'argumentCount'        =>      '1'
393                                                                                                ),
394                                'BIN2HEX'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
395                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::BINTOHEX',
396                                                                                                 'argumentCount'        =>      '1,2'
397                                                                                                ),
398                                'BIN2OCT'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
399                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::BINTOOCT',
400                                                                                                 'argumentCount'        =>      '1,2'
401                                                                                                ),
402                                'BINOMDIST'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
403                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::BINOMDIST',
404                                                                                                 'argumentCount'        =>      '4'
405                                                                                                ),
406                                'CEILING'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
407                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::CEILING',
408                                                                                                 'argumentCount'        =>      '2'
409                                                                                                ),
410                                'CELL'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
411                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
412                                                                                                 'argumentCount'        =>      '1,2'
413                                                                                                ),
414                                'CHAR'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
415                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::CHARACTER',
416                                                                                                 'argumentCount'        =>      '1'
417                                                                                                ),
418                                'CHIDIST'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
419                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::CHIDIST',
420                                                                                                 'argumentCount'        =>      '2'
421                                                                                                ),
422                                'CHIINV'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
423                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::CHIINV',
424                                                                                                 'argumentCount'        =>      '2'
425                                                                                                ),
426                                'CHITEST'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
427                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
428                                                                                                 'argumentCount'        =>      '2'
429                                                                                                ),
430                                'CHOOSE'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
431                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_LookupRef::CHOOSE',
432                                                                                                 'argumentCount'        =>      '2+'
433                                                                                                ),
434                                'CLEAN'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
435                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::TRIMNONPRINTABLE',
436                                                                                                 'argumentCount'        =>      '1'
437                                                                                                ),
438                                'CODE'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
439                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::ASCIICODE',
440                                                                                                 'argumentCount'        =>      '1'
441                                                                                                ),
442                                'COLUMN'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
443                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_LookupRef::COLUMN',
444                                                                                                 'argumentCount'        =>      '-1',
445                                                                                                 'passByReference'      =>      array(TRUE)
446                                                                                                ),
447                                'COLUMNS'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
448                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_LookupRef::COLUMNS',
449                                                                                                 'argumentCount'        =>      '1'
450                                                                                                ),
451                                'COMBIN'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
452                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::COMBIN',
453                                                                                                 'argumentCount'        =>      '2'
454                                                                                                ),
455                                'COMPLEX'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
456                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::COMPLEX',
457                                                                                                 'argumentCount'        =>      '2,3'
458                                                                                                ),
459                                'CONCATENATE'                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
460                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::CONCATENATE',
461                                                                                                 'argumentCount'        =>      '1+'
462                                                                                                ),
463                                'CONFIDENCE'                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
464                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::CONFIDENCE',
465                                                                                                 'argumentCount'        =>      '3'
466                                                                                                ),
467                                'CONVERT'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
468                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::CONVERTUOM',
469                                                                                                 'argumentCount'        =>      '3'
470                                                                                                ),
471                                'CORREL'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
472                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::CORREL',
473                                                                                                 'argumentCount'        =>      '2'
474                                                                                                ),
475                                'COS'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
476                                                                                                 'functionCall'         =>      'cos',
477                                                                                                 'argumentCount'        =>      '1'
478                                                                                                ),
479                                'COSH'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
480                                                                                                 'functionCall'         =>      'cosh',
481                                                                                                 'argumentCount'        =>      '1'
482                                                                                                ),
483                                'COUNT'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
484                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::COUNT',
485                                                                                                 'argumentCount'        =>      '1+'
486                                                                                                ),
487                                'COUNTA'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
488                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::COUNTA',
489                                                                                                 'argumentCount'        =>      '1+'
490                                                                                                ),
491                                'COUNTBLANK'                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
492                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::COUNTBLANK',
493                                                                                                 'argumentCount'        =>      '1'
494                                                                                                ),
495                                'COUNTIF'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
496                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::COUNTIF',
497                                                                                                 'argumentCount'        =>      '2'
498                                                                                                ),
499                                'COUNTIFS'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
500                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
501                                                                                                 'argumentCount'        =>      '2'
502                                                                                                ),
503                                'COUPDAYBS'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
504                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::COUPDAYBS',
505                                                                                                 'argumentCount'        =>      '3,4'
506                                                                                                ),
507                                'COUPDAYS'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
508                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::COUPDAYS',
509                                                                                                 'argumentCount'        =>      '3,4'
510                                                                                                ),
511                                'COUPDAYSNC'                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
512                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::COUPDAYSNC',
513                                                                                                 'argumentCount'        =>      '3,4'
514                                                                                                ),
515                                'COUPNCD'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
516                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::COUPNCD',
517                                                                                                 'argumentCount'        =>      '3,4'
518                                                                                                ),
519                                'COUPNUM'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
520                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::COUPNUM',
521                                                                                                 'argumentCount'        =>      '3,4'
522                                                                                                ),
523                                'COUPPCD'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
524                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::COUPPCD',
525                                                                                                 'argumentCount'        =>      '3,4'
526                                                                                                ),
527                                'COVAR'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
528                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::COVAR',
529                                                                                                 'argumentCount'        =>      '2'
530                                                                                                ),
531                                'CRITBINOM'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
532                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::CRITBINOM',
533                                                                                                 'argumentCount'        =>      '3'
534                                                                                                ),
535                                'CUBEKPIMEMBER'                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_CUBE,
536                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
537                                                                                                 'argumentCount'        =>      '?'
538                                                                                                ),
539                                'CUBEMEMBER'                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_CUBE,
540                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
541                                                                                                 'argumentCount'        =>      '?'
542                                                                                                ),
543                                'CUBEMEMBERPROPERTY'    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_CUBE,
544                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
545                                                                                                 'argumentCount'        =>      '?'
546                                                                                                ),
547                                'CUBERANKEDMEMBER'              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_CUBE,
548                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
549                                                                                                 'argumentCount'        =>      '?'
550                                                                                                ),
551                                'CUBESET'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_CUBE,
552                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
553                                                                                                 'argumentCount'        =>      '?'
554                                                                                                ),
555                                'CUBESETCOUNT'                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_CUBE,
556                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
557                                                                                                 'argumentCount'        =>      '?'
558                                                                                                ),
559                                'CUBEVALUE'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_CUBE,
560                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
561                                                                                                 'argumentCount'        =>      '?'
562                                                                                                ),
563                                'CUMIPMT'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
564                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::CUMIPMT',
565                                                                                                 'argumentCount'        =>      '6'
566                                                                                                ),
567                                'CUMPRINC'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
568                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::CUMPRINC',
569                                                                                                 'argumentCount'        =>      '6'
570                                                                                                ),
571                                'DATE'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
572                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::DATE',
573                                                                                                 'argumentCount'        =>      '3'
574                                                                                                ),
575                                'DATEDIF'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
576                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::DATEDIF',
577                                                                                                 'argumentCount'        =>      '2,3'
578                                                                                                ),
579                                'DATEVALUE'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
580                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::DATEVALUE',
581                                                                                                 'argumentCount'        =>      '1'
582                                                                                                ),
583                                'DAVERAGE'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATABASE,
584                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Database::DAVERAGE',
585                                                                                                 'argumentCount'        =>      '3'
586                                                                                                ),
587                                'DAY'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
588                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::DAYOFMONTH',
589                                                                                                 'argumentCount'        =>      '1'
590                                                                                                ),
591                                'DAYS360'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
592                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::DAYS360',
593                                                                                                 'argumentCount'        =>      '2,3'
594                                                                                                ),
595                                'DB'                                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
596                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::DB',
597                                                                                                 'argumentCount'        =>      '4,5'
598                                                                                                ),
599                                'DCOUNT'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATABASE,
600                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Database::DCOUNT',
601                                                                                                 'argumentCount'        =>      '3'
602                                                                                                ),
603                                'DCOUNTA'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATABASE,
604                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Database::DCOUNTA',
605                                                                                                 'argumentCount'        =>      '3'
606                                                                                                ),
607                                'DDB'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
608                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::DDB',
609                                                                                                 'argumentCount'        =>      '4,5'
610                                                                                                ),
611                                'DEC2BIN'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
612                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::DECTOBIN',
613                                                                                                 'argumentCount'        =>      '1,2'
614                                                                                                ),
615                                'DEC2HEX'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
616                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::DECTOHEX',
617                                                                                                 'argumentCount'        =>      '1,2'
618                                                                                                ),
619                                'DEC2OCT'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
620                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::DECTOOCT',
621                                                                                                 'argumentCount'        =>      '1,2'
622                                                                                                ),
623                                'DEGREES'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
624                                                                                                 'functionCall'         =>      'rad2deg',
625                                                                                                 'argumentCount'        =>      '1'
626                                                                                                ),
627                                'DELTA'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
628                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::DELTA',
629                                                                                                 'argumentCount'        =>      '1,2'
630                                                                                                ),
631                                'DEVSQ'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
632                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::DEVSQ',
633                                                                                                 'argumentCount'        =>      '1+'
634                                                                                                ),
635                                'DGET'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATABASE,
636                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Database::DGET',
637                                                                                                 'argumentCount'        =>      '3'
638                                                                                                ),
639                                'DISC'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
640                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::DISC',
641                                                                                                 'argumentCount'        =>      '4,5'
642                                                                                                ),
643                                'DMAX'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATABASE,
644                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Database::DMAX',
645                                                                                                 'argumentCount'        =>      '3'
646                                                                                                ),
647                                'DMIN'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATABASE,
648                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Database::DMIN',
649                                                                                                 'argumentCount'        =>      '3'
650                                                                                                ),
651                                'DOLLAR'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
652                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::DOLLAR',
653                                                                                                 'argumentCount'        =>      '1,2'
654                                                                                                ),
655                                'DOLLARDE'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
656                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::DOLLARDE',
657                                                                                                 'argumentCount'        =>      '2'
658                                                                                                ),
659                                'DOLLARFR'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
660                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::DOLLARFR',
661                                                                                                 'argumentCount'        =>      '2'
662                                                                                                ),
663                                'DPRODUCT'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATABASE,
664                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Database::DPRODUCT',
665                                                                                                 'argumentCount'        =>      '3'
666                                                                                                ),
667                                'DSTDEV'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATABASE,
668                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Database::DSTDEV',
669                                                                                                 'argumentCount'        =>      '3'
670                                                                                                ),
671                                'DSTDEVP'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATABASE,
672                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Database::DSTDEVP',
673                                                                                                 'argumentCount'        =>      '3'
674                                                                                                ),
675                                'DSUM'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATABASE,
676                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Database::DSUM',
677                                                                                                 'argumentCount'        =>      '3'
678                                                                                                ),
679                                'DURATION'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
680                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
681                                                                                                 'argumentCount'        =>      '5,6'
682                                                                                                ),
683                                'DVAR'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATABASE,
684                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Database::DVAR',
685                                                                                                 'argumentCount'        =>      '3'
686                                                                                                ),
687                                'DVARP'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATABASE,
688                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Database::DVARP',
689                                                                                                 'argumentCount'        =>      '3'
690                                                                                                ),
691                                'EDATE'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
692                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::EDATE',
693                                                                                                 'argumentCount'        =>      '2'
694                                                                                                ),
695                                'EFFECT'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
696                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::EFFECT',
697                                                                                                 'argumentCount'        =>      '2'
698                                                                                                ),
699                                'EOMONTH'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
700                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::EOMONTH',
701                                                                                                 'argumentCount'        =>      '2'
702                                                                                                ),
703                                'ERF'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
704                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::ERF',
705                                                                                                 'argumentCount'        =>      '1,2'
706                                                                                                ),
707                                'ERFC'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
708                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::ERFC',
709                                                                                                 'argumentCount'        =>      '1'
710                                                                                                ),
711                                'ERROR.TYPE'                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
712                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::ERROR_TYPE',
713                                                                                                 'argumentCount'        =>      '1'
714                                                                                                ),
715                                'EVEN'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
716                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::EVEN',
717                                                                                                 'argumentCount'        =>      '1'
718                                                                                                ),
719                                'EXACT'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
720                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
721                                                                                                 'argumentCount'        =>      '2'
722                                                                                                ),
723                                'EXP'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
724                                                                                                 'functionCall'         =>      'exp',
725                                                                                                 'argumentCount'        =>      '1'
726                                                                                                ),
727                                'EXPONDIST'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
728                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::EXPONDIST',
729                                                                                                 'argumentCount'        =>      '3'
730                                                                                                ),
731                                'FACT'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
732                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::FACT',
733                                                                                                 'argumentCount'        =>      '1'
734                                                                                                ),
735                                'FACTDOUBLE'                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
736                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::FACTDOUBLE',
737                                                                                                 'argumentCount'        =>      '1'
738                                                                                                ),
739                                'FALSE'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOGICAL,
740                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Logical::FALSE',
741                                                                                                 'argumentCount'        =>      '0'
742                                                                                                ),
743                                'FDIST'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
744                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
745                                                                                                 'argumentCount'        =>      '3'
746                                                                                                ),
747                                'FIND'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
748                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::SEARCHSENSITIVE',
749                                                                                                 'argumentCount'        =>      '2,3'
750                                                                                                ),
751                                'FINDB'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
752                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::SEARCHSENSITIVE',
753                                                                                                 'argumentCount'        =>      '2,3'
754                                                                                                ),
755                                'FINV'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
756                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
757                                                                                                 'argumentCount'        =>      '3'
758                                                                                                ),
759                                'FISHER'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
760                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::FISHER',
761                                                                                                 'argumentCount'        =>      '1'
762                                                                                                ),
763                                'FISHERINV'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
764                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::FISHERINV',
765                                                                                                 'argumentCount'        =>      '1'
766                                                                                                ),
767                                'FIXED'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
768                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::FIXEDFORMAT',
769                                                                                                 'argumentCount'        =>      '1-3'
770                                                                                                ),
771                                'FLOOR'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
772                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::FLOOR',
773                                                                                                 'argumentCount'        =>      '2'
774                                                                                                ),
775                                'FORECAST'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
776                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::FORECAST',
777                                                                                                 'argumentCount'        =>      '3'
778                                                                                                ),
779                                'FREQUENCY'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
780                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
781                                                                                                 'argumentCount'        =>      '2'
782                                                                                                ),
783                                'FTEST'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
784                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
785                                                                                                 'argumentCount'        =>      '2'
786                                                                                                ),
787                                'FV'                                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
788                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::FV',
789                                                                                                 'argumentCount'        =>      '3-5'
790                                                                                                ),
791                                'FVSCHEDULE'                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
792                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::FVSCHEDULE',
793                                                                                                 'argumentCount'        =>      '2'
794                                                                                                ),
795                                'GAMMADIST'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
796                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::GAMMADIST',
797                                                                                                 'argumentCount'        =>      '4'
798                                                                                                ),
799                                'GAMMAINV'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
800                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::GAMMAINV',
801                                                                                                 'argumentCount'        =>      '3'
802                                                                                                ),
803                                'GAMMALN'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
804                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::GAMMALN',
805                                                                                                 'argumentCount'        =>      '1'
806                                                                                                ),
807                                'GCD'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
808                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::GCD',
809                                                                                                 'argumentCount'        =>      '1+'
810                                                                                                ),
811                                'GEOMEAN'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
812                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::GEOMEAN',
813                                                                                                 'argumentCount'        =>      '1+'
814                                                                                                ),
815                                'GESTEP'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
816                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::GESTEP',
817                                                                                                 'argumentCount'        =>      '1,2'
818                                                                                                ),
819                                'GETPIVOTDATA'                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
820                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
821                                                                                                 'argumentCount'        =>      '2+'
822                                                                                                ),
823                                'GROWTH'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
824                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::GROWTH',
825                                                                                                 'argumentCount'        =>      '1-4'
826                                                                                                ),
827                                'HARMEAN'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
828                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::HARMEAN',
829                                                                                                 'argumentCount'        =>      '1+'
830                                                                                                ),
831                                'HEX2BIN'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
832                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::HEXTOBIN',
833                                                                                                 'argumentCount'        =>      '1,2'
834                                                                                                ),
835                                'HEX2DEC'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
836                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::HEXTODEC',
837                                                                                                 'argumentCount'        =>      '1'
838                                                                                                ),
839                                'HEX2OCT'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
840                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::HEXTOOCT',
841                                                                                                 'argumentCount'        =>      '1,2'
842                                                                                                ),
843                                'HLOOKUP'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
844                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_LookupRef::HLOOKUP',
845                                                                                                 'argumentCount'        =>      '3,4'
846                                                                                                ),
847                                'HOUR'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
848                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::HOUROFDAY',
849                                                                                                 'argumentCount'        =>      '1'
850                                                                                                ),
851                                'HYPERLINK'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
852                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_LookupRef::HYPERLINK',
853                                                                                                 'argumentCount'        =>      '1,2',
854                                                                                                 'passCellReference'=>  TRUE
855                                                                                                ),
856                                'HYPGEOMDIST'                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
857                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::HYPGEOMDIST',
858                                                                                                 'argumentCount'        =>      '4'
859                                                                                                ),
860                                'IF'                                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOGICAL,
861                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Logical::STATEMENT_IF',
862                                                                                                 'argumentCount'        =>      '1-3'
863                                                                                                ),
864                                'IFERROR'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOGICAL,
865                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Logical::IFERROR',
866                                                                                                 'argumentCount'        =>      '2'
867                                                                                                ),
868                                'IMABS'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
869                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::IMABS',
870                                                                                                 'argumentCount'        =>      '1'
871                                                                                                ),
872                                'IMAGINARY'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
873                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::IMAGINARY',
874                                                                                                 'argumentCount'        =>      '1'
875                                                                                                ),
876                                'IMARGUMENT'                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
877                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::IMARGUMENT',
878                                                                                                 'argumentCount'        =>      '1'
879                                                                                                ),
880                                'IMCONJUGATE'                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
881                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::IMCONJUGATE',
882                                                                                                 'argumentCount'        =>      '1'
883                                                                                                ),
884                                'IMCOS'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
885                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::IMCOS',
886                                                                                                 'argumentCount'        =>      '1'
887                                                                                                ),
888                                'IMDIV'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
889                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::IMDIV',
890                                                                                                 'argumentCount'        =>      '2'
891                                                                                                ),
892                                'IMEXP'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
893                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::IMEXP',
894                                                                                                 'argumentCount'        =>      '1'
895                                                                                                ),
896                                'IMLN'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
897                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::IMLN',
898                                                                                                 'argumentCount'        =>      '1'
899                                                                                                ),
900                                'IMLOG10'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
901                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::IMLOG10',
902                                                                                                 'argumentCount'        =>      '1'
903                                                                                                ),
904                                'IMLOG2'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
905                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::IMLOG2',
906                                                                                                 'argumentCount'        =>      '1'
907                                                                                                ),
908                                'IMPOWER'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
909                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::IMPOWER',
910                                                                                                 'argumentCount'        =>      '2'
911                                                                                                ),
912                                'IMPRODUCT'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
913                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::IMPRODUCT',
914                                                                                                 'argumentCount'        =>      '1+'
915                                                                                                ),
916                                'IMREAL'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
917                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::IMREAL',
918                                                                                                 'argumentCount'        =>      '1'
919                                                                                                ),
920                                'IMSIN'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
921                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::IMSIN',
922                                                                                                 'argumentCount'        =>      '1'
923                                                                                                ),
924                                'IMSQRT'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
925                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::IMSQRT',
926                                                                                                 'argumentCount'        =>      '1'
927                                                                                                ),
928                                'IMSUB'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
929                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::IMSUB',
930                                                                                                 'argumentCount'        =>      '2'
931                                                                                                ),
932                                'IMSUM'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
933                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::IMSUM',
934                                                                                                 'argumentCount'        =>      '1+'
935                                                                                                ),
936                                'INDEX'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
937                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_LookupRef::INDEX',
938                                                                                                 'argumentCount'        =>      '1-4'
939                                                                                                ),
940                                'INDIRECT'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
941                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_LookupRef::INDIRECT',
942                                                                                                 'argumentCount'        =>      '1,2',
943                                                                                                 'passCellReference'=>  TRUE
944                                                                                                ),
945                                'INFO'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
946                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
947                                                                                                 'argumentCount'        =>      '1'
948                                                                                                ),
949                                'INT'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
950                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::INT',
951                                                                                                 'argumentCount'        =>      '1'
952                                                                                                ),
953                                'INTERCEPT'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
954                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::INTERCEPT',
955                                                                                                 'argumentCount'        =>      '2'
956                                                                                                ),
957                                'INTRATE'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
958                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::INTRATE',
959                                                                                                 'argumentCount'        =>      '4,5'
960                                                                                                ),
961                                'IPMT'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
962                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::IPMT',
963                                                                                                 'argumentCount'        =>      '4-6'
964                                                                                                ),
965                                'IRR'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
966                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::IRR',
967                                                                                                 'argumentCount'        =>      '1,2'
968                                                                                                ),
969                                'ISBLANK'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
970                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::IS_BLANK',
971                                                                                                 'argumentCount'        =>      '1'
972                                                                                                ),
973                                'ISERR'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
974                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::IS_ERR',
975                                                                                                 'argumentCount'        =>      '1'
976                                                                                                ),
977                                'ISERROR'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
978                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::IS_ERROR',
979                                                                                                 'argumentCount'        =>      '1'
980                                                                                                ),
981                                'ISEVEN'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
982                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::IS_EVEN',
983                                                                                                 'argumentCount'        =>      '1'
984                                                                                                ),
985                                'ISLOGICAL'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
986                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::IS_LOGICAL',
987                                                                                                 'argumentCount'        =>      '1'
988                                                                                                ),
989                                'ISNA'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
990                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::IS_NA',
991                                                                                                 'argumentCount'        =>      '1'
992                                                                                                ),
993                                'ISNONTEXT'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
994                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::IS_NONTEXT',
995                                                                                                 'argumentCount'        =>      '1'
996                                                                                                ),
997                                'ISNUMBER'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
998                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::IS_NUMBER',
999                                                                                                 'argumentCount'        =>      '1'
1000                                                                                                ),
1001                                'ISODD'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
1002                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::IS_ODD',
1003                                                                                                 'argumentCount'        =>      '1'
1004                                                                                                ),
1005                                'ISPMT'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1006                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::ISPMT',
1007                                                                                                 'argumentCount'        =>      '4'
1008                                                                                                ),
1009                                'ISREF'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
1010                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
1011                                                                                                 'argumentCount'        =>      '1'
1012                                                                                                ),
1013                                'ISTEXT'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
1014                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::IS_TEXT',
1015                                                                                                 'argumentCount'        =>      '1'
1016                                                                                                ),
1017                                'JIS'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1018                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
1019                                                                                                 'argumentCount'        =>      '1'
1020                                                                                                ),
1021                                'KURT'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1022                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::KURT',
1023                                                                                                 'argumentCount'        =>      '1+'
1024                                                                                                ),
1025                                'LARGE'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1026                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::LARGE',
1027                                                                                                 'argumentCount'        =>      '2'
1028                                                                                                ),
1029                                'LCM'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1030                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::LCM',
1031                                                                                                 'argumentCount'        =>      '1+'
1032                                                                                                ),
1033                                'LEFT'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1034                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::LEFT',
1035                                                                                                 'argumentCount'        =>      '1,2'
1036                                                                                                ),
1037                                'LEFTB'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1038                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::LEFT',
1039                                                                                                 'argumentCount'        =>      '1,2'
1040                                                                                                ),
1041                                'LEN'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1042                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::STRINGLENGTH',
1043                                                                                                 'argumentCount'        =>      '1'
1044                                                                                                ),
1045                                'LENB'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1046                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::STRINGLENGTH',
1047                                                                                                 'argumentCount'        =>      '1'
1048                                                                                                ),
1049                                'LINEST'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1050                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::LINEST',
1051                                                                                                 'argumentCount'        =>      '1-4'
1052                                                                                                ),
1053                                'LN'                                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1054                                                                                                 'functionCall'         =>      'log',
1055                                                                                                 'argumentCount'        =>      '1'
1056                                                                                                ),
1057                                'LOG'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1058                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::LOG_BASE',
1059                                                                                                 'argumentCount'        =>      '1,2'
1060                                                                                                ),
1061                                'LOG10'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1062                                                                                                 'functionCall'         =>      'log10',
1063                                                                                                 'argumentCount'        =>      '1'
1064                                                                                                ),
1065                                'LOGEST'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1066                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::LOGEST',
1067                                                                                                 'argumentCount'        =>      '1-4'
1068                                                                                                ),
1069                                'LOGINV'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1070                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::LOGINV',
1071                                                                                                 'argumentCount'        =>      '3'
1072                                                                                                ),
1073                                'LOGNORMDIST'                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1074                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::LOGNORMDIST',
1075                                                                                                 'argumentCount'        =>      '3'
1076                                                                                                ),
1077                                'LOOKUP'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
1078                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_LookupRef::LOOKUP',
1079                                                                                                 'argumentCount'        =>      '2,3'
1080                                                                                                ),
1081                                'LOWER'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1082                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::LOWERCASE',
1083                                                                                                 'argumentCount'        =>      '1'
1084                                                                                                ),
1085                                'MATCH'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
1086                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_LookupRef::MATCH',
1087                                                                                                 'argumentCount'        =>      '2,3'
1088                                                                                                ),
1089                                'MAX'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1090                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::MAX',
1091                                                                                                 'argumentCount'        =>      '1+'
1092                                                                                                ),
1093                                'MAXA'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1094                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::MAXA',
1095                                                                                                 'argumentCount'        =>      '1+'
1096                                                                                                ),
1097                                'MAXIF'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1098                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::MAXIF',
1099                                                                                                 'argumentCount'        =>      '2+'
1100                                                                                                ),
1101                                'MDETERM'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1102                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::MDETERM',
1103                                                                                                 'argumentCount'        =>      '1'
1104                                                                                                ),
1105                                'MDURATION'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1106                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
1107                                                                                                 'argumentCount'        =>      '5,6'
1108                                                                                                ),
1109                                'MEDIAN'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1110                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::MEDIAN',
1111                                                                                                 'argumentCount'        =>      '1+'
1112                                                                                                ),
1113                                'MEDIANIF'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1114                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
1115                                                                                                 'argumentCount'        =>      '2+'
1116                                                                                                ),
1117                                'MID'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1118                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::MID',
1119                                                                                                 'argumentCount'        =>      '3'
1120                                                                                                ),
1121                                'MIDB'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1122                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::MID',
1123                                                                                                 'argumentCount'        =>      '3'
1124                                                                                                ),
1125                                'MIN'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1126                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::MIN',
1127                                                                                                 'argumentCount'        =>      '1+'
1128                                                                                                ),
1129                                'MINA'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1130                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::MINA',
1131                                                                                                 'argumentCount'        =>      '1+'
1132                                                                                                ),
1133                                'MINIF'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1134                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::MINIF',
1135                                                                                                 'argumentCount'        =>      '2+'
1136                                                                                                ),
1137                                'MINUTE'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1138                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::MINUTEOFHOUR',
1139                                                                                                 'argumentCount'        =>      '1'
1140                                                                                                ),
1141                                'MINVERSE'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1142                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::MINVERSE',
1143                                                                                                 'argumentCount'        =>      '1'
1144                                                                                                ),
1145                                'MIRR'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1146                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::MIRR',
1147                                                                                                 'argumentCount'        =>      '3'
1148                                                                                                ),
1149                                'MMULT'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1150                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::MMULT',
1151                                                                                                 'argumentCount'        =>      '2'
1152                                                                                                ),
1153                                'MOD'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1154                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::MOD',
1155                                                                                                 'argumentCount'        =>      '2'
1156                                                                                                ),
1157                                'MODE'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1158                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::MODE',
1159                                                                                                 'argumentCount'        =>      '1+'
1160                                                                                                ),
1161                                'MONTH'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1162                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::MONTHOFYEAR',
1163                                                                                                 'argumentCount'        =>      '1'
1164                                                                                                ),
1165                                'MROUND'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1166                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::MROUND',
1167                                                                                                 'argumentCount'        =>      '2'
1168                                                                                                ),
1169                                'MULTINOMIAL'                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1170                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::MULTINOMIAL',
1171                                                                                                 'argumentCount'        =>      '1+'
1172                                                                                                ),
1173                                'N'                                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
1174                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::N',
1175                                                                                                 'argumentCount'        =>      '1'
1176                                                                                                ),
1177                                'NA'                                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
1178                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::NA',
1179                                                                                                 'argumentCount'        =>      '0'
1180                                                                                                ),
1181                                'NEGBINOMDIST'                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1182                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::NEGBINOMDIST',
1183                                                                                                 'argumentCount'        =>      '3'
1184                                                                                                ),
1185                                'NETWORKDAYS'                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1186                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::NETWORKDAYS',
1187                                                                                                 'argumentCount'        =>      '2+'
1188                                                                                                ),
1189                                'NOMINAL'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1190                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::NOMINAL',
1191                                                                                                 'argumentCount'        =>      '2'
1192                                                                                                ),
1193                                'NORMDIST'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1194                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::NORMDIST',
1195                                                                                                 'argumentCount'        =>      '4'
1196                                                                                                ),
1197                                'NORMINV'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1198                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::NORMINV',
1199                                                                                                 'argumentCount'        =>      '3'
1200                                                                                                ),
1201                                'NORMSDIST'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1202                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::NORMSDIST',
1203                                                                                                 'argumentCount'        =>      '1'
1204                                                                                                ),
1205                                'NORMSINV'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1206                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::NORMSINV',
1207                                                                                                 'argumentCount'        =>      '1'
1208                                                                                                ),
1209                                'NOT'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOGICAL,
1210                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Logical::NOT',
1211                                                                                                 'argumentCount'        =>      '1'
1212                                                                                                ),
1213                                'NOW'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1214                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::DATETIMENOW',
1215                                                                                                 'argumentCount'        =>      '0'
1216                                                                                                ),
1217                                'NPER'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1218                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::NPER',
1219                                                                                                 'argumentCount'        =>      '3-5'
1220                                                                                                ),
1221                                'NPV'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1222                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::NPV',
1223                                                                                                 'argumentCount'        =>      '2+'
1224                                                                                                ),
1225                                'OCT2BIN'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
1226                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::OCTTOBIN',
1227                                                                                                 'argumentCount'        =>      '1,2'
1228                                                                                                ),
1229                                'OCT2DEC'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
1230                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::OCTTODEC',
1231                                                                                                 'argumentCount'        =>      '1'
1232                                                                                                ),
1233                                'OCT2HEX'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
1234                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Engineering::OCTTOHEX',
1235                                                                                                 'argumentCount'        =>      '1,2'
1236                                                                                                ),
1237                                'ODD'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1238                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::ODD',
1239                                                                                                 'argumentCount'        =>      '1'
1240                                                                                                ),
1241                                'ODDFPRICE'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1242                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
1243                                                                                                 'argumentCount'        =>      '8,9'
1244                                                                                                ),
1245                                'ODDFYIELD'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1246                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
1247                                                                                                 'argumentCount'        =>      '8,9'
1248                                                                                                ),
1249                                'ODDLPRICE'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1250                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
1251                                                                                                 'argumentCount'        =>      '7,8'
1252                                                                                                ),
1253                                'ODDLYIELD'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1254                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
1255                                                                                                 'argumentCount'        =>      '7,8'
1256                                                                                                ),
1257                                'OFFSET'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
1258                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_LookupRef::OFFSET',
1259                                                                                                 'argumentCount'        =>      '3,5',
1260                                                                                                 'passCellReference'=>  TRUE,
1261                                                                                                 'passByReference'      =>      array(TRUE)
1262                                                                                                ),
1263                                'OR'                                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOGICAL,
1264                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Logical::LOGICAL_OR',
1265                                                                                                 'argumentCount'        =>      '1+'
1266                                                                                                ),
1267                                'PEARSON'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1268                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::CORREL',
1269                                                                                                 'argumentCount'        =>      '2'
1270                                                                                                ),
1271                                'PERCENTILE'                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1272                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::PERCENTILE',
1273                                                                                                 'argumentCount'        =>      '2'
1274                                                                                                ),
1275                                'PERCENTRANK'                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1276                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::PERCENTRANK',
1277                                                                                                 'argumentCount'        =>      '2,3'
1278                                                                                                ),
1279                                'PERMUT'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1280                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::PERMUT',
1281                                                                                                 'argumentCount'        =>      '2'
1282                                                                                                ),
1283                                'PHONETIC'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1284                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
1285                                                                                                 'argumentCount'        =>      '1'
1286                                                                                                ),
1287                                'PI'                                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1288                                                                                                 'functionCall'         =>      'pi',
1289                                                                                                 'argumentCount'        =>      '0'
1290                                                                                                ),
1291                                'PMT'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1292                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::PMT',
1293                                                                                                 'argumentCount'        =>      '3-5'
1294                                                                                                ),
1295                                'POISSON'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1296                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::POISSON',
1297                                                                                                 'argumentCount'        =>      '3'
1298                                                                                                ),
1299                                'POWER'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1300                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::POWER',
1301                                                                                                 'argumentCount'        =>      '2'
1302                                                                                                ),
1303                                'PPMT'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1304                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::PPMT',
1305                                                                                                 'argumentCount'        =>      '4-6'
1306                                                                                                ),
1307                                'PRICE'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1308                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::PRICE',
1309                                                                                                 'argumentCount'        =>      '6,7'
1310                                                                                                ),
1311                                'PRICEDISC'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1312                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::PRICEDISC',
1313                                                                                                 'argumentCount'        =>      '4,5'
1314                                                                                                ),
1315                                'PRICEMAT'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1316                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::PRICEMAT',
1317                                                                                                 'argumentCount'        =>      '5,6'
1318                                                                                                ),
1319                                'PROB'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1320                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
1321                                                                                                 'argumentCount'        =>      '3,4'
1322                                                                                                ),
1323                                'PRODUCT'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1324                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::PRODUCT',
1325                                                                                                 'argumentCount'        =>      '1+'
1326                                                                                                ),
1327                                'PROPER'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1328                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::PROPERCASE',
1329                                                                                                 'argumentCount'        =>      '1'
1330                                                                                                ),
1331                                'PV'                                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1332                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::PV',
1333                                                                                                 'argumentCount'        =>      '3-5'
1334                                                                                                ),
1335                                'QUARTILE'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1336                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::QUARTILE',
1337                                                                                                 'argumentCount'        =>      '2'
1338                                                                                                ),
1339                                'QUOTIENT'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1340                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::QUOTIENT',
1341                                                                                                 'argumentCount'        =>      '2'
1342                                                                                                ),
1343                                'RADIANS'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1344                                                                                                 'functionCall'         =>      'deg2rad',
1345                                                                                                 'argumentCount'        =>      '1'
1346                                                                                                ),
1347                                'RAND'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1348                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::RAND',
1349                                                                                                 'argumentCount'        =>      '0'
1350                                                                                                ),
1351                                'RANDBETWEEN'                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1352                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::RAND',
1353                                                                                                 'argumentCount'        =>      '2'
1354                                                                                                ),
1355                                'RANK'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1356                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::RANK',
1357                                                                                                 'argumentCount'        =>      '2,3'
1358                                                                                                ),
1359                                'RATE'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1360                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::RATE',
1361                                                                                                 'argumentCount'        =>      '3-6'
1362                                                                                                ),
1363                                'RECEIVED'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1364                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::RECEIVED',
1365                                                                                                 'argumentCount'        =>      '4-5'
1366                                                                                                ),
1367                                'REPLACE'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1368                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::REPLACE',
1369                                                                                                 'argumentCount'        =>      '4'
1370                                                                                                ),
1371                                'REPLACEB'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1372                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::REPLACE',
1373                                                                                                 'argumentCount'        =>      '4'
1374                                                                                                ),
1375                                'REPT'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1376                                                                                                 'functionCall'         =>      'str_repeat',
1377                                                                                                 'argumentCount'        =>      '2'
1378                                                                                                ),
1379                                'RIGHT'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1380                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::RIGHT',
1381                                                                                                 'argumentCount'        =>      '1,2'
1382                                                                                                ),
1383                                'RIGHTB'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1384                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::RIGHT',
1385                                                                                                 'argumentCount'        =>      '1,2'
1386                                                                                                ),
1387                                'ROMAN'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1388                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::ROMAN',
1389                                                                                                 'argumentCount'        =>      '1,2'
1390                                                                                                ),
1391                                'ROUND'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1392                                                                                                 'functionCall'         =>      'round',
1393                                                                                                 'argumentCount'        =>      '2'
1394                                                                                                ),
1395                                'ROUNDDOWN'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1396                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::ROUNDDOWN',
1397                                                                                                 'argumentCount'        =>      '2'
1398                                                                                                ),
1399                                'ROUNDUP'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1400                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::ROUNDUP',
1401                                                                                                 'argumentCount'        =>      '2'
1402                                                                                                ),
1403                                'ROW'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
1404                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_LookupRef::ROW',
1405                                                                                                 'argumentCount'        =>      '-1',
1406                                                                                                 'passByReference'      =>      array(TRUE)
1407                                                                                                ),
1408                                'ROWS'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
1409                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_LookupRef::ROWS',
1410                                                                                                 'argumentCount'        =>      '1'
1411                                                                                                ),
1412                                'RSQ'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1413                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::RSQ',
1414                                                                                                 'argumentCount'        =>      '2'
1415                                                                                                ),
1416                                'RTD'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
1417                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
1418                                                                                                 'argumentCount'        =>      '1+'
1419                                                                                                ),
1420                                'SEARCH'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1421                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::SEARCHINSENSITIVE',
1422                                                                                                 'argumentCount'        =>      '2,3'
1423                                                                                                ),
1424                                'SEARCHB'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1425                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::SEARCHINSENSITIVE',
1426                                                                                                 'argumentCount'        =>      '2,3'
1427                                                                                                ),
1428                                'SECOND'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1429                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::SECONDOFMINUTE',
1430                                                                                                 'argumentCount'        =>      '1'
1431                                                                                                ),
1432                                'SERIESSUM'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1433                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::SERIESSUM',
1434                                                                                                 'argumentCount'        =>      '4'
1435                                                                                                ),
1436                                'SIGN'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1437                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::SIGN',
1438                                                                                                 'argumentCount'        =>      '1'
1439                                                                                                ),
1440                                'SIN'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1441                                                                                                 'functionCall'         =>      'sin',
1442                                                                                                 'argumentCount'        =>      '1'
1443                                                                                                ),
1444                                'SINH'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1445                                                                                                 'functionCall'         =>      'sinh',
1446                                                                                                 'argumentCount'        =>      '1'
1447                                                                                                ),
1448                                'SKEW'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1449                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::SKEW',
1450                                                                                                 'argumentCount'        =>      '1+'
1451                                                                                                ),
1452                                'SLN'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1453                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::SLN',
1454                                                                                                 'argumentCount'        =>      '3'
1455                                                                                                ),
1456                                'SLOPE'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1457                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::SLOPE',
1458                                                                                                 'argumentCount'        =>      '2'
1459                                                                                                ),
1460                                'SMALL'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1461                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::SMALL',
1462                                                                                                 'argumentCount'        =>      '2'
1463                                                                                                ),
1464                                'SQRT'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1465                                                                                                 'functionCall'         =>      'sqrt',
1466                                                                                                 'argumentCount'        =>      '1'
1467                                                                                                ),
1468                                'SQRTPI'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1469                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::SQRTPI',
1470                                                                                                 'argumentCount'        =>      '1'
1471                                                                                                ),
1472                                'STANDARDIZE'                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1473                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::STANDARDIZE',
1474                                                                                                 'argumentCount'        =>      '3'
1475                                                                                                ),
1476                                'STDEV'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1477                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::STDEV',
1478                                                                                                 'argumentCount'        =>      '1+'
1479                                                                                                ),
1480                                'STDEVA'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1481                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::STDEVA',
1482                                                                                                 'argumentCount'        =>      '1+'
1483                                                                                                ),
1484                                'STDEVP'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1485                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::STDEVP',
1486                                                                                                 'argumentCount'        =>      '1+'
1487                                                                                                ),
1488                                'STDEVPA'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1489                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::STDEVPA',
1490                                                                                                 'argumentCount'        =>      '1+'
1491                                                                                                ),
1492                                'STEYX'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1493                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::STEYX',
1494                                                                                                 'argumentCount'        =>      '2'
1495                                                                                                ),
1496                                'SUBSTITUTE'                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1497                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::SUBSTITUTE',
1498                                                                                                 'argumentCount'        =>      '3,4'
1499                                                                                                ),
1500                                'SUBTOTAL'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1501                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::SUBTOTAL',
1502                                                                                                 'argumentCount'        =>      '2+'
1503                                                                                                ),
1504                                'SUM'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1505                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::SUM',
1506                                                                                                 'argumentCount'        =>      '1+'
1507                                                                                                ),
1508                                'SUMIF'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1509                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::SUMIF',
1510                                                                                                 'argumentCount'        =>      '2,3'
1511                                                                                                ),
1512                                'SUMIFS'                                => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1513                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
1514                                                                                                 'argumentCount'        =>      '?'
1515                                                                                                ),
1516                                'SUMPRODUCT'                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1517                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::SUMPRODUCT',
1518                                                                                                 'argumentCount'        =>      '1+'
1519                                                                                                ),
1520                                'SUMSQ'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1521                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::SUMSQ',
1522                                                                                                 'argumentCount'        =>      '1+'
1523                                                                                                ),
1524                                'SUMX2MY2'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1525                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::SUMX2MY2',
1526                                                                                                 'argumentCount'        =>      '2'
1527                                                                                                ),
1528                                'SUMX2PY2'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1529                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::SUMX2PY2',
1530                                                                                                 'argumentCount'        =>      '2'
1531                                                                                                ),
1532                                'SUMXMY2'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1533                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::SUMXMY2',
1534                                                                                                 'argumentCount'        =>      '2'
1535                                                                                                ),
1536                                'SYD'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1537                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::SYD',
1538                                                                                                 'argumentCount'        =>      '4'
1539                                                                                                ),
1540                                'T'                                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1541                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::RETURNSTRING',
1542                                                                                                 'argumentCount'        =>      '1'
1543                                                                                                ),
1544                                'TAN'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1545                                                                                                 'functionCall'         =>      'tan',
1546                                                                                                 'argumentCount'        =>      '1'
1547                                                                                                ),
1548                                'TANH'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1549                                                                                                 'functionCall'         =>      'tanh',
1550                                                                                                 'argumentCount'        =>      '1'
1551                                                                                                ),
1552                                'TBILLEQ'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1553                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::TBILLEQ',
1554                                                                                                 'argumentCount'        =>      '3'
1555                                                                                                ),
1556                                'TBILLPRICE'                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1557                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::TBILLPRICE',
1558                                                                                                 'argumentCount'        =>      '3'
1559                                                                                                ),
1560                                'TBILLYIELD'                    => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1561                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::TBILLYIELD',
1562                                                                                                 'argumentCount'        =>      '3'
1563                                                                                                ),
1564                                'TDIST'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1565                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::TDIST',
1566                                                                                                 'argumentCount'        =>      '3'
1567                                                                                                ),
1568                                'TEXT'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1569                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::TEXTFORMAT',
1570                                                                                                 'argumentCount'        =>      '2'
1571                                                                                                ),
1572                                'TIME'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1573                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::TIME',
1574                                                                                                 'argumentCount'        =>      '3'
1575                                                                                                ),
1576                                'TIMEVALUE'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1577                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::TIMEVALUE',
1578                                                                                                 'argumentCount'        =>      '1'
1579                                                                                                ),
1580                                'TINV'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1581                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::TINV',
1582                                                                                                 'argumentCount'        =>      '2'
1583                                                                                                ),
1584                                'TODAY'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1585                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::DATENOW',
1586                                                                                                 'argumentCount'        =>      '0'
1587                                                                                                ),
1588                                'TRANSPOSE'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
1589                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_LookupRef::TRANSPOSE',
1590                                                                                                 'argumentCount'        =>      '1'
1591                                                                                                ),
1592                                'TREND'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1593                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::TREND',
1594                                                                                                 'argumentCount'        =>      '1-4'
1595                                                                                                ),
1596                                'TRIM'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1597                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::TRIMSPACES',
1598                                                                                                 'argumentCount'        =>      '1'
1599                                                                                                ),
1600                                'TRIMMEAN'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1601                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::TRIMMEAN',
1602                                                                                                 'argumentCount'        =>      '2'
1603                                                                                                ),
1604                                'TRUE'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOGICAL,
1605                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Logical::TRUE',
1606                                                                                                 'argumentCount'        =>      '0'
1607                                                                                                ),
1608                                'TRUNC'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1609                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_MathTrig::TRUNC',
1610                                                                                                 'argumentCount'        =>      '1,2'
1611                                                                                                ),
1612                                'TTEST'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1613                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
1614                                                                                                 'argumentCount'        =>      '4'
1615                                                                                                ),
1616                                'TYPE'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
1617                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::TYPE',
1618                                                                                                 'argumentCount'        =>      '1'
1619                                                                                                ),
1620                                'UPPER'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1621                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_TextData::UPPERCASE',
1622                                                                                                 'argumentCount'        =>      '1'
1623                                                                                                ),
1624                                'USDOLLAR'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1625                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
1626                                                                                                 'argumentCount'        =>      '2'
1627                                                                                                ),
1628                                'VALUE'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1629                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
1630                                                                                                 'argumentCount'        =>      '1'
1631                                                                                                ),
1632                                'VAR'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1633                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::VARFunc',
1634                                                                                                 'argumentCount'        =>      '1+'
1635                                                                                                ),
1636                                'VARA'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1637                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::VARA',
1638                                                                                                 'argumentCount'        =>      '1+'
1639                                                                                                ),
1640                                'VARP'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1641                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::VARP',
1642                                                                                                 'argumentCount'        =>      '1+'
1643                                                                                                ),
1644                                'VARPA'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1645                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::VARPA',
1646                                                                                                 'argumentCount'        =>      '1+'
1647                                                                                                ),
1648                                'VDB'                                   => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1649                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
1650                                                                                                 'argumentCount'        =>      '5-7'
1651                                                                                                ),
1652                                'VERSION'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
1653                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::VERSION',
1654                                                                                                 'argumentCount'        =>      '0'
1655                                                                                                ),
1656                                'VLOOKUP'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
1657                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_LookupRef::VLOOKUP',
1658                                                                                                 'argumentCount'        =>      '3,4'
1659                                                                                                ),
1660                                'WEEKDAY'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1661                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::DAYOFWEEK',
1662                                                                                                 'argumentCount'        =>      '1,2'
1663                                                                                                ),
1664                                'WEEKNUM'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1665                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::WEEKOFYEAR',
1666                                                                                                 'argumentCount'        =>      '1,2'
1667                                                                                                ),
1668                                'WEIBULL'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1669                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::WEIBULL',
1670                                                                                                 'argumentCount'        =>      '4'
1671                                                                                                ),
1672                                'WORKDAY'                               => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1673                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::WORKDAY',
1674                                                                                                 'argumentCount'        =>      '2+'
1675                                                                                                ),
1676                                'XIRR'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1677                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::XIRR',
1678                                                                                                 'argumentCount'        =>      '2,3'
1679                                                                                                ),
1680                                'XNPV'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1681                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::XNPV',
1682                                                                                                 'argumentCount'        =>      '3'
1683                                                                                                ),
1684                                'YEAR'                                  => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1685                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::YEAR',
1686                                                                                                 'argumentCount'        =>      '1'
1687                                                                                                ),
1688                                'YEARFRAC'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1689                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_DateTime::YEARFRAC',
1690                                                                                                 'argumentCount'        =>      '2,3'
1691                                                                                                ),
1692                                'YIELD'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1693                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Functions::DUMMY',
1694                                                                                                 'argumentCount'        =>      '6,7'
1695                                                                                                ),
1696                                'YIELDDISC'                             => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1697                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::YIELDDISC',
1698                                                                                                 'argumentCount'        =>      '4,5'
1699                                                                                                ),
1700                                'YIELDMAT'                              => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1701                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Financial::YIELDMAT',
1702                                                                                                 'argumentCount'        =>      '5,6'
1703                                                                                                ),
1704                                'ZTEST'                                 => array('category'                     =>      PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1705                                                                                                 'functionCall'         =>      'PHPExcel_Calculation_Statistical::ZTEST',
1706                                                                                                 'argumentCount'        =>      '2-3'
1707                                                                                                )
1708                        );
1709
1710
1711        //      Internal functions used for special control purposes
1712        private static $_controlFunctions = array(
1713                                'MKMATRIX'      => array('argumentCount'        =>      '*',
1714                                                                         'functionCall'         =>      'self::_mkMatrix'
1715                                                                        )
1716                        );
1717
1718
1719
1720
1721        private function __construct(PHPExcel $workbook = NULL) {
1722                $setPrecision = (PHP_INT_SIZE == 4) ? 14 : 16;
1723                $this->_savedPrecision = ini_get('precision');
1724                if ($this->_savedPrecision < $setPrecision) {
1725                        ini_set('precision',$setPrecision);
1726                }
1727
1728                if ($workbook !== NULL) {
1729                        self::$_workbookSets[$workbook->getID()] = $this;
1730                }
1731
1732                $this->_workbook = $workbook;
1733                $this->_cyclicReferenceStack = new PHPExcel_CalcEngine_CyclicReferenceStack();
1734            $this->_debugLog = new PHPExcel_CalcEngine_Logger($this->_cyclicReferenceStack);
1735        }       //      function __construct()
1736
1737
1738        public function __destruct() {
1739                if ($this->_savedPrecision != ini_get('precision')) {
1740                        ini_set('precision',$this->_savedPrecision);
1741                }
1742        }
1743
1744        private static function _loadLocales() {
1745                $localeFileDirectory = PHPEXCEL_ROOT.'PHPExcel/locale/';
1746                foreach (glob($localeFileDirectory.'/*',GLOB_ONLYDIR) as $filename) {
1747                        $filename = substr($filename,strlen($localeFileDirectory)+1);
1748                        if ($filename != 'en') {
1749                                self::$_validLocaleLanguages[] = $filename;
1750                        }
1751                }
1752        }
1753
1754        /**
1755         * Get an instance of this class
1756         *
1757         * @access      public
1758         * @param   PHPExcel $workbook  Injected workbook for working with a PHPExcel object,
1759         *                                                                      or NULL to create a standalone claculation engine
1760         * @return PHPExcel_Calculation
1761         */
1762        public static function getInstance(PHPExcel $workbook = NULL) {
1763                if ($workbook !== NULL) {
1764                if (isset(self::$_workbookSets[$workbook->getID()])) {
1765                        return self::$_workbookSets[$workbook->getID()];
1766                }
1767                        return new PHPExcel_Calculation($workbook);
1768                }
1769
1770                if (!isset(self::$_instance) || (self::$_instance === NULL)) {
1771                        self::$_instance = new PHPExcel_Calculation();
1772                }
1773
1774                return self::$_instance;
1775        }       //      function getInstance()
1776
1777        /**
1778         * Unset an instance of this class
1779         *
1780         * @access      public
1781         * @param   PHPExcel $workbook  Injected workbook identifying the instance to unset
1782         */
1783        public static function unsetInstance(PHPExcel $workbook = NULL) {
1784                if ($workbook !== NULL) {
1785                if (isset(self::$_workbookSets[$workbook->getID()])) {
1786                        unset(self::$_workbookSets[$workbook->getID()]);
1787                }
1788                }
1789    }
1790
1791        /**
1792         * Flush the calculation cache for any existing instance of this class
1793         *              but only if a PHPExcel_Calculation instance exists
1794         *
1795         * @access      public
1796         * @return null
1797         */
1798        public function flushInstance() {
1799                $this->clearCalculationCache();
1800        }       //      function flushInstance()
1801
1802
1803        /**
1804         * Get the debuglog for this claculation engine instance
1805         *
1806         * @access      public
1807         * @return PHPExcel_CalcEngine_Logger
1808         */
1809        public function getDebugLog() {
1810                return $this->_debugLog;
1811        }
1812
1813        /**
1814         * __clone implementation. Cloning should not be allowed in a Singleton!
1815         *
1816         * @access      public
1817         * @throws      PHPExcel_Calculation_Exception
1818         */
1819        public final function __clone() {
1820                throw new PHPExcel_Calculation_Exception ('Cloning the calculation engine is not allowed!');
1821        }       //      function __clone()
1822
1823
1824        /**
1825         * Return the locale-specific translation of TRUE
1826         *
1827         * @access      public
1828         * @return       string         locale-specific translation of TRUE
1829         */
1830        public static function getTRUE() {
1831                return self::$_localeBoolean['TRUE'];
1832        }
1833
1834        /**
1835         * Return the locale-specific translation of FALSE
1836         *
1837         * @access      public
1838         * @return       string         locale-specific translation of FALSE
1839         */
1840        public static function getFALSE() {
1841                return self::$_localeBoolean['FALSE'];
1842        }
1843
1844        /**
1845         * Set the Array Return Type (Array or Value of first element in the array)
1846         *
1847         * @access      public
1848         * @param        string $returnType                     Array return type
1849         * @return       boolean                                        Success or failure
1850         */
1851        public static function setArrayReturnType($returnType) {
1852                if (($returnType == self::RETURN_ARRAY_AS_VALUE) ||
1853                        ($returnType == self::RETURN_ARRAY_AS_ERROR) ||
1854                        ($returnType == self::RETURN_ARRAY_AS_ARRAY)) {
1855                        self::$returnArrayAsType = $returnType;
1856                        return TRUE;
1857                }
1858                return FALSE;
1859        }       //      function setArrayReturnType()
1860
1861
1862        /**
1863         * Return the Array Return Type (Array or Value of first element in the array)
1864         *
1865         * @access      public
1866         * @return       string         $returnType                     Array return type
1867         */
1868        public static function getArrayReturnType() {
1869                return self::$returnArrayAsType;
1870        }       //      function getArrayReturnType()
1871
1872
1873        /**
1874         * Is calculation caching enabled?
1875         *
1876         * @access      public
1877         * @return boolean
1878         */
1879        public function getCalculationCacheEnabled() {
1880                return $this->_calculationCacheEnabled;
1881        }       //      function getCalculationCacheEnabled()
1882
1883        /**
1884         * Enable/disable calculation cache
1885         *
1886         * @access      public
1887         * @param boolean $pValue
1888         */
1889        public function setCalculationCacheEnabled($pValue = TRUE) {
1890                $this->_calculationCacheEnabled = $pValue;
1891                $this->clearCalculationCache();
1892        }       //      function setCalculationCacheEnabled()
1893
1894
1895        /**
1896         * Enable calculation cache
1897         */
1898        public function enableCalculationCache() {
1899                $this->setCalculationCacheEnabled(TRUE);
1900        }       //      function enableCalculationCache()
1901
1902
1903        /**
1904         * Disable calculation cache
1905         */
1906        public function disableCalculationCache() {
1907                $this->setCalculationCacheEnabled(FALSE);
1908        }       //      function disableCalculationCache()
1909
1910
1911        /**
1912         * Clear calculation cache
1913         */
1914        public function clearCalculationCache() {
1915                $this->_calculationCache = array();
1916        }       //      function clearCalculationCache()
1917
1918        /**
1919         * Clear calculation cache for a specified worksheet
1920         *
1921         * @param string $worksheetName
1922         */
1923        public function clearCalculationCacheForWorksheet($worksheetName) {
1924                if (isset($this->_calculationCache[$worksheetName])) {
1925                        unset($this->_calculationCache[$worksheetName]);
1926                }
1927        }       //      function clearCalculationCacheForWorksheet()
1928
1929        /**
1930         * Rename calculation cache for a specified worksheet
1931         *
1932         * @param string $fromWorksheetName
1933         * @param string $toWorksheetName
1934         */
1935        public function renameCalculationCacheForWorksheet($fromWorksheetName, $toWorksheetName) {
1936                if (isset($this->_calculationCache[$fromWorksheetName])) {
1937                        $this->_calculationCache[$toWorksheetName] = &$this->_calculationCache[$fromWorksheetName];
1938                        unset($this->_calculationCache[$fromWorksheetName]);
1939                }
1940        }       //      function renameCalculationCacheForWorksheet()
1941
1942
1943        /**
1944         * Get the currently defined locale code
1945         *
1946         * @return string
1947         */
1948        public function getLocale() {
1949                return self::$_localeLanguage;
1950        }       //      function getLocale()
1951
1952
1953        /**
1954         * Set the locale code
1955         *
1956         * @param string $locale  The locale to use for formula translation
1957         * @return boolean
1958         */
1959        public function setLocale($locale = 'en_us') {
1960                //      Identify our locale and language
1961                $language = $locale = strtolower($locale);
1962                if (strpos($locale,'_') !== FALSE) {
1963                        list($language) = explode('_',$locale);
1964                }
1965
1966                if (count(self::$_validLocaleLanguages) == 1)
1967                        self::_loadLocales();
1968
1969                //      Test whether we have any language data for this language (any locale)
1970                if (in_array($language,self::$_validLocaleLanguages)) {
1971                        //      initialise language/locale settings
1972                        self::$_localeFunctions = array();
1973                        self::$_localeArgumentSeparator = ',';
1974                        self::$_localeBoolean = array('TRUE' => 'TRUE', 'FALSE' => 'FALSE', 'NULL' => 'NULL');
1975                        //      Default is English, if user isn't requesting english, then read the necessary data from the locale files
1976                        if ($locale != 'en_us') {
1977                                //      Search for a file with a list of function names for locale
1978                                $functionNamesFile = PHPEXCEL_ROOT . 'PHPExcel'.DIRECTORY_SEPARATOR.'locale'.DIRECTORY_SEPARATOR.str_replace('_',DIRECTORY_SEPARATOR,$locale).DIRECTORY_SEPARATOR.'functions';
1979                                if (!file_exists($functionNamesFile)) {
1980                                        //      If there isn't a locale specific function file, look for a language specific function file
1981                                        $functionNamesFile = PHPEXCEL_ROOT . 'PHPExcel'.DIRECTORY_SEPARATOR.'locale'.DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.'functions';
1982                                        if (!file_exists($functionNamesFile)) {
1983                                                return FALSE;
1984                                        }
1985                                }
1986                                //      Retrieve the list of locale or language specific function names
1987                                $localeFunctions = file($functionNamesFile,FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
1988                                foreach ($localeFunctions as $localeFunction) {
1989                                        list($localeFunction) = explode('##',$localeFunction);  //      Strip out comments
1990                                        if (strpos($localeFunction,'=') !== FALSE) {
1991                                                list($fName,$lfName) = explode('=',$localeFunction);
1992                                                $fName = trim($fName);
1993                                                $lfName = trim($lfName);
1994                                                if ((isset(self::$_PHPExcelFunctions[$fName])) && ($lfName != '') && ($fName != $lfName)) {
1995                                                        self::$_localeFunctions[$fName] = $lfName;
1996                                                }
1997                                        }
1998                                }
1999                                //      Default the TRUE and FALSE constants to the locale names of the TRUE() and FALSE() functions
2000                                if (isset(self::$_localeFunctions['TRUE'])) { self::$_localeBoolean['TRUE'] = self::$_localeFunctions['TRUE']; }
2001                                if (isset(self::$_localeFunctions['FALSE'])) { self::$_localeBoolean['FALSE'] = self::$_localeFunctions['FALSE']; }
2002
2003                                $configFile = PHPEXCEL_ROOT . 'PHPExcel'.DIRECTORY_SEPARATOR.'locale'.DIRECTORY_SEPARATOR.str_replace('_',DIRECTORY_SEPARATOR,$locale).DIRECTORY_SEPARATOR.'config';
2004                                if (!file_exists($configFile)) {
2005                                        $configFile = PHPEXCEL_ROOT . 'PHPExcel'.DIRECTORY_SEPARATOR.'locale'.DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.'config';
2006                                }
2007                                if (file_exists($configFile)) {
2008                                        $localeSettings = file($configFile,FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
2009                                        foreach ($localeSettings as $localeSetting) {
2010                                                list($localeSetting) = explode('##',$localeSetting);    //      Strip out comments
2011                                                if (strpos($localeSetting,'=') !== FALSE) {
2012                                                        list($settingName,$settingValue) = explode('=',$localeSetting);
2013                                                        $settingName = strtoupper(trim($settingName));
2014                                                        switch ($settingName) {
2015                                                                case 'ARGUMENTSEPARATOR' :
2016                                                                        self::$_localeArgumentSeparator = trim($settingValue);
2017                                                                        break;
2018                                                        }
2019                                                }
2020                                        }
2021                                }
2022                        }
2023
2024                        self::$functionReplaceFromExcel = self::$functionReplaceToExcel =
2025                        self::$functionReplaceFromLocale = self::$functionReplaceToLocale = NULL;
2026                        self::$_localeLanguage = $locale;
2027                        return TRUE;
2028                }
2029                return FALSE;
2030        }       //      function setLocale()
2031
2032
2033
2034        public static function _translateSeparator($fromSeparator,$toSeparator,$formula,&$inBraces) {
2035                $strlen = mb_strlen($formula);
2036                for ($i = 0; $i < $strlen; ++$i) {
2037                        $chr = mb_substr($formula,$i,1);
2038                        switch ($chr) {
2039                                case '{' :      $inBraces = TRUE;
2040                                                        break;
2041                                case '}' :      $inBraces = FALSE;
2042                                                        break;
2043                                case $fromSeparator :
2044                                                        if (!$inBraces) {
2045                                                                $formula = mb_substr($formula,0,$i).$toSeparator.mb_substr($formula,$i+1);
2046                                                        }
2047                        }
2048                }
2049                return $formula;
2050        }
2051
2052        private static function _translateFormula($from,$to,$formula,$fromSeparator,$toSeparator) {
2053                //      Convert any Excel function names to the required language
2054                if (self::$_localeLanguage !== 'en_us') {
2055                        $inBraces = FALSE;
2056                        //      If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators
2057                        if (strpos($formula,'"') !== FALSE) {
2058                                //      So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded
2059                                //              the formula
2060                                $temp = explode('"',$formula);
2061                                $i = FALSE;
2062                                foreach($temp as &$value) {
2063                                        //      Only count/replace in alternating array entries
2064                                        if ($i = !$i) {
2065                                                $value = preg_replace($from,$to,$value);
2066                                                $value = self::_translateSeparator($fromSeparator,$toSeparator,$value,$inBraces);
2067                                        }
2068                                }
2069                                unset($value);
2070                                //      Then rebuild the formula string
2071                                $formula = implode('"',$temp);
2072                        } else {
2073                                //      If there's no quoted strings, then we do a simple count/replace
2074                                $formula = preg_replace($from,$to,$formula);
2075                                $formula = self::_translateSeparator($fromSeparator,$toSeparator,$formula,$inBraces);
2076                        }
2077                }
2078
2079                return $formula;
2080        }
2081
2082        private static $functionReplaceFromExcel        = NULL;
2083        private static $functionReplaceToLocale         = NULL;
2084
2085        public function _translateFormulaToLocale($formula) {
2086                if (self::$functionReplaceFromExcel === NULL) {
2087                        self::$functionReplaceFromExcel = array();
2088                        foreach(array_keys(self::$_localeFunctions) as $excelFunctionName) {
2089                                self::$functionReplaceFromExcel[] = '/(@?[^\w\.])'.preg_quote($excelFunctionName).'([\s]*\()/Ui';
2090                        }
2091                        foreach(array_keys(self::$_localeBoolean) as $excelBoolean) {
2092                                self::$functionReplaceFromExcel[] = '/(@?[^\w\.])'.preg_quote($excelBoolean).'([^\w\.])/Ui';
2093                        }
2094
2095                }
2096
2097                if (self::$functionReplaceToLocale === NULL) {
2098                        self::$functionReplaceToLocale = array();
2099                        foreach(array_values(self::$_localeFunctions) as $localeFunctionName) {
2100                                self::$functionReplaceToLocale[] = '$1'.trim($localeFunctionName).'$2';
2101                        }
2102                        foreach(array_values(self::$_localeBoolean) as $localeBoolean) {
2103                                self::$functionReplaceToLocale[] = '$1'.trim($localeBoolean).'$2';
2104                        }
2105                }
2106
2107                return self::_translateFormula(self::$functionReplaceFromExcel,self::$functionReplaceToLocale,$formula,',',self::$_localeArgumentSeparator);
2108        }       //      function _translateFormulaToLocale()
2109
2110
2111        private static $functionReplaceFromLocale       = NULL;
2112        private static $functionReplaceToExcel          = NULL;
2113
2114        public function _translateFormulaToEnglish($formula) {
2115                if (self::$functionReplaceFromLocale === NULL) {
2116                        self::$functionReplaceFromLocale = array();
2117                        foreach(array_values(self::$_localeFunctions) as $localeFunctionName) {
2118                                self::$functionReplaceFromLocale[] = '/(@?[^\w\.])'.preg_quote($localeFunctionName).'([\s]*\()/Ui';
2119                        }
2120                        foreach(array_values(self::$_localeBoolean) as $excelBoolean) {
2121                                self::$functionReplaceFromLocale[] = '/(@?[^\w\.])'.preg_quote($excelBoolean).'([^\w\.])/Ui';
2122                        }
2123                }
2124
2125                if (self::$functionReplaceToExcel === NULL) {
2126                        self::$functionReplaceToExcel = array();
2127                        foreach(array_keys(self::$_localeFunctions) as $excelFunctionName) {
2128                                self::$functionReplaceToExcel[] = '$1'.trim($excelFunctionName).'$2';
2129                        }
2130                        foreach(array_keys(self::$_localeBoolean) as $excelBoolean) {
2131                                self::$functionReplaceToExcel[] = '$1'.trim($excelBoolean).'$2';
2132                        }
2133                }
2134
2135                return self::_translateFormula(self::$functionReplaceFromLocale,self::$functionReplaceToExcel,$formula,self::$_localeArgumentSeparator,',');
2136        }       //      function _translateFormulaToEnglish()
2137
2138
2139        public static function _localeFunc($function) {
2140                if (self::$_localeLanguage !== 'en_us') {
2141                        $functionName = trim($function,'(');
2142                        if (isset(self::$_localeFunctions[$functionName])) {
2143                                $brace = ($functionName != $function);
2144                                $function = self::$_localeFunctions[$functionName];
2145                                if ($brace) { $function .= '('; }
2146                        }
2147                }
2148                return $function;
2149        }
2150
2151
2152
2153
2154        /**
2155         * Wrap string values in quotes
2156         *
2157         * @param mixed $value
2158         * @return mixed
2159         */
2160        public static function _wrapResult($value) {
2161                if (is_string($value)) {
2162                        //      Error values cannot be "wrapped"
2163                        if (preg_match('/^'.self::CALCULATION_REGEXP_ERROR.'$/i', $value, $match)) {
2164                                //      Return Excel errors "as is"
2165                                return $value;
2166                        }
2167                        //      Return strings wrapped in quotes
2168                        return '"'.$value.'"';
2169                //      Convert numeric errors to NaN error
2170                } else if((is_float($value)) && ((is_nan($value)) || (is_infinite($value)))) {
2171                        return PHPExcel_Calculation_Functions::NaN();
2172                }
2173
2174                return $value;
2175        }       //      function _wrapResult()
2176
2177
2178        /**
2179         * Remove quotes used as a wrapper to identify string values
2180         *
2181         * @param mixed $value
2182         * @return mixed
2183         */
2184        public static function _unwrapResult($value) {
2185                if (is_string($value)) {
2186                        if ((isset($value{0})) && ($value{0} == '"') && (substr($value,-1) == '"')) {
2187                                return substr($value,1,-1);
2188                        }
2189                //      Convert numeric errors to NaN error
2190                } else if((is_float($value)) && ((is_nan($value)) || (is_infinite($value)))) {
2191                        return PHPExcel_Calculation_Functions::NaN();
2192                }
2193                return $value;
2194        }       //      function _unwrapResult()
2195
2196
2197
2198
2199        /**
2200         * Calculate cell value (using formula from a cell ID)
2201         * Retained for backward compatibility
2202         *
2203         * @access      public
2204         * @param       PHPExcel_Cell   $pCell  Cell to calculate
2205         * @return      mixed
2206         * @throws      PHPExcel_Calculation_Exception
2207         */
2208        public function calculate(PHPExcel_Cell $pCell = NULL) {
2209                try {
2210                        return $this->calculateCellValue($pCell);
2211                } catch (PHPExcel_Exception $e) {
2212                        throw new PHPExcel_Calculation_Exception($e->getMessage());
2213                }
2214        }       //      function calculate()
2215
2216
2217        /**
2218         * Calculate the value of a cell formula
2219         *
2220         * @access      public
2221         * @param       PHPExcel_Cell   $pCell          Cell to calculate
2222         * @param       Boolean                 $resetLog       Flag indicating whether the debug log should be reset or not
2223         * @return      mixed
2224         * @throws      PHPExcel_Calculation_Exception
2225         */
2226        public function calculateCellValue(PHPExcel_Cell $pCell = NULL, $resetLog = TRUE) {
2227                if ($pCell === NULL) {
2228                        return NULL;
2229                }
2230
2231                $returnArrayAsType = self::$returnArrayAsType;
2232                if ($resetLog) {
2233                        //      Initialise the logging settings if requested
2234                        $this->formulaError = null;
2235                        $this->_debugLog->clearLog();
2236                        $this->_cyclicReferenceStack->clear();
2237                        $this->_cyclicFormulaCount = 1;
2238
2239                        self::$returnArrayAsType = self::RETURN_ARRAY_AS_ARRAY;
2240                }
2241
2242                //      Execute the calculation for the cell formula
2243                try {
2244                        $result = self::_unwrapResult($this->_calculateFormulaValue($pCell->getValue(), $pCell->getCoordinate(), $pCell));
2245                } catch (PHPExcel_Exception $e) {
2246                        throw new PHPExcel_Calculation_Exception($e->getMessage());
2247                }
2248
2249                if ((is_array($result)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) {
2250                        self::$returnArrayAsType = $returnArrayAsType;
2251                        $testResult = PHPExcel_Calculation_Functions::flattenArray($result);
2252                        if (self::$returnArrayAsType == self::RETURN_ARRAY_AS_ERROR) {
2253                                return PHPExcel_Calculation_Functions::VALUE();
2254                        }
2255                        //      If there's only a single cell in the array, then we allow it
2256                        if (count($testResult) != 1) {
2257                                //      If keys are numeric, then it's a matrix result rather than a cell range result, so we permit it
2258                                $r = array_keys($result);
2259                                $r = array_shift($r);
2260                                if (!is_numeric($r)) { return PHPExcel_Calculation_Functions::VALUE(); }
2261                                if (is_array($result[$r])) {
2262                                        $c = array_keys($result[$r]);
2263                                        $c = array_shift($c);
2264                                        if (!is_numeric($c)) {
2265                                                return PHPExcel_Calculation_Functions::VALUE();
2266                                        }
2267                                }
2268                        }
2269                        $result = array_shift($testResult);
2270                }
2271                self::$returnArrayAsType = $returnArrayAsType;
2272
2273
2274                if ($result === NULL) {
2275                        return 0;
2276                } elseif((is_float($result)) && ((is_nan($result)) || (is_infinite($result)))) {
2277                        return PHPExcel_Calculation_Functions::NaN();
2278                }
2279                return $result;
2280        }       //      function calculateCellValue(
2281
2282
2283        /**
2284         * Validate and parse a formula string
2285         *
2286         * @param       string          $formula                Formula to parse
2287         * @return      array
2288         * @throws      PHPExcel_Calculation_Exception
2289         */
2290        public function parseFormula($formula) {
2291                //      Basic validation that this is indeed a formula
2292                //      We return an empty array if not
2293                $formula = trim($formula);
2294                if ((!isset($formula{0})) || ($formula{0} != '=')) return array();
2295                $formula = ltrim(substr($formula,1));
2296                if (!isset($formula{0})) return array();
2297
2298                //      Parse the formula and return the token stack
2299                return $this->_parseFormula($formula);
2300        }       //      function parseFormula()
2301
2302
2303        /**
2304         * Calculate the value of a formula
2305         *
2306         * @param       string                  $formula        Formula to parse
2307         * @param       string                  $cellID         Address of the cell to calculate
2308         * @param       PHPExcel_Cell   $pCell          Cell to calculate
2309         * @return      mixed
2310         * @throws      PHPExcel_Calculation_Exception
2311         */
2312        public function calculateFormula($formula, $cellID=NULL, PHPExcel_Cell $pCell = NULL) {
2313                //      Initialise the logging settings
2314                $this->formulaError = null;
2315                $this->_debugLog->clearLog();
2316                $this->_cyclicReferenceStack->clear();
2317
2318                //      Disable calculation cacheing because it only applies to cell calculations, not straight formulae
2319                //      But don't actually flush any cache
2320                $resetCache = $this->getCalculationCacheEnabled();
2321                $this->_calculationCacheEnabled = FALSE;
2322                //      Execute the calculation
2323                try {
2324                        $result = self::_unwrapResult($this->_calculateFormulaValue($formula, $cellID, $pCell));
2325                } catch (PHPExcel_Exception $e) {
2326                        throw new PHPExcel_Calculation_Exception($e->getMessage());
2327                }
2328
2329                //      Reset calculation cacheing to its previous state
2330                $this->_calculationCacheEnabled = $resetCache;
2331
2332                return $result;
2333        }       //      function calculateFormula()
2334
2335
2336    public function getValueFromCache($worksheetName, $cellID, &$cellValue) {
2337                // Is calculation cacheing enabled?
2338                // Is the value present in calculation cache?
2339//echo 'Test cache for ',$worksheetName,'!',$cellID,PHP_EOL;
2340                $this->_debugLog->writeDebugLog('Testing cache value for cell ', $worksheetName, '!', $cellID);
2341                if (($this->_calculationCacheEnabled) && (isset($this->_calculationCache[$worksheetName][$cellID]))) {
2342//echo 'Retrieve from cache',PHP_EOL;
2343                        $this->_debugLog->writeDebugLog('Retrieving value for cell ', $worksheetName, '!', $cellID, ' from cache');
2344                        // Return the cached result
2345                        $cellValue = $this->_calculationCache[$worksheetName][$cellID];
2346                        return TRUE;
2347                }
2348                return FALSE;
2349    }
2350
2351    public function saveValueToCache($worksheetName, $cellID, $cellValue) {
2352                if ($this->_calculationCacheEnabled) {
2353                        $this->_calculationCache[$worksheetName][$cellID] = $cellValue;
2354                }
2355        }
2356
2357        /**
2358         * Parse a cell formula and calculate its value
2359         *
2360         * @param       string                  $formula        The formula to parse and calculate
2361         * @param       string                  $cellID         The ID (e.g. A3) of the cell that we are calculating
2362         * @param       PHPExcel_Cell   $pCell          Cell to calculate
2363         * @return      mixed
2364         * @throws      PHPExcel_Calculation_Exception
2365         */
2366        public function _calculateFormulaValue($formula, $cellID=null, PHPExcel_Cell $pCell = null) {
2367                $cellValue = '';
2368
2369                //      Basic validation that this is indeed a formula
2370                //      We simply return the cell value if not
2371                $formula = trim($formula);
2372                if ($formula{0} != '=') return self::_wrapResult($formula);
2373                $formula = ltrim(substr($formula,1));
2374                if (!isset($formula{0})) return self::_wrapResult($formula);
2375
2376                $pCellParent = ($pCell !== NULL) ? $pCell->getWorksheet() : NULL;
2377                $wsTitle = ($pCellParent !== NULL) ? $pCellParent->getTitle() : "\x00Wrk";
2378
2379                if (($cellID !== NULL) && ($this->getValueFromCache($wsTitle, $cellID, $cellValue))) {
2380                        return $cellValue;
2381                }
2382
2383                if (($wsTitle{0} !== "\x00") && ($this->_cyclicReferenceStack->onStack($wsTitle.'!'.$cellID))) {
2384                        if ($this->cyclicFormulaCount <= 0) {
2385                                return $this->_raiseFormulaError('Cyclic Reference in Formula');
2386                        } elseif (($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) &&
2387                                          ($this->_cyclicFormulaCell == $wsTitle.'!'.$cellID)) {
2388                                return $cellValue;
2389                        } elseif ($this->_cyclicFormulaCell == $wsTitle.'!'.$cellID) {
2390                                ++$this->_cyclicFormulaCount;
2391                                if ($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) {
2392                                        return $cellValue;
2393                                }
2394                        } elseif ($this->_cyclicFormulaCell == '') {
2395                                $this->_cyclicFormulaCell = $wsTitle.'!'.$cellID;
2396                                if ($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) {
2397                                        return $cellValue;
2398                                }
2399                        }
2400                }
2401
2402                //      Parse the formula onto the token stack and calculate the value
2403                $this->_cyclicReferenceStack->push($wsTitle.'!'.$cellID);
2404                $cellValue = $this->_processTokenStack($this->_parseFormula($formula, $pCell), $cellID, $pCell);
2405                $this->_cyclicReferenceStack->pop();
2406
2407                // Save to calculation cache
2408                if ($cellID !== NULL) {
2409                        $this->saveValueToCache($wsTitle, $cellID, $cellValue);
2410                }
2411
2412                //      Return the calculated value
2413                return $cellValue;
2414        }       //      function _calculateFormulaValue()
2415
2416
2417        /**
2418         * Ensure that paired matrix operands are both matrices and of the same size
2419         *
2420         * @param       mixed           &$operand1      First matrix operand
2421         * @param       mixed           &$operand2      Second matrix operand
2422         * @param       integer         $resize         Flag indicating whether the matrices should be resized to match
2423         *                                                                              and (if so), whether the smaller dimension should grow or the
2424         *                                                                              larger should shrink.
2425         *                                                                                      0 = no resize
2426         *                                                                                      1 = shrink to fit
2427         *                                                                                      2 = extend to fit
2428         */
2429        private static function _checkMatrixOperands(&$operand1,&$operand2,$resize = 1) {
2430                //      Examine each of the two operands, and turn them into an array if they aren't one already
2431                //      Note that this function should only be called if one or both of the operand is already an array
2432                if (!is_array($operand1)) {
2433                        list($matrixRows,$matrixColumns) = self::_getMatrixDimensions($operand2);
2434                        $operand1 = array_fill(0,$matrixRows,array_fill(0,$matrixColumns,$operand1));
2435                        $resize = 0;
2436                } elseif (!is_array($operand2)) {
2437                        list($matrixRows,$matrixColumns) = self::_getMatrixDimensions($operand1);
2438                        $operand2 = array_fill(0,$matrixRows,array_fill(0,$matrixColumns,$operand2));
2439                        $resize = 0;
2440                }
2441
2442                list($matrix1Rows,$matrix1Columns) = self::_getMatrixDimensions($operand1);
2443                list($matrix2Rows,$matrix2Columns) = self::_getMatrixDimensions($operand2);
2444                if (($matrix1Rows == $matrix2Columns) && ($matrix2Rows == $matrix1Columns)) {
2445                        $resize = 1;
2446                }
2447
2448                if ($resize == 2) {
2449                        //      Given two matrices of (potentially) unequal size, convert the smaller in each dimension to match the larger
2450                        self::_resizeMatricesExtend($operand1,$operand2,$matrix1Rows,$matrix1Columns,$matrix2Rows,$matrix2Columns);
2451                } elseif ($resize == 1) {
2452                        //      Given two matrices of (potentially) unequal size, convert the larger in each dimension to match the smaller
2453                        self::_resizeMatricesShrink($operand1,$operand2,$matrix1Rows,$matrix1Columns,$matrix2Rows,$matrix2Columns);
2454                }
2455                return array( $matrix1Rows,$matrix1Columns,$matrix2Rows,$matrix2Columns);
2456        }       //      function _checkMatrixOperands()
2457
2458
2459        /**
2460         * Read the dimensions of a matrix, and re-index it with straight numeric keys starting from row 0, column 0
2461         *
2462         * @param       mixed           &$matrix                matrix operand
2463         * @return      array           An array comprising the number of rows, and number of columns
2464         */
2465        public static function _getMatrixDimensions(&$matrix) {
2466                $matrixRows = count($matrix);
2467                $matrixColumns = 0;
2468                foreach($matrix as $rowKey => $rowValue) {
2469                        $matrixColumns = max(count($rowValue),$matrixColumns);
2470                        if (!is_array($rowValue)) {
2471                                $matrix[$rowKey] = array($rowValue);
2472                        } else {
2473                                $matrix[$rowKey] = array_values($rowValue);
2474                        }
2475                }
2476                $matrix = array_values($matrix);
2477                return array($matrixRows,$matrixColumns);
2478        }       //      function _getMatrixDimensions()
2479
2480
2481        /**
2482         * Ensure that paired matrix operands are both matrices of the same size
2483         *
2484         * @param       mixed           &$matrix1               First matrix operand
2485         * @param       mixed           &$matrix2               Second matrix operand
2486         * @param       integer         $matrix1Rows    Row size of first matrix operand
2487         * @param       integer         $matrix1Columns Column size of first matrix operand
2488         * @param       integer         $matrix2Rows    Row size of second matrix operand
2489         * @param       integer         $matrix2Columns Column size of second matrix operand
2490         */
2491        private static function _resizeMatricesShrink(&$matrix1,&$matrix2,$matrix1Rows,$matrix1Columns,$matrix2Rows,$matrix2Columns) {
2492                if (($matrix2Columns < $matrix1Columns) || ($matrix2Rows < $matrix1Rows)) {
2493                        if ($matrix2Rows < $matrix1Rows) {
2494                                for ($i = $matrix2Rows; $i < $matrix1Rows; ++$i) {
2495                                        unset($matrix1[$i]);
2496                                }
2497                        }
2498                        if ($matrix2Columns < $matrix1Columns) {
2499                                for ($i = 0; $i < $matrix1Rows; ++$i) {
2500                                        for ($j = $matrix2Columns; $j < $matrix1Columns; ++$j) {
2501                                                unset($matrix1[$i][$j]);
2502                                        }
2503                                }
2504                        }
2505                }
2506
2507                if (($matrix1Columns < $matrix2Columns) || ($matrix1Rows < $matrix2Rows)) {
2508                        if ($matrix1Rows < $matrix2Rows) {
2509                                for ($i = $matrix1Rows; $i < $matrix2Rows; ++$i) {
2510                                        unset($matrix2[$i]);
2511                                }
2512                        }
2513                        if ($matrix1Columns < $matrix2Columns) {
2514                                for ($i = 0; $i < $matrix2Rows; ++$i) {
2515                                        for ($j = $matrix1Columns; $j < $matrix2Columns; ++$j) {
2516                                                unset($matrix2[$i][$j]);
2517                                        }
2518                                }
2519                        }
2520                }
2521        }       //      function _resizeMatricesShrink()
2522
2523
2524        /**
2525         * Ensure that paired matrix operands are both matrices of the same size
2526         *
2527         * @param       mixed           &$matrix1       First matrix operand
2528         * @param       mixed           &$matrix2       Second matrix operand
2529         * @param       integer         $matrix1Rows    Row size of first matrix operand
2530         * @param       integer         $matrix1Columns Column size of first matrix operand
2531         * @param       integer         $matrix2Rows    Row size of second matrix operand
2532         * @param       integer         $matrix2Columns Column size of second matrix operand
2533         */
2534        private static function _resizeMatricesExtend(&$matrix1,&$matrix2,$matrix1Rows,$matrix1Columns,$matrix2Rows,$matrix2Columns) {
2535                if (($matrix2Columns < $matrix1Columns) || ($matrix2Rows < $matrix1Rows)) {
2536                        if ($matrix2Columns < $matrix1Columns) {
2537                                for ($i = 0; $i < $matrix2Rows; ++$i) {
2538                                        $x = $matrix2[$i][$matrix2Columns-1];
2539                                        for ($j = $matrix2Columns; $j < $matrix1Columns; ++$j) {
2540                                                $matrix2[$i][$j] = $x;
2541                                        }
2542                                }
2543                        }
2544                        if ($matrix2Rows < $matrix1Rows) {
2545                                $x = $matrix2[$matrix2Rows-1];
2546                                for ($i = 0; $i < $matrix1Rows; ++$i) {
2547                                        $matrix2[$i] = $x;
2548                                }
2549                        }
2550                }
2551
2552                if (($matrix1Columns < $matrix2Columns) || ($matrix1Rows < $matrix2Rows)) {
2553                        if ($matrix1Columns < $matrix2Columns) {
2554                                for ($i = 0; $i < $matrix1Rows; ++$i) {
2555                                        $x = $matrix1[$i][$matrix1Columns-1];
2556                                        for ($j = $matrix1Columns; $j < $matrix2Columns; ++$j) {
2557                                                $matrix1[$i][$j] = $x;
2558                                        }
2559                                }
2560                        }
2561                        if ($matrix1Rows < $matrix2Rows) {
2562                                $x = $matrix1[$matrix1Rows-1];
2563                                for ($i = 0; $i < $matrix2Rows; ++$i) {
2564                                        $matrix1[$i] = $x;
2565                                }
2566                        }
2567                }
2568        }       //      function _resizeMatricesExtend()
2569
2570
2571        /**
2572         * Format details of an operand for display in the log (based on operand type)
2573         *
2574         * @param       mixed           $value  First matrix operand
2575         * @return      mixed
2576         */
2577        private function _showValue($value) {
2578                if ($this->_debugLog->getWriteDebugLog()) {
2579                        $testArray = PHPExcel_Calculation_Functions::flattenArray($value);
2580                        if (count($testArray) == 1) {
2581                                $value = array_pop($testArray);
2582                        }
2583
2584                        if (is_array($value)) {
2585                                $returnMatrix = array();
2586                                $pad = $rpad = ', ';
2587                                foreach($value as $row) {
2588                                        if (is_array($row)) {
2589                                                $returnMatrix[] = implode($pad,array_map(array($this,'_showValue'),$row));
2590                                                $rpad = '; ';
2591                                        } else {
2592                                                $returnMatrix[] = $this->_showValue($row);
2593                                        }
2594                                }
2595                                return '{ '.implode($rpad,$returnMatrix).' }';
2596                        } elseif(is_string($value) && (trim($value,'"') == $value)) {
2597                                return '"'.$value.'"';
2598                        } elseif(is_bool($value)) {
2599                                return ($value) ? self::$_localeBoolean['TRUE'] : self::$_localeBoolean['FALSE'];
2600                        }
2601                }
2602                return PHPExcel_Calculation_Functions::flattenSingleValue($value);
2603        }       //      function _showValue()
2604
2605
2606        /**
2607         * Format type and details of an operand for display in the log (based on operand type)
2608         *
2609         * @param       mixed           $value  First matrix operand
2610         * @return      mixed
2611         */
2612        private function _showTypeDetails($value) {
2613                if ($this->_debugLog->getWriteDebugLog()) {
2614                        $testArray = PHPExcel_Calculation_Functions::flattenArray($value);
2615                        if (count($testArray) == 1) {
2616                                $value = array_pop($testArray);
2617                        }
2618
2619                        if ($value === NULL) {
2620                                return 'a NULL value';
2621                        } elseif (is_float($value)) {
2622                                $typeString = 'a floating point number';
2623                        } elseif(is_int($value)) {
2624                                $typeString = 'an integer number';
2625                        } elseif(is_bool($value)) {
2626                                $typeString = 'a boolean';
2627                        } elseif(is_array($value)) {
2628                                $typeString = 'a matrix';
2629                        } else {
2630                                if ($value == '') {
2631                                        return 'an empty string';
2632                                } elseif ($value{0} == '#') {
2633                                        return 'a '.$value.' error';
2634                                } else {
2635                                        $typeString = 'a string';
2636                                }
2637                        }
2638                        return $typeString.' with a value of '.$this->_showValue($value);
2639                }
2640        }       //      function _showTypeDetails()
2641
2642
2643        private static function _convertMatrixReferences($formula) {
2644                static $matrixReplaceFrom = array('{',';','}');
2645                static $matrixReplaceTo = array('MKMATRIX(MKMATRIX(','),MKMATRIX(','))');
2646
2647                //      Convert any Excel matrix references to the MKMATRIX() function
2648                if (strpos($formula,'{') !== FALSE) {
2649                        //      If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators
2650                        if (strpos($formula,'"') !== FALSE) {
2651                                //      So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded
2652                                //              the formula
2653                                $temp = explode('"',$formula);
2654                                //      Open and Closed counts used for trapping mismatched braces in the formula
2655                                $openCount = $closeCount = 0;
2656                                $i = FALSE;
2657                                foreach($temp as &$value) {
2658                                        //      Only count/replace in alternating array entries
2659                                        if ($i = !$i) {
2660                                                $openCount += substr_count($value,'{');
2661                                                $closeCount += substr_count($value,'}');
2662                                                $value = str_replace($matrixReplaceFrom,$matrixReplaceTo,$value);
2663                                        }
2664                                }
2665                                unset($value);
2666                                //      Then rebuild the formula string
2667                                $formula = implode('"',$temp);
2668                        } else {
2669                                //      If there's no quoted strings, then we do a simple count/replace
2670                                $openCount = substr_count($formula,'{');
2671                                $closeCount = substr_count($formula,'}');
2672                                $formula = str_replace($matrixReplaceFrom,$matrixReplaceTo,$formula);
2673                        }
2674                        //      Trap for mismatched braces and trigger an appropriate error
2675                        if ($openCount < $closeCount) {
2676                                if ($openCount > 0) {
2677                                        return $this->_raiseFormulaError("Formula Error: Mismatched matrix braces '}'");
2678                                } else {
2679                                        return $this->_raiseFormulaError("Formula Error: Unexpected '}' encountered");
2680                                }
2681                        } elseif ($openCount > $closeCount) {
2682                                if ($closeCount > 0) {
2683                                        return $this->_raiseFormulaError("Formula Error: Mismatched matrix braces '{'");
2684                                } else {
2685                                        return $this->_raiseFormulaError("Formula Error: Unexpected '{' encountered");
2686                                }
2687                        }
2688                }
2689
2690                return $formula;
2691        }       //      function _convertMatrixReferences()
2692
2693
2694        private static function _mkMatrix() {
2695                return func_get_args();
2696        }       //      function _mkMatrix()
2697
2698
2699        //      Binary Operators
2700        //      These operators always work on two values
2701        //      Array key is the operator, the value indicates whether this is a left or right associative operator
2702        private static $_operatorAssociativity  = array(
2703                '^' => 0,                                                                                                                       //      Exponentiation
2704                '*' => 0, '/' => 0,                                                                                             //      Multiplication and Division
2705                '+' => 0, '-' => 0,                                                                                                     //      Addition and Subtraction
2706                '&' => 0,                                                                                                                       //      Concatenation
2707                '|' => 0, ':' => 0,                                                                                                     //      Intersect and Range
2708                '>' => 0, '<' => 0, '=' => 0, '>=' => 0, '<=' => 0, '<>' => 0           //      Comparison
2709        );
2710
2711        //      Comparison (Boolean) Operators
2712        //      These operators work on two values, but always return a boolean result
2713        private static $_comparisonOperators    = array('>' => TRUE, '<' => TRUE, '=' => TRUE, '>=' => TRUE, '<=' => TRUE, '<>' => TRUE);
2714
2715        //      Operator Precedence
2716        //      This list includes all valid operators, whether binary (including boolean) or unary (such as %)
2717        //      Array key is the operator, the value is its precedence
2718        private static $_operatorPrecedence     = array(
2719                ':' => 8,                                                                                                                               //      Range
2720                '|' => 7,                                                                                                                               //      Intersect
2721                '~' => 6,                                                                                                                               //      Negation
2722                '%' => 5,                                                                                                                               //      Percentage
2723                '^' => 4,                                                                                                                               //      Exponentiation
2724                '*' => 3, '/' => 3,                                                                                                     //      Multiplication and Division
2725                '+' => 2, '-' => 2,                                                                                                             //      Addition and Subtraction
2726                '&' => 1,                                                                                                                               //      Concatenation
2727                '>' => 0, '<' => 0, '=' => 0, '>=' => 0, '<=' => 0, '<>' => 0                   //      Comparison
2728        );
2729
2730        // Convert infix to postfix notation
2731        private function _parseFormula($formula, PHPExcel_Cell $pCell = NULL) {
2732                if (($formula = self::_convertMatrixReferences(trim($formula))) === FALSE) {
2733                        return FALSE;
2734                }
2735
2736                //      If we're using cell caching, then $pCell may well be flushed back to the cache (which detaches the parent worksheet),
2737                //              so we store the parent worksheet so that we can re-attach it when necessary
2738                $pCellParent = ($pCell !== NULL) ? $pCell->getWorksheet() : NULL;
2739
2740                $regexpMatchString = '/^('.self::CALCULATION_REGEXP_FUNCTION.
2741                                                           '|'.self::CALCULATION_REGEXP_CELLREF.
2742                                                           '|'.self::CALCULATION_REGEXP_NUMBER.
2743                                                           '|'.self::CALCULATION_REGEXP_STRING.
2744                                                           '|'.self::CALCULATION_REGEXP_OPENBRACE.
2745                                                           '|'.self::CALCULATION_REGEXP_NAMEDRANGE.
2746                                                           '|'.self::CALCULATION_REGEXP_ERROR.
2747                                                         ')/si';
2748
2749                //      Start with initialisation
2750                $index = 0;
2751                $stack = new PHPExcel_Calculation_Token_Stack;
2752                $output = array();
2753                $expectingOperator = FALSE;                                     //      We use this test in syntax-checking the expression to determine when a
2754                                                                                                        //              - is a negation or + is a positive operator rather than an operation
2755                $expectingOperand = FALSE;                                      //      We use this test in syntax-checking the expression to determine whether an operand
2756                                                                                                        //              should be null in a function call
2757                //      The guts of the lexical parser
2758                //      Loop through the formula extracting each operator and operand in turn
2759                while(TRUE) {
2760//echo 'Assessing Expression '.substr($formula, $index),PHP_EOL;
2761                        $opCharacter = $formula{$index};        //      Get the first character of the value at the current index position
2762//echo 'Initial character of expression block is '.$opCharacter,PHP_EOL;
2763                        if ((isset(self::$_comparisonOperators[$opCharacter])) && (strlen($formula) > $index) && (isset(self::$_comparisonOperators[$formula{$index+1}]))) {
2764                                $opCharacter .= $formula{++$index};
2765//echo 'Initial character of expression block is comparison operator '.$opCharacter.PHP_EOL;
2766                        }
2767
2768                        //      Find out if we're currently at the beginning of a number, variable, cell reference, function, parenthesis or operand
2769                        $isOperandOrFunction = preg_match($regexpMatchString, substr($formula, $index), $match);
2770//echo '$isOperandOrFunction is '.(($isOperandOrFunction) ? 'True' : 'False').PHP_EOL;
2771//var_dump($match);
2772
2773                        if ($opCharacter == '-' && !$expectingOperator) {                               //      Is it a negation instead of a minus?
2774//echo 'Element is a Negation operator',PHP_EOL;
2775                                $stack->push('Unary Operator','~');                                                     //      Put a negation on the stack
2776                                ++$index;                                                                                                       //              and drop the negation symbol
2777                        } elseif ($opCharacter == '%' && $expectingOperator) {
2778//echo 'Element is a Percentage operator',PHP_EOL;
2779                                $stack->push('Unary Operator','%');                                                     //      Put a percentage on the stack
2780                                ++$index;
2781                        } elseif ($opCharacter == '+' && !$expectingOperator) {                 //      Positive (unary plus rather than binary operator plus) can be discarded?
2782//echo 'Element is a Positive number, not Plus operator',PHP_EOL;
2783                                ++$index;                                                                                                       //      Drop the redundant plus symbol
2784                        } elseif ((($opCharacter == '~') || ($opCharacter == '|')) && (!$isOperandOrFunction)) {        //      We have to explicitly deny a tilde or pipe, because they are legal
2785                                return $this->_raiseFormulaError("Formula Error: Illegal character '~'");                               //              on the stack but not in the input expression
2786
2787                        } elseif ((isset(self::$_operators[$opCharacter]) or $isOperandOrFunction) && $expectingOperator) {     //      Are we putting an operator on the stack?
2788//echo 'Element with value '.$opCharacter.' is an Operator',PHP_EOL;
2789                                while($stack->count() > 0 &&
2790                                        ($o2 = $stack->last()) &&
2791                                        isset(self::$_operators[$o2['value']]) &&
2792                                        @(self::$_operatorAssociativity[$opCharacter] ? self::$_operatorPrecedence[$opCharacter] < self::$_operatorPrecedence[$o2['value']] : self::$_operatorPrecedence[$opCharacter] <= self::$_operatorPrecedence[$o2['value']])) {
2793                                        $output[] = $stack->pop();                                                              //      Swap operands and higher precedence operators from the stack to the output
2794                                }
2795                                $stack->push('Binary Operator',$opCharacter);   //      Finally put our current operator onto the stack
2796                                ++$index;
2797                                $expectingOperator = FALSE;
2798
2799                        } elseif ($opCharacter == ')' && $expectingOperator) {                  //      Are we expecting to close a parenthesis?
2800//echo 'Element is a Closing bracket',PHP_EOL;
2801                                $expectingOperand = FALSE;
2802                                while (($o2 = $stack->pop()) && $o2['value'] != '(') {          //      Pop off the stack back to the last (
2803                                        if ($o2 === NULL) return $this->_raiseFormulaError('Formula Error: Unexpected closing brace ")"');
2804                                        else $output[] = $o2;
2805                                }
2806                                $d = $stack->last(2);
2807                                if (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $d['value'], $matches)) {  //      Did this parenthesis just close a function?
2808                                        $functionName = $matches[1];                                                                            //      Get the function name
2809//echo 'Closed Function is '.$functionName,PHP_EOL;
2810                                        $d = $stack->pop();
2811                                        $argumentCount = $d['value'];           //      See how many arguments there were (argument count is the next value stored on the stack)
2812//if ($argumentCount == 0) {
2813//      echo 'With no arguments',PHP_EOL;
2814//} elseif ($argumentCount == 1) {
2815//      echo 'With 1 argument',PHP_EOL;
2816//} else {
2817//      echo 'With '.$argumentCount.' arguments',PHP_EOL;
2818//}
2819                                        $output[] = $d;                                         //      Dump the argument count on the output
2820                                        $output[] = $stack->pop();                      //      Pop the function and push onto the output
2821                                        if (isset(self::$_controlFunctions[$functionName])) {
2822//echo 'Built-in function '.$functionName,PHP_EOL;
2823                                                $expectedArgumentCount = self::$_controlFunctions[$functionName]['argumentCount'];
2824                                                $functionCall = self::$_controlFunctions[$functionName]['functionCall'];
2825                                        } elseif (isset(self::$_PHPExcelFunctions[$functionName])) {
2826//echo 'PHPExcel function '.$functionName,PHP_EOL;
2827                                                $expectedArgumentCount = self::$_PHPExcelFunctions[$functionName]['argumentCount'];
2828                                                $functionCall = self::$_PHPExcelFunctions[$functionName]['functionCall'];
2829                                        } else {        // did we somehow push a non-function on the stack? this should never happen
2830                                                return $this->_raiseFormulaError("Formula Error: Internal error, non-function on stack");
2831                                        }
2832                                        //      Check the argument count
2833                                        $argumentCountError = FALSE;
2834                                        if (is_numeric($expectedArgumentCount)) {
2835                                                if ($expectedArgumentCount < 0) {
2836//echo '$expectedArgumentCount is between 0 and '.abs($expectedArgumentCount),PHP_EOL;
2837                                                        if ($argumentCount > abs($expectedArgumentCount)) {
2838                                                                $argumentCountError = TRUE;
2839                                                                $expectedArgumentCountString = 'no more than '.abs($expectedArgumentCount);
2840                                                        }
2841                                                } else {
2842//echo '$expectedArgumentCount is numeric '.$expectedArgumentCount,PHP_EOL;
2843                                                        if ($argumentCount != $expectedArgumentCount) {
2844                                                                $argumentCountError = TRUE;
2845                                                                $expectedArgumentCountString = $expectedArgumentCount;
2846                                                        }
2847                                                }
2848                                        } elseif ($expectedArgumentCount != '*') {
2849                                                $isOperandOrFunction = preg_match('/(\d*)([-+,])(\d*)/',$expectedArgumentCount,$argMatch);
2850//print_r($argMatch);
2851//echo PHP_EOL;
2852                                                switch ($argMatch[2]) {
2853                                                        case '+' :
2854                                                                if ($argumentCount < $argMatch[1]) {
2855                                                                        $argumentCountError = TRUE;
2856                                                                        $expectedArgumentCountString = $argMatch[1].' or more ';
2857                                                                }
2858                                                                break;
2859                                                        case '-' :
2860                                                                if (($argumentCount < $argMatch[1]) || ($argumentCount > $argMatch[3])) {
2861                                                                        $argumentCountError = TRUE;
2862                                                                        $expectedArgumentCountString = 'between '.$argMatch[1].' and '.$argMatch[3];
2863                                                                }
2864                                                                break;
2865                                                        case ',' :
2866                                                                if (($argumentCount != $argMatch[1]) && ($argumentCount != $argMatch[3])) {
2867                                                                        $argumentCountError = TRUE;
2868                                                                        $expectedArgumentCountString = 'either '.$argMatch[1].' or '.$argMatch[3];
2869                                                                }
2870                                                                break;
2871                                                }
2872                                        }
2873                                        if ($argumentCountError) {
2874                                                return $this->_raiseFormulaError("Formula Error: Wrong number of arguments for $functionName() function: $argumentCount given, ".$expectedArgumentCountString." expected");
2875                                        }
2876                                }
2877                                ++$index;
2878
2879                        } elseif ($opCharacter == ',') {                        //      Is this the separator for function arguments?
2880//echo 'Element is a Function argument separator',PHP_EOL;
2881                                while (($o2 = $stack->pop()) && $o2['value'] != '(') {          //      Pop off the stack back to the last (
2882                                        if ($o2 === NULL) return $this->_raiseFormulaError("Formula Error: Unexpected ,");
2883                                        else $output[] = $o2;   // pop the argument expression stuff and push onto the output
2884                                }
2885                                //      If we've a comma when we're expecting an operand, then what we actually have is a null operand;
2886                                //              so push a null onto the stack
2887                                if (($expectingOperand) || (!$expectingOperator)) {
2888                                        $output[] = array('type' => 'NULL Value', 'value' => self::$_ExcelConstants['NULL'], 'reference' => NULL);
2889                                }
2890                                // make sure there was a function
2891                                $d = $stack->last(2);
2892                                if (!preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $d['value'], $matches))
2893                                        return $this->_raiseFormulaError("Formula Error: Unexpected ,");
2894                                $d = $stack->pop();
2895                                $stack->push($d['type'],++$d['value'],$d['reference']); // increment the argument count
2896                                $stack->push('Brace', '(');     // put the ( back on, we'll need to pop back to it again
2897                                $expectingOperator = FALSE;
2898                                $expectingOperand = TRUE;
2899                                ++$index;
2900
2901                        } elseif ($opCharacter == '(' && !$expectingOperator) {
2902//                              echo 'Element is an Opening Bracket<br />';
2903                                $stack->push('Brace', '(');
2904                                ++$index;
2905
2906                        } elseif ($isOperandOrFunction && !$expectingOperator) {        // do we now have a function/variable/number?
2907                                $expectingOperator = TRUE;
2908                                $expectingOperand = FALSE;
2909                                $val = $match[1];
2910                                $length = strlen($val);
2911//                              echo 'Element with value '.$val.' is an Operand, Variable, Constant, String, Number, Cell Reference or Function<br />';
2912
2913                                if (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $val, $matches)) {
2914                                        $val = preg_replace('/\s/','',$val);
2915//                                      echo 'Element '.$val.' is a Function<br />';
2916                                        if (isset(self::$_PHPExcelFunctions[strtoupper($matches[1])]) || isset(self::$_controlFunctions[strtoupper($matches[1])])) {    // it's a function
2917                                                $stack->push('Function', strtoupper($val));
2918                                                $ax = preg_match('/^\s*(\s*\))/i', substr($formula, $index+$length), $amatch);
2919                                                if ($ax) {
2920                                                        $stack->push('Operand Count for Function '.strtoupper($val).')', 0);
2921                                                        $expectingOperator = TRUE;
2922                                                } else {
2923                                                        $stack->push('Operand Count for Function '.strtoupper($val).')', 1);
2924                                                        $expectingOperator = FALSE;
2925                                                }
2926                                                $stack->push('Brace', '(');
2927                                        } else {        // it's a var w/ implicit multiplication
2928                                                $output[] = array('type' => 'Value', 'value' => $matches[1], 'reference' => NULL);
2929                                        }
2930                                } elseif (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $val, $matches)) {
2931//                                      echo 'Element '.$val.' is a Cell reference<br />';
2932                                        //      Watch for this case-change when modifying to allow cell references in different worksheets...
2933                                        //      Should only be applied to the actual cell column, not the worksheet name
2934
2935                                        //      If the last entry on the stack was a : operator, then we have a cell range reference
2936                                        $testPrevOp = $stack->last(1);
2937                                        if ($testPrevOp['value'] == ':') {
2938                                                //      If we have a worksheet reference, then we're playing with a 3D reference
2939                                                if ($matches[2] == '') {
2940                                                        //      Otherwise, we 'inherit' the worksheet reference from the start cell reference
2941                                                        //      The start of the cell range reference should be the last entry in $output
2942                                                        $startCellRef = $output[count($output)-1]['value'];
2943                                                        preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $startCellRef, $startMatches);
2944                                                        if ($startMatches[2] > '') {
2945                                                                $val = $startMatches[2].'!'.$val;
2946                                                        }
2947                                                } else {
2948                                                        return $this->_raiseFormulaError("3D Range references are not yet supported");
2949                                                }
2950                                        }
2951
2952                                        $output[] = array('type' => 'Cell Reference', 'value' => $val, 'reference' => $val);
2953//                                      $expectingOperator = FALSE;
2954                                } else {        // it's a variable, constant, string, number or boolean
2955//                                      echo 'Element is a Variable, Constant, String, Number or Boolean<br />';
2956                                        //      If the last entry on the stack was a : operator, then we may have a row or column range reference
2957                                        $testPrevOp = $stack->last(1);
2958                                        if ($testPrevOp['value'] == ':') {
2959                                                $startRowColRef = $output[count($output)-1]['value'];
2960                                                $rangeWS1 = '';
2961                                                if (strpos('!',$startRowColRef) !== FALSE) {
2962                                                        list($rangeWS1,$startRowColRef) = explode('!',$startRowColRef);
2963                                                }
2964                                                if ($rangeWS1 != '') $rangeWS1 .= '!';
2965                                                $rangeWS2 = $rangeWS1;
2966                                                if (strpos('!',$val) !== FALSE) {
2967                                                        list($rangeWS2,$val) = explode('!',$val);
2968                                                }
2969                                                if ($rangeWS2 != '') $rangeWS2 .= '!';
2970                                                if ((is_integer($startRowColRef)) && (ctype_digit($val)) &&
2971                                                        ($startRowColRef <= 1048576) && ($val <= 1048576)) {
2972                                                        //      Row range
2973                                                        $endRowColRef = ($pCellParent !== NULL) ? $pCellParent->getHighestColumn() : 'XFD';     //      Max 16,384 columns for Excel2007
2974                                                        $output[count($output)-1]['value'] = $rangeWS1.'A'.$startRowColRef;
2975                                                        $val = $rangeWS2.$endRowColRef.$val;
2976                                                } elseif ((ctype_alpha($startRowColRef)) && (ctype_alpha($val)) &&
2977                                                        (strlen($startRowColRef) <= 3) && (strlen($val) <= 3)) {
2978                                                        //      Column range
2979                                                        $endRowColRef = ($pCellParent !== NULL) ? $pCellParent->getHighestRow() : 1048576;              //      Max 1,048,576 rows for Excel2007
2980                                                        $output[count($output)-1]['value'] = $rangeWS1.strtoupper($startRowColRef).'1';
2981                                                        $val = $rangeWS2.$val.$endRowColRef;
2982                                                }
2983                                        }
2984
2985                                        $localeConstant = FALSE;
2986                                        if ($opCharacter == '"') {
2987//                                              echo 'Element is a String<br />';
2988                                                //      UnEscape any quotes within the string
2989                                                $val = self::_wrapResult(str_replace('""','"',self::_unwrapResult($val)));
2990                                        } elseif (is_numeric($val)) {
2991//                                              echo 'Element is a Number<br />';
2992                                                if ((strpos($val,'.') !== FALSE) || (stripos($val,'e') !== FALSE) || ($val > PHP_INT_MAX) || ($val < -PHP_INT_MAX)) {
2993//                                                      echo 'Casting '.$val.' to float<br />';
2994                                                        $val = (float) $val;
2995                                                } else {
2996//                                                      echo 'Casting '.$val.' to integer<br />';
2997                                                        $val = (integer) $val;
2998                                                }
2999                                        } elseif (isset(self::$_ExcelConstants[trim(strtoupper($val))])) {
3000                                                $excelConstant = trim(strtoupper($val));
3001//                                              echo 'Element '.$excelConstant.' is an Excel Constant<br />';
3002                                                $val = self::$_ExcelConstants[$excelConstant];
3003                                        } elseif (($localeConstant = array_search(trim(strtoupper($val)), self::$_localeBoolean)) !== FALSE) {
3004//                                              echo 'Element '.$localeConstant.' is an Excel Constant<br />';
3005                                                $val = self::$_ExcelConstants[$localeConstant];
3006                                        }
3007                                        $details = array('type' => 'Value', 'value' => $val, 'reference' => NULL);
3008                                        if ($localeConstant) { $details['localeValue'] = $localeConstant; }
3009                                        $output[] = $details;
3010                                }
3011                                $index += $length;
3012
3013                        } elseif ($opCharacter == '$') {        // absolute row or column range
3014                                ++$index;
3015                        } elseif ($opCharacter == ')') {        // miscellaneous error checking
3016                                if ($expectingOperand) {
3017                                        $output[] = array('type' => 'NULL Value', 'value' => self::$_ExcelConstants['NULL'], 'reference' => NULL);
3018                                        $expectingOperand = FALSE;
3019                                        $expectingOperator = TRUE;
3020                                } else {
3021                                        return $this->_raiseFormulaError("Formula Error: Unexpected ')'");
3022                                }
3023                        } elseif (isset(self::$_operators[$opCharacter]) && !$expectingOperator) {
3024                                return $this->_raiseFormulaError("Formula Error: Unexpected operator '$opCharacter'");
3025                        } else {        // I don't even want to know what you did to get here
3026                                return $this->_raiseFormulaError("Formula Error: An unexpected error occured");
3027                        }
3028                        //      Test for end of formula string
3029                        if ($index == strlen($formula)) {
3030                                //      Did we end with an operator?.
3031                                //      Only valid for the % unary operator
3032                                if ((isset(self::$_operators[$opCharacter])) && ($opCharacter != '%')) {
3033                                        return $this->_raiseFormulaError("Formula Error: Operator '$opCharacter' has no operands");
3034                                } else {
3035                                        break;
3036                                }
3037                        }
3038                        //      Ignore white space
3039                        while (($formula{$index} == "\n") || ($formula{$index} == "\r")) {
3040                                ++$index;
3041                        }
3042                        if ($formula{$index} == ' ') {
3043                                while ($formula{$index} == ' ') {
3044                                        ++$index;
3045                                }
3046                                //      If we're expecting an operator, but only have a space between the previous and next operands (and both are
3047                                //              Cell References) then we have an INTERSECTION operator
3048//                              echo 'Possible Intersect Operator<br />';
3049                                if (($expectingOperator) && (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'.*/Ui', substr($formula, $index), $match)) &&
3050                                        ($output[count($output)-1]['type'] == 'Cell Reference')) {
3051//                                      echo 'Element is an Intersect Operator<br />';
3052                                        while($stack->count() > 0 &&
3053                                                ($o2 = $stack->last()) &&
3054                                                isset(self::$_operators[$o2['value']]) &&
3055                                                @(self::$_operatorAssociativity[$opCharacter] ? self::$_operatorPrecedence[$opCharacter] < self::$_operatorPrecedence[$o2['value']] : self::$_operatorPrecedence[$opCharacter] <= self::$_operatorPrecedence[$o2['value']])) {
3056                                                $output[] = $stack->pop();                                                              //      Swap operands and higher precedence operators from the stack to the output
3057                                        }
3058                                        $stack->push('Binary Operator','|');    //      Put an Intersect Operator on the stack
3059                                        $expectingOperator = FALSE;
3060                                }
3061                        }
3062                }
3063
3064                while (($op = $stack->pop()) !== NULL) {        // pop everything off the stack and push onto output
3065                        if ((is_array($op) && $op['value'] == '(') || ($op === '('))
3066                                return $this->_raiseFormulaError("Formula Error: Expecting ')'");       // if there are any opening braces on the stack, then braces were unbalanced
3067                        $output[] = $op;
3068                }
3069                return $output;
3070        }       //      function _parseFormula()
3071
3072
3073        private static function _dataTestReference(&$operandData)
3074        {
3075                $operand = $operandData['value'];
3076                if (($operandData['reference'] === NULL) && (is_array($operand))) {
3077                        $rKeys = array_keys($operand);
3078                        $rowKey = array_shift($rKeys);
3079                        $cKeys = array_keys(array_keys($operand[$rowKey]));
3080                        $colKey = array_shift($cKeys);
3081                        if (ctype_upper($colKey)) {
3082                                $operandData['reference'] = $colKey.$rowKey;
3083                        }
3084                }
3085                return $operand;
3086        }
3087
3088        // evaluate postfix notation
3089        private function _processTokenStack($tokens, $cellID = NULL, PHPExcel_Cell $pCell = NULL) {
3090                if ($tokens == FALSE) return FALSE;
3091
3092                //      If we're using cell caching, then $pCell may well be flushed back to the cache (which detaches the parent cell collection),
3093                //              so we store the parent cell collection so that we can re-attach it when necessary
3094                $pCellWorksheet = ($pCell !== NULL) ? $pCell->getWorksheet() : NULL;
3095                $pCellParent = ($pCell !== NULL) ? $pCell->getParent() : null;
3096                $stack = new PHPExcel_Calculation_Token_Stack;
3097
3098                //      Loop through each token in turn
3099                foreach ($tokens as $tokenData) {
3100//                      print_r($tokenData);
3101//                      echo '<br />';
3102                        $token = $tokenData['value'];
3103//                      echo '<b>Token is '.$token.'</b><br />';
3104                        // if the token is a binary operator, pop the top two values off the stack, do the operation, and push the result back on the stack
3105                        if (isset(self::$_binaryOperators[$token])) {
3106//                              echo 'Token is a binary operator<br />';
3107                                //      We must have two operands, error if we don't
3108                                if (($operand2Data = $stack->pop()) === NULL) return $this->_raiseFormulaError('Internal error - Operand value missing from stack');
3109                                if (($operand1Data = $stack->pop()) === NULL) return $this->_raiseFormulaError('Internal error - Operand value missing from stack');
3110
3111                                $operand1 = self::_dataTestReference($operand1Data);
3112                                $operand2 = self::_dataTestReference($operand2Data);
3113
3114                                //      Log what we're doing
3115                                if ($token == ':') {
3116                                        $this->_debugLog->writeDebugLog('Evaluating Range ', $this->_showValue($operand1Data['reference']), ' ', $token, ' ', $this->_showValue($operand2Data['reference']));
3117                                } else {
3118                                        $this->_debugLog->writeDebugLog('Evaluating ', $this->_showValue($operand1), ' ', $token, ' ', $this->_showValue($operand2));
3119                                }
3120
3121                                //      Process the operation in the appropriate manner
3122                                switch ($token) {
3123                                        //      Comparison (Boolean) Operators
3124                                        case '>'        :                       //      Greater than
3125                                        case '<'        :                       //      Less than
3126                                        case '>='       :                       //      Greater than or Equal to
3127                                        case '<='       :                       //      Less than or Equal to
3128                                        case '='        :                       //      Equality
3129                                        case '<>'       :                       //      Inequality
3130                                                $this->_executeBinaryComparisonOperation($cellID,$operand1,$operand2,$token,$stack);
3131                                                break;
3132                                        //      Binary Operators
3133                                        case ':'        :                       //      Range
3134                                                $sheet1 = $sheet2 = '';
3135                                                if (strpos($operand1Data['reference'],'!') !== FALSE) {
3136                                                        list($sheet1,$operand1Data['reference']) = explode('!',$operand1Data['reference']);
3137                                                } else {
3138                                                        $sheet1 = ($pCellParent !== NULL) ? $pCellWorksheet->getTitle() : '';
3139                                                }
3140                                                if (strpos($operand2Data['reference'],'!') !== FALSE) {
3141                                                        list($sheet2,$operand2Data['reference']) = explode('!',$operand2Data['reference']);
3142                                                } else {
3143                                                        $sheet2 = $sheet1;
3144                                                }
3145                                                if ($sheet1 == $sheet2) {
3146                                                        if ($operand1Data['reference'] === NULL) {
3147                                                                if ((trim($operand1Data['value']) != '') && (is_numeric($operand1Data['value']))) {
3148                                                                        $operand1Data['reference'] = $pCell->getColumn().$operand1Data['value'];
3149                                                                } elseif (trim($operand1Data['reference']) == '') {
3150                                                                        $operand1Data['reference'] = $pCell->getCoordinate();
3151                                                                } else {
3152                                                                        $operand1Data['reference'] = $operand1Data['value'].$pCell->getRow();
3153                                                                }
3154                                                        }
3155                                                        if ($operand2Data['reference'] === NULL) {
3156                                                                if ((trim($operand2Data['value']) != '') && (is_numeric($operand2Data['value']))) {
3157                                                                        $operand2Data['reference'] = $pCell->getColumn().$operand2Data['value'];
3158                                                                } elseif (trim($operand2Data['reference']) == '') {
3159                                                                        $operand2Data['reference'] = $pCell->getCoordinate();
3160                                                                } else {
3161                                                                        $operand2Data['reference'] = $operand2Data['value'].$pCell->getRow();
3162                                                                }
3163                                                        }
3164
3165                                                        $oData = array_merge(explode(':',$operand1Data['reference']),explode(':',$operand2Data['reference']));
3166                                                        $oCol = $oRow = array();
3167                                                        foreach($oData as $oDatum) {
3168                                                                $oCR = PHPExcel_Cell::coordinateFromString($oDatum);
3169                                                                $oCol[] = PHPExcel_Cell::columnIndexFromString($oCR[0]) - 1;
3170                                                                $oRow[] = $oCR[1];
3171                                                        }
3172                                                        $cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)).min($oRow).':'.PHPExcel_Cell::stringFromColumnIndex(max($oCol)).max($oRow);
3173                                                        if ($pCellParent !== NULL) {
3174                                                                $cellValue = $this->extractCellRange($cellRef, $this->_workbook->getSheetByName($sheet1), FALSE);
3175                                                        } else {
3176                                                                return $this->_raiseFormulaError('Unable to access Cell Reference');
3177                                                        }
3178                                                        $stack->push('Cell Reference',$cellValue,$cellRef);
3179                                                } else {
3180                                                        $stack->push('Error',PHPExcel_Calculation_Functions::REF(),NULL);
3181                                                }
3182
3183                                                break;
3184                                        case '+'        :                       //      Addition
3185                                                $this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'plusEquals',$stack);
3186                                                break;
3187                                        case '-'        :                       //      Subtraction
3188                                                $this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'minusEquals',$stack);
3189                                                break;
3190                                        case '*'        :                       //      Multiplication
3191                                                $this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'arrayTimesEquals',$stack);
3192                                                break;
3193                                        case '/'        :                       //      Division
3194                                                $this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'arrayRightDivide',$stack);
3195                                                break;
3196                                        case '^'        :                       //      Exponential
3197                                                $this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'power',$stack);
3198                                                break;
3199                                        case '&'        :                       //      Concatenation
3200                                                //      If either of the operands is a matrix, we need to treat them both as matrices
3201                                                //              (converting the other operand to a matrix if need be); then perform the required
3202                                                //              matrix operation
3203                                                if (is_bool($operand1)) {
3204                                                        $operand1 = ($operand1) ? self::$_localeBoolean['TRUE'] : self::$_localeBoolean['FALSE'];
3205                                                }
3206                                                if (is_bool($operand2)) {
3207                                                        $operand2 = ($operand2) ? self::$_localeBoolean['TRUE'] : self::$_localeBoolean['FALSE'];
3208                                                }
3209                                                if ((is_array($operand1)) || (is_array($operand2))) {
3210                                                        //      Ensure that both operands are arrays/matrices
3211                                                        self::_checkMatrixOperands($operand1,$operand2,2);
3212                                                        try {
3213                                                                //      Convert operand 1 from a PHP array to a matrix
3214                                                                $matrix = new PHPExcel_Shared_JAMA_Matrix($operand1);
3215                                                                //      Perform the required operation against the operand 1 matrix, passing in operand 2
3216                                                                $matrixResult = $matrix->concat($operand2);
3217                                                                $result = $matrixResult->getArray();
3218                                                        } catch (PHPExcel_Exception $ex) {
3219                                                                $this->_debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage());
3220                                                                $result = '#VALUE!';
3221                                                        }
3222                                                } else {
3223                                                        $result = '"'.str_replace('""','"',self::_unwrapResult($operand1,'"').self::_unwrapResult($operand2,'"')).'"';
3224                                                }
3225                                                $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result));
3226                                                $stack->push('Value',$result);
3227                                                break;
3228                                        case '|'        :                       //      Intersect
3229                                                $rowIntersect = array_intersect_key($operand1,$operand2);
3230                                                $cellIntersect = $oCol = $oRow = array();
3231                                                foreach(array_keys($rowIntersect) as $row) {
3232                                                        $oRow[] = $row;
3233                                                        foreach($rowIntersect[$row] as $col => $data) {
3234                                                                $oCol[] = PHPExcel_Cell::columnIndexFromString($col) - 1;
3235                                                                $cellIntersect[$row] = array_intersect_key($operand1[$row],$operand2[$row]);
3236                                                        }
3237                                                }
3238                                                $cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)).min($oRow).':'.PHPExcel_Cell::stringFromColumnIndex(max($oCol)).max($oRow);
3239                                                $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($cellIntersect));
3240                                                $stack->push('Value',$cellIntersect,$cellRef);
3241                                                break;
3242                                }
3243
3244                        // if the token is a unary operator, pop one value off the stack, do the operation, and push it back on
3245                        } elseif (($token === '~') || ($token === '%')) {
3246//                              echo 'Token is a unary operator<br />';
3247                                if (($arg = $stack->pop()) === NULL) return $this->_raiseFormulaError('Internal error - Operand value missing from stack');
3248                                $arg = $arg['value'];
3249                                if ($token === '~') {
3250//                                      echo 'Token is a negation operator<br />';
3251                                        $this->_debugLog->writeDebugLog('Evaluating Negation of ', $this->_showValue($arg));
3252                                        $multiplier = -1;
3253                                } else {
3254//                                      echo 'Token is a percentile operator<br />';
3255                                        $this->_debugLog->writeDebugLog('Evaluating Percentile of ', $this->_showValue($arg));
3256                                        $multiplier = 0.01;
3257                                }
3258                                if (is_array($arg)) {
3259                                        self::_checkMatrixOperands($arg,$multiplier,2);
3260                                        try {
3261                                                $matrix1 = new PHPExcel_Shared_JAMA_Matrix($arg);
3262                                                $matrixResult = $matrix1->arrayTimesEquals($multiplier);
3263                                                $result = $matrixResult->getArray();
3264                                        } catch (PHPExcel_Exception $ex) {
3265                                                $this->_debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage());
3266                                                $result = '#VALUE!';
3267                                        }
3268                                        $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result));
3269                                        $stack->push('Value',$result);
3270                                } else {
3271                                        $this->_executeNumericBinaryOperation($cellID,$multiplier,$arg,'*','arrayTimesEquals',$stack);
3272                                }
3273
3274                        } elseif (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $token, $matches)) {
3275                                $cellRef = NULL;
3276//                              echo 'Element '.$token.' is a Cell reference<br />';
3277                                if (isset($matches[8])) {
3278//                                      echo 'Reference is a Range of cells<br />';
3279                                        if ($pCell === NULL) {
3280//                                              We can't access the range, so return a REF error
3281                                                $cellValue = PHPExcel_Calculation_Functions::REF();
3282                                        } else {
3283                                                $cellRef = $matches[6].$matches[7].':'.$matches[9].$matches[10];
3284                                                if ($matches[2] > '') {
3285                                                        $matches[2] = trim($matches[2],"\"'");
3286                                                        if ((strpos($matches[2],'[') !== FALSE) || (strpos($matches[2],']') !== FALSE)) {
3287                                                                //      It's a Reference to an external workbook (not currently supported)
3288                                                                return $this->_raiseFormulaError('Unable to access External Workbook');
3289                                                        }
3290                                                        $matches[2] = trim($matches[2],"\"'");
3291//                                                      echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'<br />';
3292                                                        $this->_debugLog->writeDebugLog('Evaluating Cell Range ', $cellRef, ' in worksheet ', $matches[2]);
3293                                                        if ($pCellParent !== NULL) {
3294                                                                $cellValue = $this->extractCellRange($cellRef, $this->_workbook->getSheetByName($matches[2]), FALSE);
3295                                                        } else {
3296                                                                return $this->_raiseFormulaError('Unable to access Cell Reference');
3297                                                        }
3298                                                        $this->_debugLog->writeDebugLog('Evaluation Result for cells ', $cellRef, ' in worksheet ', $matches[2], ' is ', $this->_showTypeDetails($cellValue));
3299//                                                      $cellRef = $matches[2].'!'.$cellRef;
3300                                                } else {
3301//                                                      echo '$cellRef='.$cellRef.' in current worksheet<br />';
3302                                                        $this->_debugLog->writeDebugLog('Evaluating Cell Range ', $cellRef, ' in current worksheet');
3303                                                        if ($pCellParent !== NULL) {
3304                                                                $cellValue = $this->extractCellRange($cellRef, $pCellWorksheet, FALSE);
3305                                                        } else {
3306                                                                return $this->_raiseFormulaError('Unable to access Cell Reference');
3307                                                        }
3308                                                        $this->_debugLog->writeDebugLog('Evaluation Result for cells ', $cellRef, ' is ', $this->_showTypeDetails($cellValue));
3309                                                }
3310                                        }
3311                                } else {
3312//                                      echo 'Reference is a single Cell<br />';
3313                                        if ($pCell === NULL) {
3314//                                              We can't access the cell, so return a REF error
3315                                                $cellValue = PHPExcel_Calculation_Functions::REF();
3316                                        } else {
3317                                                $cellRef = $matches[6].$matches[7];
3318                                                if ($matches[2] > '') {
3319                                                        $matches[2] = trim($matches[2],"\"'");
3320                                                        if ((strpos($matches[2],'[') !== FALSE) || (strpos($matches[2],']') !== FALSE)) {
3321                                                                //      It's a Reference to an external workbook (not currently supported)
3322                                                                return $this->_raiseFormulaError('Unable to access External Workbook');
3323                                                        }
3324//                                                      echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'<br />';
3325                                                        $this->_debugLog->writeDebugLog('Evaluating Cell ', $cellRef, ' in worksheet ', $matches[2]);
3326                                                        if ($pCellParent !== NULL) {
3327                                                                $cellSheet = $this->_workbook->getSheetByName($matches[2]);
3328                                                                if ($cellSheet && $cellSheet->cellExists($cellRef)) {
3329                                                                        $cellValue = $this->extractCellRange($cellRef, $this->_workbook->getSheetByName($matches[2]), FALSE);
3330                                                                        $pCell->attach($pCellParent);
3331                                                                } else {
3332                                                                        $cellValue = NULL;
3333                                                                }
3334                                                        } else {
3335                                                                return $this->_raiseFormulaError('Unable to access Cell Reference');
3336                                                        }
3337                                                        $this->_debugLog->writeDebugLog('Evaluation Result for cell ', $cellRef, ' in worksheet ', $matches[2], ' is ', $this->_showTypeDetails($cellValue));
3338//                                                      $cellRef = $matches[2].'!'.$cellRef;
3339                                                } else {
3340//                                                      echo '$cellRef='.$cellRef.' in current worksheet<br />';
3341                                                        $this->_debugLog->writeDebugLog('Evaluating Cell ', $cellRef, ' in current worksheet');
3342                                                        if ($pCellParent->isDataSet($cellRef)) {
3343                                                                $cellValue = $this->extractCellRange($cellRef, $pCellWorksheet, FALSE);
3344                                                                $pCell->attach($pCellParent);
3345                                                        } else {
3346                                                                $cellValue = NULL;
3347                                                        }
3348                                                        $this->_debugLog->writeDebugLog('Evaluation Result for cell ', $cellRef, ' is ', $this->_showTypeDetails($cellValue));
3349                                                }
3350                                        }
3351                                }
3352                                $stack->push('Value',$cellValue,$cellRef);
3353
3354                        // if the token is a function, pop arguments off the stack, hand them to the function, and push the result back on
3355                        } elseif (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $token, $matches)) {
3356//                              echo 'Token is a function<br />';
3357                                $functionName = $matches[1];
3358                                $argCount = $stack->pop();
3359                                $argCount = $argCount['value'];
3360                                if ($functionName != 'MKMATRIX') {
3361                                        $this->_debugLog->writeDebugLog('Evaluating Function ', self::_localeFunc($functionName), '() with ', (($argCount == 0) ? 'no' : $argCount), ' argument', (($argCount == 1) ? '' : 's'));
3362                                }
3363                                if ((isset(self::$_PHPExcelFunctions[$functionName])) || (isset(self::$_controlFunctions[$functionName]))) {    // function
3364                                        if (isset(self::$_PHPExcelFunctions[$functionName])) {
3365                                                $functionCall = self::$_PHPExcelFunctions[$functionName]['functionCall'];
3366                                                $passByReference = isset(self::$_PHPExcelFunctions[$functionName]['passByReference']);
3367                                                $passCellReference = isset(self::$_PHPExcelFunctions[$functionName]['passCellReference']);
3368                                        } elseif (isset(self::$_controlFunctions[$functionName])) {
3369                                                $functionCall = self::$_controlFunctions[$functionName]['functionCall'];
3370                                                $passByReference = isset(self::$_controlFunctions[$functionName]['passByReference']);
3371                                                $passCellReference = isset(self::$_controlFunctions[$functionName]['passCellReference']);
3372                                        }
3373                                        // get the arguments for this function
3374//                                      echo 'Function '.$functionName.' expects '.$argCount.' arguments<br />';
3375                                        $args = $argArrayVals = array();
3376                                        for ($i = 0; $i < $argCount; ++$i) {
3377                                                $arg = $stack->pop();
3378                                                $a = $argCount - $i - 1;
3379                                                if (($passByReference) &&
3380                                                        (isset(self::$_PHPExcelFunctions[$functionName]['passByReference'][$a])) &&
3381                                                        (self::$_PHPExcelFunctions[$functionName]['passByReference'][$a])) {
3382                                                        if ($arg['reference'] === NULL) {
3383                                                                $args[] = $cellID;
3384                                                                if ($functionName != 'MKMATRIX') { $argArrayVals[] = $this->_showValue($cellID); }
3385                                                        } else {
3386                                                                $args[] = $arg['reference'];
3387                                                                if ($functionName != 'MKMATRIX') { $argArrayVals[] = $this->_showValue($arg['reference']); }
3388                                                        }
3389                                                } else {
3390                                                        $args[] = self::_unwrapResult($arg['value']);
3391                                                        if ($functionName != 'MKMATRIX') { $argArrayVals[] = $this->_showValue($arg['value']); }
3392                                                }
3393                                        }
3394                                        //      Reverse the order of the arguments
3395                                        krsort($args);
3396                                        if (($passByReference) && ($argCount == 0)) {
3397                                                $args[] = $cellID;
3398                                                $argArrayVals[] = $this->_showValue($cellID);
3399                                        }
3400//                                      echo 'Arguments are: ';
3401//                                      print_r($args);
3402//                                      echo '<br />';
3403                                        if ($functionName != 'MKMATRIX') {
3404                                                if ($this->_debugLog->getWriteDebugLog()) {
3405                                                        krsort($argArrayVals);
3406                                                        $this->_debugLog->writeDebugLog('Evaluating ', self::_localeFunc($functionName), '( ', implode(self::$_localeArgumentSeparator.' ',PHPExcel_Calculation_Functions::flattenArray($argArrayVals)), ' )');
3407                                                }
3408                                        }
3409                                        //      Process each argument in turn, building the return value as an array
3410//                                      if (($argCount == 1) && (is_array($args[1])) && ($functionName != 'MKMATRIX')) {
3411//                                              $operand1 = $args[1];
3412//                                              $this->_debugLog->writeDebugLog('Argument is a matrix: ', $this->_showValue($operand1));
3413//                                              $result = array();
3414//                                              $row = 0;
3415//                                              foreach($operand1 as $args) {
3416//                                                      if (is_array($args)) {
3417//                                                              foreach($args as $arg) {
3418//                                                                      $this->_debugLog->writeDebugLog('Evaluating ', self::_localeFunc($functionName), '( ', $this->_showValue($arg), ' )');
3419//                                                                      $r = call_user_func_array($functionCall,$arg);
3420//                                                                      $this->_debugLog->writeDebugLog('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($r));
3421//                                                                      $result[$row][] = $r;
3422//                                                              }
3423//                                                              ++$row;
3424//                                                      } else {
3425//                                                              $this->_debugLog->writeDebugLog('Evaluating ', self::_localeFunc($functionName), '( ', $this->_showValue($args), ' )');
3426//                                                              $r = call_user_func_array($functionCall,$args);
3427//                                                              $this->_debugLog->writeDebugLog('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($r));
3428//                                                              $result[] = $r;
3429//                                                      }
3430//                                              }
3431//                                      } else {
3432                                        //      Process the argument with the appropriate function call
3433                                                if ($passCellReference) {
3434                                                        $args[] = $pCell;
3435                                                }
3436                                                if (strpos($functionCall,'::') !== FALSE) {
3437                                                        $result = call_user_func_array(explode('::',$functionCall),$args);
3438                                                } else {
3439                                                        foreach($args as &$arg) {
3440                                                                $arg = PHPExcel_Calculation_Functions::flattenSingleValue($arg);
3441                                                        }
3442                                                        unset($arg);
3443                                                        $result = call_user_func_array($functionCall,$args);
3444                                                }
3445//                                      }
3446                                        if ($functionName != 'MKMATRIX') {
3447                                                $this->_debugLog->writeDebugLog('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($result));
3448                                        }
3449                                        $stack->push('Value',self::_wrapResult($result));
3450                                }
3451
3452                        } else {
3453                                // if the token is a number, boolean, string or an Excel error, push it onto the stack
3454                                if (isset(self::$_ExcelConstants[strtoupper($token)])) {
3455                                        $excelConstant = strtoupper($token);
3456//                                      echo 'Token is a PHPExcel constant: '.$excelConstant.'<br />';
3457                                        $stack->push('Constant Value',self::$_ExcelConstants[$excelConstant]);
3458                                        $this->_debugLog->writeDebugLog('Evaluating Constant ', $excelConstant, ' as ', $this->_showTypeDetails(self::$_ExcelConstants[$excelConstant]));
3459                                } elseif ((is_numeric($token)) || ($token === NULL) || (is_bool($token)) || ($token == '') || ($token{0} == '"') || ($token{0} == '#')) {
3460//                                      echo 'Token is a number, boolean, string, null or an Excel error<br />';
3461                                        $stack->push('Value',$token);
3462                                // if the token is a named range, push the named range name onto the stack
3463                                } elseif (preg_match('/^'.self::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $token, $matches)) {
3464//                                      echo 'Token is a named range<br />';
3465                                        $namedRange = $matches[6];
3466//                                      echo 'Named Range is '.$namedRange.'<br />';
3467                                        $this->_debugLog->writeDebugLog('Evaluating Named Range ', $namedRange);
3468                                        $cellValue = $this->extractNamedRange($namedRange, ((NULL !== $pCell) ? $pCellWorksheet : NULL), FALSE);
3469                                        $pCell->attach($pCellParent);
3470                                        $this->_debugLog->writeDebugLog('Evaluation Result for named range ', $namedRange, ' is ', $this->_showTypeDetails($cellValue));
3471                                        $stack->push('Named Range',$cellValue,$namedRange);
3472                                } else {
3473                                        return $this->_raiseFormulaError("undefined variable '$token'");
3474                                }
3475                        }
3476                }
3477                // when we're out of tokens, the stack should have a single element, the final result
3478                if ($stack->count() != 1) return $this->_raiseFormulaError("internal error");
3479                $output = $stack->pop();
3480                $output = $output['value'];
3481
3482//              if ((is_array($output)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) {
3483//                      return array_shift(PHPExcel_Calculation_Functions::flattenArray($output));
3484//              }
3485                return $output;
3486        }       //      function _processTokenStack()
3487
3488
3489        private function _validateBinaryOperand($cellID, &$operand, &$stack) {
3490                if (is_array($operand)) {
3491                        if ((count($operand, COUNT_RECURSIVE) - count($operand)) == 1) {
3492                                do {
3493                                        $operand = array_pop($operand);
3494                                } while (is_array($operand));
3495                        }
3496                }
3497                //      Numbers, matrices and booleans can pass straight through, as they're already valid
3498                if (is_string($operand)) {
3499                        //      We only need special validations for the operand if it is a string
3500                        //      Start by stripping off the quotation marks we use to identify true excel string values internally
3501                        if ($operand > '' && $operand{0} == '"') { $operand = self::_unwrapResult($operand); }
3502                        //      If the string is a numeric value, we treat it as a numeric, so no further testing
3503                        if (!is_numeric($operand)) {
3504                                //      If not a numeric, test to see if the value is an Excel error, and so can't be used in normal binary operations
3505                                if ($operand > '' && $operand{0} == '#') {
3506                                        $stack->push('Value', $operand);
3507                                        $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($operand));
3508                                        return FALSE;
3509                                } elseif (!PHPExcel_Shared_String::convertToNumberIfFraction($operand)) {
3510                                        //      If not a numeric or a fraction, then it's a text string, and so can't be used in mathematical binary operations
3511                                        $stack->push('Value', '#VALUE!');
3512                                        $this->_debugLog->writeDebugLog('Evaluation Result is a ', $this->_showTypeDetails('#VALUE!'));
3513                                        return FALSE;
3514                                }
3515                        }
3516                }
3517
3518                //      return a true if the value of the operand is one that we can use in normal binary operations
3519                return TRUE;
3520        }       //      function _validateBinaryOperand()
3521
3522
3523        private function _executeBinaryComparisonOperation($cellID, $operand1, $operand2, $operation, &$stack, $recursingArrays=FALSE) {
3524                //      If we're dealing with matrix operations, we want a matrix result
3525                if ((is_array($operand1)) || (is_array($operand2))) {
3526                        $result = array();
3527                        if ((is_array($operand1)) && (!is_array($operand2))) {
3528                                foreach($operand1 as $x => $operandData) {
3529                                        $this->_debugLog->writeDebugLog('Evaluating Comparison ', $this->_showValue($operandData), ' ', $operation, ' ', $this->_showValue($operand2));
3530                                        $this->_executeBinaryComparisonOperation($cellID,$operandData,$operand2,$operation,$stack);
3531                                        $r = $stack->pop();
3532                                        $result[$x] = $r['value'];
3533                                }
3534                        } elseif ((!is_array($operand1)) && (is_array($operand2))) {
3535                                foreach($operand2 as $x => $operandData) {
3536                                        $this->_debugLog->writeDebugLog('Evaluating Comparison ', $this->_showValue($operand1), ' ', $operation, ' ', $this->_showValue($operandData));
3537                                        $this->_executeBinaryComparisonOperation($cellID,$operand1,$operandData,$operation,$stack);
3538                                        $r = $stack->pop();
3539                                        $result[$x] = $r['value'];
3540                                }
3541                        } else {
3542                                if (!$recursingArrays) { self::_checkMatrixOperands($operand1,$operand2,2); }
3543                                foreach($operand1 as $x => $operandData) {
3544                                        $this->_debugLog->writeDebugLog('Evaluating Comparison ', $this->_showValue($operandData), ' ', $operation, ' ', $this->_showValue($operand2[$x]));
3545                                        $this->_executeBinaryComparisonOperation($cellID,$operandData,$operand2[$x],$operation,$stack,TRUE);
3546                                        $r = $stack->pop();
3547                                        $result[$x] = $r['value'];
3548                                }
3549                        }
3550                        //      Log the result details
3551                        $this->_debugLog->writeDebugLog('Comparison Evaluation Result is ', $this->_showTypeDetails($result));
3552                        //      And push the result onto the stack
3553                        $stack->push('Array',$result);
3554                        return TRUE;
3555                }
3556
3557                //      Simple validate the two operands if they are string values
3558                if (is_string($operand1) && $operand1 > '' && $operand1{0} == '"') { $operand1 = self::_unwrapResult($operand1); }
3559                if (is_string($operand2) && $operand2 > '' && $operand2{0} == '"') { $operand2 = self::_unwrapResult($operand2); }
3560
3561                // Use case insensitive comparaison if not OpenOffice mode
3562                if (PHPExcel_Calculation_Functions::getCompatibilityMode() != PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE)
3563                {
3564                        if (is_string($operand1)) {
3565                                $operand1 = strtoupper($operand1);
3566                        }
3567
3568                        if (is_string($operand2)) {
3569                                $operand2 = strtoupper($operand2);
3570                        }
3571                }
3572
3573                $useLowercaseFirstComparison = is_string($operand1) && is_string($operand2) && PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE;
3574
3575                //      execute the necessary operation
3576                switch ($operation) {
3577                        //      Greater than
3578                        case '>':
3579                                if ($useLowercaseFirstComparison) {
3580                                        $result = $this->strcmpLowercaseFirst($operand1, $operand2) > 0;
3581                                } else {
3582                                        $result = ($operand1 > $operand2);
3583                                }
3584                                break;
3585                        //      Less than
3586                        case '<':
3587                                if ($useLowercaseFirstComparison) {
3588                                        $result = $this->strcmpLowercaseFirst($operand1, $operand2) < 0;
3589                                } else {
3590                                        $result = ($operand1 < $operand2);
3591                                }
3592                                break;
3593                        //      Equality
3594                        case '=':
3595                                $result = ($operand1 == $operand2);
3596                                break;
3597                        //      Greater than or equal
3598                        case '>=':
3599                                if ($useLowercaseFirstComparison) {
3600                                        $result = $this->strcmpLowercaseFirst($operand1, $operand2) >= 0;
3601                                } else {
3602                                        $result = ($operand1 >= $operand2);
3603                                }
3604                                break;
3605                        //      Less than or equal
3606                        case '<=':
3607                                if ($useLowercaseFirstComparison) {
3608                                        $result = $this->strcmpLowercaseFirst($operand1, $operand2) <= 0;
3609                                } else {
3610                                        $result = ($operand1 <= $operand2);
3611                                }
3612                                break;
3613                        //      Inequality
3614                        case '<>':
3615                                $result = ($operand1 != $operand2);
3616                                break;
3617                }
3618
3619                //      Log the result details
3620                $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result));
3621                //      And push the result onto the stack
3622                $stack->push('Value',$result);
3623                return TRUE;
3624        }       //      function _executeBinaryComparisonOperation()
3625
3626        /**
3627         * Compare two strings in the same way as strcmp() except that lowercase come before uppercase letters
3628         * @param string $str1
3629         * @param string $str2
3630         * @return integer
3631         */
3632        private function strcmpLowercaseFirst($str1, $str2)
3633        {
3634                $from = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
3635                $to = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
3636                $inversedStr1 = strtr($str1, $from, $to);
3637                $inversedStr2 = strtr($str2, $from, $to);
3638
3639                return strcmp($inversedStr1, $inversedStr2);
3640        }
3641
3642        private function _executeNumericBinaryOperation($cellID,$operand1,$operand2,$operation,$matrixFunction,&$stack) {
3643                //      Validate the two operands
3644                if (!$this->_validateBinaryOperand($cellID,$operand1,$stack)) return FALSE;
3645                if (!$this->_validateBinaryOperand($cellID,$operand2,$stack)) return FALSE;
3646
3647                //      If either of the operands is a matrix, we need to treat them both as matrices
3648                //              (converting the other operand to a matrix if need be); then perform the required
3649                //              matrix operation
3650                if ((is_array($operand1)) || (is_array($operand2))) {
3651                        //      Ensure that both operands are arrays/matrices of the same size
3652                        self::_checkMatrixOperands($operand1, $operand2, 2);
3653
3654                        try {
3655                                //      Convert operand 1 from a PHP array to a matrix
3656                                $matrix = new PHPExcel_Shared_JAMA_Matrix($operand1);
3657                                //      Perform the required operation against the operand 1 matrix, passing in operand 2
3658                                $matrixResult = $matrix->$matrixFunction($operand2);
3659                                $result = $matrixResult->getArray();
3660                        } catch (PHPExcel_Exception $ex) {
3661                                $this->_debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage());
3662                                $result = '#VALUE!';
3663                        }
3664                } else {
3665                        if ((PHPExcel_Calculation_Functions::getCompatibilityMode() != PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) &&
3666                                ((is_string($operand1) && !is_numeric($operand1) && strlen($operand1)>0) ||
3667                 (is_string($operand2) && !is_numeric($operand2) && strlen($operand2)>0))) {
3668                                $result = PHPExcel_Calculation_Functions::VALUE();
3669                        } else {
3670                                //      If we're dealing with non-matrix operations, execute the necessary operation
3671                                switch ($operation) {
3672                                        //      Addition
3673                                        case '+':
3674                                                $result = $operand1 + $operand2;
3675                                                break;
3676                                        //      Subtraction
3677                                        case '-':
3678                                                $result = $operand1 - $operand2;
3679                                                break;
3680                                        //      Multiplication
3681                                        case '*':
3682                                                $result = $operand1 * $operand2;
3683                                                break;
3684                                        //      Division
3685                                        case '/':
3686                                                if ($operand2 == 0) {
3687                                                        //      Trap for Divide by Zero error
3688                                                        $stack->push('Value','#DIV/0!');
3689                                                        $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails('#DIV/0!'));
3690                                                        return FALSE;
3691                                                } else {
3692                                                        $result = $operand1 / $operand2;
3693                                                }
3694                                                break;
3695                                        //      Power
3696                                        case '^':
3697                                                $result = pow($operand1, $operand2);
3698                                                break;
3699                                }
3700                        }
3701                }
3702
3703                //      Log the result details
3704                $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result));
3705                //      And push the result onto the stack
3706                $stack->push('Value',$result);
3707                return TRUE;
3708        }       //      function _executeNumericBinaryOperation()
3709
3710
3711        // trigger an error, but nicely, if need be
3712        protected function _raiseFormulaError($errorMessage) {
3713                $this->formulaError = $errorMessage;
3714                $this->_cyclicReferenceStack->clear();
3715                if (!$this->suppressFormulaErrors) throw new PHPExcel_Calculation_Exception($errorMessage);
3716                trigger_error($errorMessage, E_USER_ERROR);
3717        }       //      function _raiseFormulaError()
3718
3719
3720        /**
3721         * Extract range values
3722         *
3723         * @param       string                          &$pRange        String based range representation
3724         * @param       PHPExcel_Worksheet      $pSheet         Worksheet
3725         * @param       boolean                         $resetLog       Flag indicating whether calculation log should be reset or not
3726         * @return  mixed                               Array of values in range if range contains more than one element. Otherwise, a single value is returned.
3727         * @throws      PHPExcel_Calculation_Exception
3728         */
3729        public function extractCellRange(&$pRange = 'A1', PHPExcel_Worksheet $pSheet = NULL, $resetLog = TRUE) {
3730                // Return value
3731                $returnValue = array ();
3732
3733//              echo 'extractCellRange('.$pRange.')',PHP_EOL;
3734                if ($pSheet !== NULL) {
3735                        $pSheetName = $pSheet->getTitle();
3736//                      echo 'Passed sheet name is '.$pSheetName.PHP_EOL;
3737//                      echo 'Range reference is '.$pRange.PHP_EOL;
3738                        if (strpos ($pRange, '!') !== false) {
3739//                              echo '$pRange reference includes sheet reference',PHP_EOL;
3740                                list($pSheetName,$pRange) = PHPExcel_Worksheet::extractSheetTitle($pRange, true);
3741//                              echo 'New sheet name is '.$pSheetName,PHP_EOL;
3742//                              echo 'Adjusted Range reference is '.$pRange,PHP_EOL;
3743                                $pSheet = $this->_workbook->getSheetByName($pSheetName);
3744                        }
3745
3746                        // Extract range
3747                        $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange);
3748                        $pRange = $pSheetName.'!'.$pRange;
3749                        if (!isset($aReferences[1])) {
3750                                //      Single cell in range
3751                                sscanf($aReferences[0],'%[A-Z]%d', $currentCol, $currentRow);
3752                                $cellValue = NULL;
3753                                if ($pSheet->cellExists($aReferences[0])) {
3754                                        $returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog);
3755                                } else {
3756                                        $returnValue[$currentRow][$currentCol] = NULL;
3757                                }
3758                        } else {
3759                                // Extract cell data for all cells in the range
3760                                foreach ($aReferences as $reference) {
3761                                        // Extract range
3762                                        sscanf($reference,'%[A-Z]%d', $currentCol, $currentRow);
3763                                        $cellValue = NULL;
3764                                        if ($pSheet->cellExists($reference)) {
3765                                                $returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog);
3766                                        } else {
3767                                                $returnValue[$currentRow][$currentCol] = NULL;
3768                                        }
3769                                }
3770                        }
3771                }
3772
3773                // Return
3774                return $returnValue;
3775        }       //      function extractCellRange()
3776
3777
3778        /**
3779         * Extract range values
3780         *
3781         * @param       string                          &$pRange        String based range representation
3782         * @param       PHPExcel_Worksheet      $pSheet         Worksheet
3783         * @return  mixed                               Array of values in range if range contains more than one element. Otherwise, a single value is returned.
3784         * @param       boolean                         $resetLog       Flag indicating whether calculation log should be reset or not
3785         * @throws      PHPExcel_Calculation_Exception
3786         */
3787        public function extractNamedRange(&$pRange = 'A1', PHPExcel_Worksheet $pSheet = NULL, $resetLog = TRUE) {
3788                // Return value
3789                $returnValue = array ();
3790
3791//              echo 'extractNamedRange('.$pRange.')<br />';
3792                if ($pSheet !== NULL) {
3793                        $pSheetName = $pSheet->getTitle();
3794//                      echo 'Current sheet name is '.$pSheetName.'<br />';
3795//                      echo 'Range reference is '.$pRange.'<br />';
3796                        if (strpos ($pRange, '!') !== false) {
3797//                              echo '$pRange reference includes sheet reference',PHP_EOL;
3798                                list($pSheetName,$pRange) = PHPExcel_Worksheet::extractSheetTitle($pRange, true);
3799//                              echo 'New sheet name is '.$pSheetName,PHP_EOL;
3800//                              echo 'Adjusted Range reference is '.$pRange,PHP_EOL;
3801                                $pSheet = $this->_workbook->getSheetByName($pSheetName);
3802                        }
3803
3804                        // Named range?
3805                        $namedRange = PHPExcel_NamedRange::resolveRange($pRange, $pSheet);
3806                        if ($namedRange !== NULL) {
3807                                $pSheet = $namedRange->getWorksheet();
3808//                              echo 'Named Range '.$pRange.' (';
3809                                $pRange = $namedRange->getRange();
3810                                $splitRange = PHPExcel_Cell::splitRange($pRange);
3811                                //      Convert row and column references
3812                                if (ctype_alpha($splitRange[0][0])) {
3813                                        $pRange = $splitRange[0][0] . '1:' . $splitRange[0][1] . $namedRange->getWorksheet()->getHighestRow();
3814                                } elseif(ctype_digit($splitRange[0][0])) {
3815                                        $pRange = 'A' . $splitRange[0][0] . ':' . $namedRange->getWorksheet()->getHighestColumn() . $splitRange[0][1];
3816                                }
3817//                              echo $pRange.') is in sheet '.$namedRange->getWorksheet()->getTitle().'<br />';
3818
3819//                              if ($pSheet->getTitle() != $namedRange->getWorksheet()->getTitle()) {
3820//                                      if (!$namedRange->getLocalOnly()) {
3821//                                              $pSheet = $namedRange->getWorksheet();
3822//                                      } else {
3823//                                              return $returnValue;
3824//                                      }
3825//                              }
3826                        } else {
3827                                return PHPExcel_Calculation_Functions::REF();
3828                        }
3829
3830                        // Extract range
3831                        $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange);
3832//                      var_dump($aReferences);
3833                        if (!isset($aReferences[1])) {
3834                                //      Single cell (or single column or row) in range
3835                                list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($aReferences[0]);
3836                                $cellValue = NULL;
3837                                if ($pSheet->cellExists($aReferences[0])) {
3838                                        $returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog);
3839                                } else {
3840                                        $returnValue[$currentRow][$currentCol] = NULL;
3841                                }
3842                        } else {
3843                                // Extract cell data for all cells in the range
3844                                foreach ($aReferences as $reference) {
3845                                        // Extract range
3846                                        list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($reference);
3847//                                      echo 'NAMED RANGE: $currentCol='.$currentCol.' $currentRow='.$currentRow.'<br />';
3848                                        $cellValue = NULL;
3849                                        if ($pSheet->cellExists($reference)) {
3850                                                $returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog);
3851                                        } else {
3852                                                $returnValue[$currentRow][$currentCol] = NULL;
3853                                        }
3854                                }
3855                        }
3856//                              print_r($returnValue);
3857//                      echo '<br />';
3858                }
3859
3860                // Return
3861                return $returnValue;
3862        }       //      function extractNamedRange()
3863
3864
3865        /**
3866         * Is a specific function implemented?
3867         *
3868         * @param       string  $pFunction      Function Name
3869         * @return      boolean
3870         */
3871        public function isImplemented($pFunction = '') {
3872                $pFunction = strtoupper ($pFunction);
3873                if (isset(self::$_PHPExcelFunctions[$pFunction])) {
3874                        return (self::$_PHPExcelFunctions[$pFunction]['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY');
3875                } else {
3876                        return FALSE;
3877                }
3878        }       //      function isImplemented()
3879
3880
3881        /**
3882         * Get a list of all implemented functions as an array of function objects
3883         *
3884         * @return      array of PHPExcel_Calculation_Function
3885         */
3886        public function listFunctions() {
3887                // Return value
3888                $returnValue = array();
3889                // Loop functions
3890                foreach(self::$_PHPExcelFunctions as $functionName => $function) {
3891                        if ($function['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY') {
3892                                $returnValue[$functionName] = new PHPExcel_Calculation_Function($function['category'],
3893                                                                                                                                                                $functionName,
3894                                                                                                                                                                $function['functionCall']
3895                                                                                                                                                           );
3896                        }
3897                }
3898
3899                // Return
3900                return $returnValue;
3901        }       //      function listFunctions()
3902
3903
3904        /**
3905         * Get a list of all Excel function names
3906         *
3907         * @return      array
3908         */
3909        public function listAllFunctionNames() {
3910                return array_keys(self::$_PHPExcelFunctions);
3911        }       //      function listAllFunctionNames()
3912
3913        /**
3914         * Get a list of implemented Excel function names
3915         *
3916         * @return      array
3917         */
3918        public function listFunctionNames() {
3919                // Return value
3920                $returnValue = array();
3921                // Loop functions
3922                foreach(self::$_PHPExcelFunctions as $functionName => $function) {
3923                        if ($function['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY') {
3924                                $returnValue[] = $functionName;
3925                        }
3926                }
3927
3928                // Return
3929                return $returnValue;
3930        }       //      function listFunctionNames()
3931
3932}       //      class PHPExcel_Calculation
3933
Note: See TracBrowser for help on using the repository browser.