5
* Copyright (c) 2006 - 2009 PHPExcel
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.
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.
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
22
* @package PHPExcel_Calculation
23
* @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
24
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
25
* @version 1.7.0, 2009-08-10
29
/** PHPExcel root directory */
30
if (!defined('PHPEXCEL_ROOT')) {
34
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../');
38
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/Matrix.php';
40
/** PHPExcel_Calculation_Function */
41
require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/Function.php';
43
/** PHPExcel_Calculation_Functions */
44
require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/Functions.php';
48
* PHPExcel_Calculation (Singleton)
51
* @package PHPExcel_Calculation
52
* @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
54
class PHPExcel_Calculation {
57
/** Regular Expressions */
59
const CALCULATION_REGEXP_NUMBER = '[-+]?\d*\.?\d+(e[-+]?\d+)?';
61
const CALCULATION_REGEXP_STRING = '"(?:[^"]|"")*"';
63
const CALCULATION_REGEXP_OPENBRACE = '\(';
65
const CALCULATION_REGEXP_FUNCTION = '([A-Z][A-Z0-9\.]*)[\s]*\(';
66
// Cell reference (cell or range of cells, with or without a sheet reference)
67
const CALCULATION_REGEXP_CELLREF = '(((\w*)|(\'.*\')|(\".*\"))!)?\$?([a-z]+)\$?(\d+)(:\$?([a-z]+)\$?(\d+))?';
68
// Named Range of cells
69
const CALCULATION_REGEXP_NAMEDRANGE = '(((\w*)|(\'.*\')|(\".*\"))!)?([_A-Z][_A-Z0-9]*)';
71
const CALCULATION_REGEXP_ERROR = '\#[^!]+!';
75
const RETURN_ARRAY_AS_VALUE = 'value';
76
const RETURN_ARRAY_AS_ARRAY = 'array';
78
private static $returnArrayAsType = self::RETURN_ARRAY_AS_ARRAY;
81
* Instance of this class
84
* @var PHPExcel_Calculation
86
private static $_instance;
95
private $_calculationCache = array ();
99
* Calculation cache enabled
104
private $_calculationCacheEnabled = true;
108
* Calculation cache expiration time
113
private $_calculationCacheExpirationTime = 0.01;
117
* List of operators that can be used within formulae
122
private $_operators = array('+', '-', '*', '/', '^', '&', '%', '_', '>', '<', '=', '>=', '<=', '<>');
126
* List of binary operators (those that expect two operands)
131
private $_binaryOperators = array('+', '-', '*', '/', '^', '&', '>', '<', '=', '>=', '<=', '<>');
133
public $suppressFormulaErrors = false;
134
public $formulaError = null;
135
public $writeDebugLog = false;
136
private $debugLogStack = array();
137
public $debugLog = array();
140
// Constant conversion from text name/value to actual (datatyped) value
141
private $_ExcelConstants = array('TRUE' => True,
146
// PHPExcel functions
147
private $_PHPExcelFunctions = array( // PHPExcel functions
148
'ABS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
149
'functionCall' => 'abs',
150
'argumentCount' => '1'
152
'ACCRINT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
153
'functionCall' => 'PHPExcel_Calculation_Functions::ACCRINT',
154
'argumentCount' => '4-7'
156
'ACCRINTM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
157
'functionCall' => 'PHPExcel_Calculation_Functions::ACCRINTM',
158
'argumentCount' => '3-5'
160
'ACOS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
161
'functionCall' => 'acos',
162
'argumentCount' => '1'
164
'ACOSH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
165
'functionCall' => 'acosh',
166
'argumentCount' => '1'
168
'ADDRESS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
169
'functionCall' => 'PHPExcel_Calculation_Functions::CELL_ADDRESS',
170
'argumentCount' => '2-5'
172
'AMORDEGRC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
173
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
174
'argumentCount' => '6,7'
176
'AMORLINC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
177
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
178
'argumentCount' => '6,7'
180
'AND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL,
181
'functionCall' => 'PHPExcel_Calculation_Functions::LOGICAL_AND',
182
'argumentCount' => '1+'
184
'AREAS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
185
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
186
'argumentCount' => '1'
188
'ASC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
189
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
190
'argumentCount' => '1'
192
'ASIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
193
'functionCall' => 'asin',
194
'argumentCount' => '1'
196
'ASINH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
197
'functionCall' => 'asinh',
198
'argumentCount' => '1'
200
'ATAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
201
'functionCall' => 'atan',
202
'argumentCount' => '1'
204
'ATAN2' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
205
'functionCall' => 'PHPExcel_Calculation_Functions::REVERSE_ATAN2',
206
'argumentCount' => '2'
208
'ATANH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
209
'functionCall' => 'atanh',
210
'argumentCount' => '1'
212
'AVEDEV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
213
'functionCall' => 'PHPExcel_Calculation_Functions::AVEDEV',
214
'argumentCount' => '1+'
216
'AVERAGE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
217
'functionCall' => 'PHPExcel_Calculation_Functions::AVERAGE',
218
'argumentCount' => '1+'
220
'AVERAGEA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
221
'functionCall' => 'PHPExcel_Calculation_Functions::AVERAGEA',
222
'argumentCount' => '1+'
224
'AVERAGEIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
225
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
226
'argumentCount' => '2,3'
228
'AVERAGEIFS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
229
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
230
'argumentCount' => '3+'
232
'BAHTTEXT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
233
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
234
'argumentCount' => '1'
236
'BESSELI' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
237
'functionCall' => 'PHPExcel_Calculation_Functions::BESSELI',
238
'argumentCount' => '2'
240
'BESSELJ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
241
'functionCall' => 'PHPExcel_Calculation_Functions::BESSELJ',
242
'argumentCount' => '2'
244
'BESSELK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
245
'functionCall' => 'PHPExcel_Calculation_Functions::BESSELK',
246
'argumentCount' => '2'
248
'BESSELY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
249
'functionCall' => 'PHPExcel_Calculation_Functions::BESSELY',
250
'argumentCount' => '2'
252
'BETADIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
253
'functionCall' => 'PHPExcel_Calculation_Functions::BETADIST',
254
'argumentCount' => '3-5'
256
'BETAINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
257
'functionCall' => 'PHPExcel_Calculation_Functions::BETAINV',
258
'argumentCount' => '3-5'
260
'BIN2DEC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
261
'functionCall' => 'PHPExcel_Calculation_Functions::BINTODEC',
262
'argumentCount' => '1'
264
'BIN2HEX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
265
'functionCall' => 'PHPExcel_Calculation_Functions::BINTOHEX',
266
'argumentCount' => '1,2'
268
'BIN2OCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
269
'functionCall' => 'PHPExcel_Calculation_Functions::BINTOOCT',
270
'argumentCount' => '1,2'
272
'BINOMDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
273
'functionCall' => 'PHPExcel_Calculation_Functions::BINOMDIST',
274
'argumentCount' => '4'
276
'CEILING' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
277
'functionCall' => 'PHPExcel_Calculation_Functions::CEILING',
278
'argumentCount' => '2'
280
'CELL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
281
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
282
'argumentCount' => '1,2'
284
'CHAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
285
'functionCall' => 'PHPExcel_Calculation_Functions::CHARACTER',
286
'argumentCount' => '1'
288
'CHIDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
289
'functionCall' => 'PHPExcel_Calculation_Functions::CHIDIST',
290
'argumentCount' => '2'
292
'CHIINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
293
'functionCall' => 'PHPExcel_Calculation_Functions::CHIINV',
294
'argumentCount' => '2'
296
'CHITEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
297
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
298
'argumentCount' => '2'
300
'CHOOSE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
301
'functionCall' => 'PHPExcel_Calculation_Functions::CHOOSE',
302
'argumentCount' => '2+'
304
'CLEAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
305
'functionCall' => 'PHPExcel_Calculation_Functions::TRIMNONPRINTABLE',
306
'argumentCount' => '1'
308
'CODE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
309
'functionCall' => 'PHPExcel_Calculation_Functions::ASCIICODE',
310
'argumentCount' => '1'
312
'COLUMN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
313
'functionCall' => 'PHPExcel_Calculation_Functions::COLUMN',
314
'argumentCount' => '-1'
316
'COLUMNS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
317
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
318
'argumentCount' => '1'
320
'COMBIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
321
'functionCall' => 'PHPExcel_Calculation_Functions::COMBIN',
322
'argumentCount' => '2'
324
'COMPLEX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
325
'functionCall' => 'PHPExcel_Calculation_Functions::COMPLEX',
326
'argumentCount' => '2,3'
328
'CONCATENATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
329
'functionCall' => 'PHPExcel_Calculation_Functions::CONCATENATE',
330
'argumentCount' => '1+'
332
'CONFIDENCE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
333
'functionCall' => 'PHPExcel_Calculation_Functions::CONFIDENCE',
334
'argumentCount' => '3'
336
'CONVERT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
337
'functionCall' => 'PHPExcel_Calculation_Functions::CONVERTUOM',
338
'argumentCount' => '3'
340
'CORREL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
341
'functionCall' => 'PHPExcel_Calculation_Functions::CORREL',
342
'argumentCount' => '2'
344
'COS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
345
'functionCall' => 'cos',
346
'argumentCount' => '1'
348
'COSH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
349
'functionCall' => 'cosh',
350
'argumentCount' => '1'
352
'COUNT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
353
'functionCall' => 'PHPExcel_Calculation_Functions::COUNT',
354
'argumentCount' => '1+'
356
'COUNTA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
357
'functionCall' => 'PHPExcel_Calculation_Functions::COUNTA',
358
'argumentCount' => '1+'
360
'COUNTBLANK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
361
'functionCall' => 'PHPExcel_Calculation_Functions::COUNTBLANK',
362
'argumentCount' => '1'
364
'COUNTIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
365
'functionCall' => 'PHPExcel_Calculation_Functions::COUNTIF',
366
'argumentCount' => '2'
368
'COUNTIFS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
369
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
370
'argumentCount' => '2'
372
'COUPDAYBS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
373
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
374
'argumentCount' => '3,4'
376
'COUPDAYS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
377
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
378
'argumentCount' => '3,4'
380
'COUPDAYSNC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
381
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
382
'argumentCount' => '3,4'
384
'COUPNCD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
385
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
386
'argumentCount' => '3,4'
388
'COUPNUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
389
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
390
'argumentCount' => '3,4'
392
'COUPPCD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
393
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
394
'argumentCount' => '3,4'
396
'COVAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
397
'functionCall' => 'PHPExcel_Calculation_Functions::COVAR',
398
'argumentCount' => '2'
400
'CRITBINOM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
401
'functionCall' => 'PHPExcel_Calculation_Functions::CRITBINOM',
402
'argumentCount' => '3'
404
'CUBEKPIMEMBER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_CUBE,
405
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
406
'argumentCount' => '?'
408
'CUBEMEMBER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_CUBE,
409
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
410
'argumentCount' => '?'
412
'CUBEMEMBERPROPERTY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_CUBE,
413
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
414
'argumentCount' => '?'
416
'CUBERANKEDMEMBER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_CUBE,
417
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
418
'argumentCount' => '?'
420
'CUBESET' => array('category' => PHPExcel_Calculation_Function::CATEGORY_CUBE,
421
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
422
'argumentCount' => '?'
424
'CUBESETCOUNT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_CUBE,
425
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
426
'argumentCount' => '?'
428
'CUBEVALUE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_CUBE,
429
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
430
'argumentCount' => '?'
432
'CUMIPMT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
433
'functionCall' => 'PHPExcel_Calculation_Functions::CUMIPMT',
434
'argumentCount' => '6'
436
'CUMPRINC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
437
'functionCall' => 'PHPExcel_Calculation_Functions::CUMPRINC',
438
'argumentCount' => '6'
440
'DATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
441
'functionCall' => 'PHPExcel_Calculation_Functions::DATE',
442
'argumentCount' => '3'
444
'DATEDIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
445
'functionCall' => 'PHPExcel_Calculation_Functions::DATEDIF',
446
'argumentCount' => '3'
448
'DATEVALUE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
449
'functionCall' => 'PHPExcel_Calculation_Functions::DATEVALUE',
450
'argumentCount' => '1'
452
'DAVERAGE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE,
453
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
454
'argumentCount' => '?'
456
'DAY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
457
'functionCall' => 'PHPExcel_Calculation_Functions::DAYOFMONTH',
458
'argumentCount' => '1'
460
'DAYS360' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
461
'functionCall' => 'PHPExcel_Calculation_Functions::DAYS360',
462
'argumentCount' => '2,3'
464
'DB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
465
'functionCall' => 'PHPExcel_Calculation_Functions::DB',
466
'argumentCount' => '4,5'
468
'DCOUNT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE,
469
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
470
'argumentCount' => '?'
472
'DCOUNTA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE,
473
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
474
'argumentCount' => '?'
476
'DDB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
477
'functionCall' => 'PHPExcel_Calculation_Functions::DDB',
478
'argumentCount' => '4,5'
480
'DEC2BIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
481
'functionCall' => 'PHPExcel_Calculation_Functions::DECTOBIN',
482
'argumentCount' => '1,2'
484
'DEC2HEX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
485
'functionCall' => 'PHPExcel_Calculation_Functions::DECTOHEX',
486
'argumentCount' => '1,2'
488
'DEC2OCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
489
'functionCall' => 'PHPExcel_Calculation_Functions::DECTOOCT',
490
'argumentCount' => '1,2'
492
'DEGREES' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
493
'functionCall' => 'rad2deg',
494
'argumentCount' => '1'
496
'DELTA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
497
'functionCall' => 'PHPExcel_Calculation_Functions::DELTA',
498
'argumentCount' => '1,2'
500
'DEVSQ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
501
'functionCall' => 'PHPExcel_Calculation_Functions::DEVSQ',
502
'argumentCount' => '1+'
504
'DGET' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE,
505
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
506
'argumentCount' => '?'
508
'DISC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
509
'functionCall' => 'PHPExcel_Calculation_Functions::DISC',
510
'argumentCount' => '4,5'
512
'DMAX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE,
513
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
514
'argumentCount' => '?'
516
'DMIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE,
517
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
518
'argumentCount' => '?'
520
'DOLLAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
521
'functionCall' => 'PHPExcel_Calculation_Functions::DOLLAR',
522
'argumentCount' => '1,2'
524
'DOLLARDE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
525
'functionCall' => 'PHPExcel_Calculation_Functions::DOLLARDE',
526
'argumentCount' => '2'
528
'DOLLARFR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
529
'functionCall' => 'PHPExcel_Calculation_Functions::DOLLARFR',
530
'argumentCount' => '2'
532
'DPRODUCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE,
533
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
534
'argumentCount' => '?'
536
'DSTDEV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE,
537
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
538
'argumentCount' => '?'
540
'DSTDEVP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE,
541
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
542
'argumentCount' => '?'
544
'DSUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE,
545
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
546
'argumentCount' => '?'
548
'DURATION' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
549
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
550
'argumentCount' => '5,6'
552
'DVAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE,
553
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
554
'argumentCount' => '?'
556
'DVARP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE,
557
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
558
'argumentCount' => '?'
560
'EDATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
561
'functionCall' => 'PHPExcel_Calculation_Functions::EDATE',
562
'argumentCount' => '2'
564
'EFFECT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
565
'functionCall' => 'PHPExcel_Calculation_Functions::EFFECT',
566
'argumentCount' => '2'
568
'EOMONTH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
569
'functionCall' => 'PHPExcel_Calculation_Functions::EOMONTH',
570
'argumentCount' => '2'
572
'ERF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
573
'functionCall' => 'PHPExcel_Calculation_Functions::ERF',
574
'argumentCount' => '1,2'
576
'ERFC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
577
'functionCall' => 'PHPExcel_Calculation_Functions::ERFC',
578
'argumentCount' => '1'
580
'ERROR.TYPE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
581
'functionCall' => 'PHPExcel_Calculation_Functions::ERROR_TYPE',
582
'argumentCount' => '1'
584
'EVEN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
585
'functionCall' => 'PHPExcel_Calculation_Functions::EVEN',
586
'argumentCount' => '1'
588
'EXACT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
589
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
590
'argumentCount' => '2'
592
'EXP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
593
'functionCall' => 'exp',
594
'argumentCount' => '1'
596
'EXPONDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
597
'functionCall' => 'PHPExcel_Calculation_Functions::EXPONDIST',
598
'argumentCount' => '3'
600
'FACT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
601
'functionCall' => 'PHPExcel_Calculation_Functions::FACT',
602
'argumentCount' => '1'
604
'FACTDOUBLE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
605
'functionCall' => 'PHPExcel_Calculation_Functions::FACTDOUBLE',
606
'argumentCount' => '1'
608
'FALSE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL,
609
'functionCall' => 'PHPExcel_Calculation_Functions::LOGICAL_FALSE',
610
'argumentCount' => '0'
612
'FDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
613
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
614
'argumentCount' => '3'
616
'FIND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
617
'functionCall' => 'PHPExcel_Calculation_Functions::SEARCHSENSITIVE',
618
'argumentCount' => '2,3'
620
'FINDB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
621
'functionCall' => 'PHPExcel_Calculation_Functions::SEARCHSENSITIVE',
622
'argumentCount' => '2,3'
624
'FINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
625
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
626
'argumentCount' => '3'
628
'FISHER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
629
'functionCall' => 'PHPExcel_Calculation_Functions::FISHER',
630
'argumentCount' => '1'
632
'FISHERINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
633
'functionCall' => 'PHPExcel_Calculation_Functions::FISHERINV',
634
'argumentCount' => '1'
636
'FIXED' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
637
'functionCall' => 'PHPExcel_Calculation_Functions::FIXEDFORMAT',
638
'argumentCount' => '1-3'
640
'FLOOR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
641
'functionCall' => 'PHPExcel_Calculation_Functions::FLOOR',
642
'argumentCount' => '2'
644
'FORECAST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
645
'functionCall' => 'PHPExcel_Calculation_Functions::FORECAST',
646
'argumentCount' => '3'
648
'FREQUENCY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
649
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
650
'argumentCount' => '2'
652
'FTEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
653
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
654
'argumentCount' => '2'
656
'FV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
657
'functionCall' => 'PHPExcel_Calculation_Functions::FV',
658
'argumentCount' => '3-5'
660
'FVSCHEDULE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
661
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
662
'argumentCount' => '2'
664
'GAMMADIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
665
'functionCall' => 'PHPExcel_Calculation_Functions::GAMMADIST',
666
'argumentCount' => '4'
668
'GAMMAINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
669
'functionCall' => 'PHPExcel_Calculation_Functions::GAMMAINV',
670
'argumentCount' => '3'
672
'GAMMALN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
673
'functionCall' => 'PHPExcel_Calculation_Functions::GAMMALN',
674
'argumentCount' => '1'
676
'GCD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
677
'functionCall' => 'PHPExcel_Calculation_Functions::GCD',
678
'argumentCount' => '1+'
680
'GEOMEAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
681
'functionCall' => 'PHPExcel_Calculation_Functions::GEOMEAN',
682
'argumentCount' => '1+'
684
'GESTEP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
685
'functionCall' => 'PHPExcel_Calculation_Functions::GESTEP',
686
'argumentCount' => '1,2'
688
'GETPIVOTDATA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
689
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
690
'argumentCount' => '2+'
692
'GROWTH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
693
'functionCall' => 'PHPExcel_Calculation_Functions::GROWTH',
694
'argumentCount' => '1-4'
696
'HARMEAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
697
'functionCall' => 'PHPExcel_Calculation_Functions::HARMEAN',
698
'argumentCount' => '1+'
700
'HEX2BIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
701
'functionCall' => 'PHPExcel_Calculation_Functions::HEXTOBIN',
702
'argumentCount' => '1,2'
704
'HEX2DEC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
705
'functionCall' => 'PHPExcel_Calculation_Functions::HEXTODEC',
706
'argumentCount' => '1'
708
'HEX2OCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
709
'functionCall' => 'PHPExcel_Calculation_Functions::HEXTOOCT',
710
'argumentCount' => '1,2'
712
'HLOOKUP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
713
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
714
'argumentCount' => '3,4'
716
'HOUR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
717
'functionCall' => 'PHPExcel_Calculation_Functions::HOUROFDAY',
718
'argumentCount' => '1'
720
'HYPERLINK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
721
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
722
'argumentCount' => '1,2'
724
'HYPGEOMDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
725
'functionCall' => 'PHPExcel_Calculation_Functions::HYPGEOMDIST',
726
'argumentCount' => '4'
728
'IF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL,
729
'functionCall' => 'PHPExcel_Calculation_Functions::STATEMENT_IF',
730
'argumentCount' => '1-3'
732
'IFERROR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL,
733
'functionCall' => 'PHPExcel_Calculation_Functions::STATEMENT_IFERROR',
734
'argumentCount' => '1'
736
'IMABS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
737
'functionCall' => 'PHPExcel_Calculation_Functions::IMABS',
738
'argumentCount' => '1'
740
'IMAGINARY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
741
'functionCall' => 'PHPExcel_Calculation_Functions::IMAGINARY',
742
'argumentCount' => '1'
744
'IMARGUMENT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
745
'functionCall' => 'PHPExcel_Calculation_Functions::IMARGUMENT',
746
'argumentCount' => '1'
748
'IMCONJUGATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
749
'functionCall' => 'PHPExcel_Calculation_Functions::IMCONJUGATE',
750
'argumentCount' => '1'
752
'IMCOS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
753
'functionCall' => 'PHPExcel_Calculation_Functions::IMCOS',
754
'argumentCount' => '1'
756
'IMDIV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
757
'functionCall' => 'PHPExcel_Calculation_Functions::IMDIV',
758
'argumentCount' => '2'
760
'IMEXP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
761
'functionCall' => 'PHPExcel_Calculation_Functions::IMEXP',
762
'argumentCount' => '1'
764
'IMLN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
765
'functionCall' => 'PHPExcel_Calculation_Functions::IMLN',
766
'argumentCount' => '1'
768
'IMLOG10' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
769
'functionCall' => 'PHPExcel_Calculation_Functions::IMLOG10',
770
'argumentCount' => '1'
772
'IMLOG2' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
773
'functionCall' => 'PHPExcel_Calculation_Functions::IMLOG2',
774
'argumentCount' => '1'
776
'IMPOWER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
777
'functionCall' => 'PHPExcel_Calculation_Functions::IMPOWER',
778
'argumentCount' => '2'
780
'IMPRODUCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
781
'functionCall' => 'PHPExcel_Calculation_Functions::IMPRODUCT',
782
'argumentCount' => '1+'
784
'IMREAL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
785
'functionCall' => 'PHPExcel_Calculation_Functions::IMREAL',
786
'argumentCount' => '1'
788
'IMSIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
789
'functionCall' => 'PHPExcel_Calculation_Functions::IMSIN',
790
'argumentCount' => '1'
792
'IMSQRT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
793
'functionCall' => 'PHPExcel_Calculation_Functions::IMSQRT',
794
'argumentCount' => '1'
796
'IMSUB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
797
'functionCall' => 'PHPExcel_Calculation_Functions::IMSUB',
798
'argumentCount' => '2'
800
'IMSUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
801
'functionCall' => 'PHPExcel_Calculation_Functions::IMSUM',
802
'argumentCount' => '1+'
804
'INDEX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
805
'functionCall' => 'PHPExcel_Calculation_Functions::INDEX',
806
'argumentCount' => '1-4'
808
'INDIRECT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
809
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
810
'argumentCount' => '1,2'
812
'INFO' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
813
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
814
'argumentCount' => '1'
816
'INT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
817
'functionCall' => 'PHPExcel_Calculation_Functions::INTVALUE',
818
'argumentCount' => '1'
820
'INTERCEPT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
821
'functionCall' => 'PHPExcel_Calculation_Functions::INTERCEPT',
822
'argumentCount' => '2'
824
'INTRATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
825
'functionCall' => 'PHPExcel_Calculation_Functions::INTRATE',
826
'argumentCount' => '4,5'
828
'IPMT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
829
'functionCall' => 'PHPExcel_Calculation_Functions::IPMT',
830
'argumentCount' => '4-6'
832
'IRR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
833
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
834
'argumentCount' => '1,2'
836
'ISBLANK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
837
'functionCall' => 'PHPExcel_Calculation_Functions::IS_BLANK',
838
'argumentCount' => '1'
840
'ISERR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
841
'functionCall' => 'PHPExcel_Calculation_Functions::IS_ERR',
842
'argumentCount' => '1'
844
'ISERROR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
845
'functionCall' => 'PHPExcel_Calculation_Functions::IS_ERROR',
846
'argumentCount' => '1'
848
'ISEVEN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
849
'functionCall' => 'PHPExcel_Calculation_Functions::IS_EVEN',
850
'argumentCount' => '1'
852
'ISLOGICAL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
853
'functionCall' => 'PHPExcel_Calculation_Functions::IS_LOGICAL',
854
'argumentCount' => '1'
856
'ISNA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
857
'functionCall' => 'PHPExcel_Calculation_Functions::IS_NA',
858
'argumentCount' => '1'
860
'ISNONTEXT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
861
'functionCall' => 'PHPExcel_Calculation_Functions::IS_NONTEXT',
862
'argumentCount' => '1'
864
'ISNUMBER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
865
'functionCall' => 'PHPExcel_Calculation_Functions::IS_NUMBER',
866
'argumentCount' => '1'
868
'ISODD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
869
'functionCall' => 'PHPExcel_Calculation_Functions::IS_ODD',
870
'argumentCount' => '1'
872
'ISPMT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
873
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
874
'argumentCount' => '4'
876
'ISREF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
877
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
878
'argumentCount' => '1'
880
'ISTEXT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
881
'functionCall' => 'PHPExcel_Calculation_Functions::IS_TEXT',
882
'argumentCount' => '1'
884
'JIS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
885
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
886
'argumentCount' => '1'
888
'KURT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
889
'functionCall' => 'PHPExcel_Calculation_Functions::KURT',
890
'argumentCount' => '1+'
892
'LARGE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
893
'functionCall' => 'PHPExcel_Calculation_Functions::LARGE',
894
'argumentCount' => '2'
896
'LCM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
897
'functionCall' => 'PHPExcel_Calculation_Functions::LCM',
898
'argumentCount' => '1+'
900
'LEFT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
901
'functionCall' => 'PHPExcel_Calculation_Functions::LEFT',
902
'argumentCount' => '1,2'
904
'LEFTB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
905
'functionCall' => 'PHPExcel_Calculation_Functions::LEFT',
906
'argumentCount' => '1,2'
908
'LEN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
909
'functionCall' => 'PHPExcel_Calculation_Functions::STRINGLENGTH',
910
'argumentCount' => '1'
912
'LENB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
913
'functionCall' => 'PHPExcel_Calculation_Functions::STRINGLENGTH',
914
'argumentCount' => '1'
916
'LINEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
917
'functionCall' => 'PHPExcel_Calculation_Functions::LINEST',
918
'argumentCount' => '1-4'
920
'LN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
921
'functionCall' => 'log',
922
'argumentCount' => '1'
924
'LOG' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
925
'functionCall' => 'PHPExcel_Calculation_Functions::LOG_BASE',
926
'argumentCount' => '1,2'
928
'LOG10' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
929
'functionCall' => 'log10',
930
'argumentCount' => '1'
932
'LOGEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
933
'functionCall' => 'PHPExcel_Calculation_Functions::LOGEST',
934
'argumentCount' => '1-4'
936
'LOGINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
937
'functionCall' => 'PHPExcel_Calculation_Functions::LOGINV',
938
'argumentCount' => '3'
940
'LOGNORMDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
941
'functionCall' => 'PHPExcel_Calculation_Functions::LOGNORMDIST',
942
'argumentCount' => '3'
944
'LOOKUP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
945
'functionCall' => 'PHPExcel_Calculation_Functions::LOOKUP',
946
'argumentCount' => '2,3'
948
'LOWER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
949
'functionCall' => 'PHPExcel_Calculation_Functions::LOWERCASE',
950
'argumentCount' => '1'
952
'MATCH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
953
'functionCall' => 'PHPExcel_Calculation_Functions::MATCH',
954
'argumentCount' => '2,3'
956
'MAX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
957
'functionCall' => 'PHPExcel_Calculation_Functions::MAX',
958
'argumentCount' => '1+'
960
'MAXA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
961
'functionCall' => 'PHPExcel_Calculation_Functions::MAXA',
962
'argumentCount' => '1+'
964
'MDETERM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
965
'functionCall' => 'PHPExcel_Calculation_Functions::MDETERM',
966
'argumentCount' => '1'
968
'MDURATION' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
969
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
970
'argumentCount' => '5,6'
972
'MEDIAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
973
'functionCall' => 'PHPExcel_Calculation_Functions::MEDIAN',
974
'argumentCount' => '1+'
976
'MID' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
977
'functionCall' => 'PHPExcel_Calculation_Functions::MID',
978
'argumentCount' => '3'
980
'MIDB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
981
'functionCall' => 'PHPExcel_Calculation_Functions::MID',
982
'argumentCount' => '3'
984
'MIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
985
'functionCall' => 'PHPExcel_Calculation_Functions::MIN',
986
'argumentCount' => '1+'
988
'MINA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
989
'functionCall' => 'PHPExcel_Calculation_Functions::MINA',
990
'argumentCount' => '1+'
992
'MINUTE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
993
'functionCall' => 'PHPExcel_Calculation_Functions::MINUTEOFHOUR',
994
'argumentCount' => '1'
996
'MINVERSE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
997
'functionCall' => 'PHPExcel_Calculation_Functions::MINVERSE',
998
'argumentCount' => '1'
1000
'MIRR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1001
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1002
'argumentCount' => '3'
1004
'MMULT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1005
'functionCall' => 'PHPExcel_Calculation_Functions::MMULT',
1006
'argumentCount' => '2'
1008
'MOD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1009
'functionCall' => 'PHPExcel_Calculation_Functions::MOD',
1010
'argumentCount' => '2'
1012
'MODE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1013
'functionCall' => 'PHPExcel_Calculation_Functions::MODE',
1014
'argumentCount' => '1+'
1016
'MONTH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1017
'functionCall' => 'PHPExcel_Calculation_Functions::MONTHOFYEAR',
1018
'argumentCount' => '1'
1020
'MROUND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1021
'functionCall' => 'PHPExcel_Calculation_Functions::MROUND',
1022
'argumentCount' => '2'
1024
'MULTINOMIAL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1025
'functionCall' => 'PHPExcel_Calculation_Functions::MULTINOMIAL',
1026
'argumentCount' => '1+'
1028
'N' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
1029
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1030
'argumentCount' => '1'
1032
'NA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
1033
'functionCall' => 'PHPExcel_Calculation_Functions::NA',
1034
'argumentCount' => '0'
1036
'NEGBINOMDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1037
'functionCall' => 'PHPExcel_Calculation_Functions::NEGBINOMDIST',
1038
'argumentCount' => '3'
1040
'NETWORKDAYS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1041
'functionCall' => 'PHPExcel_Calculation_Functions::NETWORKDAYS',
1042
'argumentCount' => '2+'
1044
'NOMINAL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1045
'functionCall' => 'PHPExcel_Calculation_Functions::NOMINAL',
1046
'argumentCount' => '2'
1048
'NORMDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1049
'functionCall' => 'PHPExcel_Calculation_Functions::NORMDIST',
1050
'argumentCount' => '4'
1052
'NORMINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1053
'functionCall' => 'PHPExcel_Calculation_Functions::NORMINV',
1054
'argumentCount' => '3'
1056
'NORMSDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1057
'functionCall' => 'PHPExcel_Calculation_Functions::NORMSDIST',
1058
'argumentCount' => '1'
1060
'NORMSINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1061
'functionCall' => 'PHPExcel_Calculation_Functions::NORMSINV',
1062
'argumentCount' => '1'
1064
'NOT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL,
1065
'functionCall' => 'PHPExcel_Calculation_Functions::LOGICAL_NOT',
1066
'argumentCount' => '1'
1068
'NOW' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1069
'functionCall' => 'PHPExcel_Calculation_Functions::DATETIMENOW',
1070
'argumentCount' => '0'
1072
'NPER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1073
'functionCall' => 'PHPExcel_Calculation_Functions::NPER',
1074
'argumentCount' => '3-5'
1076
'NPV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1077
'functionCall' => 'PHPExcel_Calculation_Functions::NPV',
1078
'argumentCount' => '2+'
1080
'OCT2BIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
1081
'functionCall' => 'PHPExcel_Calculation_Functions::OCTTOBIN',
1082
'argumentCount' => '1,2'
1084
'OCT2DEC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
1085
'functionCall' => 'PHPExcel_Calculation_Functions::OCTTODEC',
1086
'argumentCount' => '1'
1088
'OCT2HEX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING,
1089
'functionCall' => 'PHPExcel_Calculation_Functions::OCTTOHEX',
1090
'argumentCount' => '1,2'
1092
'ODD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1093
'functionCall' => 'PHPExcel_Calculation_Functions::ODD',
1094
'argumentCount' => '1'
1096
'ODDFPRICE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1097
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1098
'argumentCount' => '8,9'
1100
'ODDFYIELD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1101
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1102
'argumentCount' => '8,9'
1104
'ODDLPRICE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1105
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1106
'argumentCount' => '7,8'
1108
'ODDLYIELD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1109
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1110
'argumentCount' => '7,8'
1112
'OFFSET' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
1113
'functionCall' => 'PHPExcel_Calculation_Functions::OFFSET',
1114
'argumentCount' => '3,5'
1116
'OR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL,
1117
'functionCall' => 'PHPExcel_Calculation_Functions::LOGICAL_OR',
1118
'argumentCount' => '1+'
1120
'PEARSON' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1121
'functionCall' => 'PHPExcel_Calculation_Functions::CORREL',
1122
'argumentCount' => '2'
1124
'PERCENTILE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1125
'functionCall' => 'PHPExcel_Calculation_Functions::PERCENTILE',
1126
'argumentCount' => '2'
1128
'PERCENTRANK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1129
'functionCall' => 'PHPExcel_Calculation_Functions::PERCENTRANK',
1130
'argumentCount' => '2,3'
1132
'PERMUT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1133
'functionCall' => 'PHPExcel_Calculation_Functions::PERMUT',
1134
'argumentCount' => '2'
1136
'PHONETIC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1137
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1138
'argumentCount' => '1'
1140
'PI' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1141
'functionCall' => 'pi',
1142
'argumentCount' => '0'
1144
'PMT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1145
'functionCall' => 'PHPExcel_Calculation_Functions::PMT',
1146
'argumentCount' => '3-5'
1148
'POISSON' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1149
'functionCall' => 'PHPExcel_Calculation_Functions::POISSON',
1150
'argumentCount' => '3'
1152
'POWER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1153
'functionCall' => 'PHPExcel_Calculation_Functions::POWER',
1154
'argumentCount' => '2'
1156
'PPMT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1157
'functionCall' => 'PHPExcel_Calculation_Functions::PPMT',
1158
'argumentCount' => '4-6'
1160
'PRICE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1161
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1162
'argumentCount' => '6,7'
1164
'PRICEDISC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1165
'functionCall' => 'PHPExcel_Calculation_Functions::PRICEDISC',
1166
'argumentCount' => '4,5'
1168
'PRICEMAT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1169
'functionCall' => 'PHPExcel_Calculation_Functions::PRICEMAT',
1170
'argumentCount' => '5,6'
1172
'PROB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1173
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1174
'argumentCount' => '3,4'
1176
'PRODUCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1177
'functionCall' => 'PHPExcel_Calculation_Functions::PRODUCT',
1178
'argumentCount' => '1+'
1180
'PROPER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1181
'functionCall' => 'PHPExcel_Calculation_Functions::PROPERCASE',
1182
'argumentCount' => '1'
1184
'PV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1185
'functionCall' => 'PHPExcel_Calculation_Functions::PV',
1186
'argumentCount' => '3-5'
1188
'QUARTILE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1189
'functionCall' => 'PHPExcel_Calculation_Functions::QUARTILE',
1190
'argumentCount' => '2'
1192
'QUOTIENT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1193
'functionCall' => 'PHPExcel_Calculation_Functions::QUOTIENT',
1194
'argumentCount' => '2'
1196
'RADIANS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1197
'functionCall' => 'deg2rad',
1198
'argumentCount' => '1'
1200
'RAND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1201
'functionCall' => 'PHPExcel_Calculation_Functions::RAND',
1202
'argumentCount' => '0'
1204
'RANDBETWEEN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1205
'functionCall' => 'PHPExcel_Calculation_Functions::RAND',
1206
'argumentCount' => '2'
1208
'RANK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1209
'functionCall' => 'PHPExcel_Calculation_Functions::RANK',
1210
'argumentCount' => '2,3'
1212
'RATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1213
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1214
'argumentCount' => '3-6'
1216
'RECEIVED' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1217
'functionCall' => 'PHPExcel_Calculation_Functions::RECEIVED',
1218
'argumentCount' => '4-5'
1220
'REPLACE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1221
'functionCall' => 'PHPExcel_Calculation_Functions::REPLACE',
1222
'argumentCount' => '4'
1224
'REPLACEB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1225
'functionCall' => 'PHPExcel_Calculation_Functions::REPLACE',
1226
'argumentCount' => '4'
1228
'REPT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1229
'functionCall' => 'str_repeat',
1230
'argumentCount' => '2'
1232
'RIGHT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1233
'functionCall' => 'PHPExcel_Calculation_Functions::RIGHT',
1234
'argumentCount' => '1,2'
1236
'RIGHTB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1237
'functionCall' => 'PHPExcel_Calculation_Functions::RIGHT',
1238
'argumentCount' => '1,2'
1240
'ROMAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1241
'functionCall' => 'PHPExcel_Calculation_Functions::ROMAN',
1242
'argumentCount' => '1,2'
1244
'ROUND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1245
'functionCall' => 'round',
1246
'argumentCount' => '2'
1248
'ROUNDDOWN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1249
'functionCall' => 'PHPExcel_Calculation_Functions::ROUNDDOWN',
1250
'argumentCount' => '2'
1252
'ROUNDUP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1253
'functionCall' => 'PHPExcel_Calculation_Functions::ROUNDUP',
1254
'argumentCount' => '2'
1256
'ROW' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
1257
'functionCall' => 'PHPExcel_Calculation_Functions::ROW',
1258
'argumentCount' => '-1'
1260
'ROWS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
1261
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1262
'argumentCount' => '1'
1264
'RSQ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1265
'functionCall' => 'PHPExcel_Calculation_Functions::RSQ',
1266
'argumentCount' => '2'
1268
'RTD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
1269
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1270
'argumentCount' => '1+'
1272
'SEARCH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1273
'functionCall' => 'PHPExcel_Calculation_Functions::SEARCHINSENSITIVE',
1274
'argumentCount' => '2,3'
1276
'SEARCHB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1277
'functionCall' => 'PHPExcel_Calculation_Functions::SEARCHINSENSITIVE',
1278
'argumentCount' => '2,3'
1280
'SECOND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1281
'functionCall' => 'PHPExcel_Calculation_Functions::SECONDOFMINUTE',
1282
'argumentCount' => '1'
1284
'SERIESSUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1285
'functionCall' => 'PHPExcel_Calculation_Functions::SERIESSUM',
1286
'argumentCount' => '4'
1288
'SIGN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1289
'functionCall' => 'PHPExcel_Calculation_Functions::SIGN',
1290
'argumentCount' => '1'
1292
'SIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1293
'functionCall' => 'sin',
1294
'argumentCount' => '1'
1296
'SINH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1297
'functionCall' => 'sinh',
1298
'argumentCount' => '1'
1300
'SKEW' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1301
'functionCall' => 'PHPExcel_Calculation_Functions::SKEW',
1302
'argumentCount' => '1+'
1304
'SLN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1305
'functionCall' => 'PHPExcel_Calculation_Functions::SLN',
1306
'argumentCount' => '3'
1308
'SLOPE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1309
'functionCall' => 'PHPExcel_Calculation_Functions::SLOPE',
1310
'argumentCount' => '2'
1312
'SMALL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1313
'functionCall' => 'PHPExcel_Calculation_Functions::SMALL',
1314
'argumentCount' => '2'
1316
'SQRT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1317
'functionCall' => 'sqrt',
1318
'argumentCount' => '1'
1320
'SQRTPI' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1321
'functionCall' => 'PHPExcel_Calculation_Functions::SQRTPI',
1322
'argumentCount' => '1'
1324
'STANDARDIZE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1325
'functionCall' => 'PHPExcel_Calculation_Functions::STANDARDIZE',
1326
'argumentCount' => '3'
1328
'STDEV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1329
'functionCall' => 'PHPExcel_Calculation_Functions::STDEV',
1330
'argumentCount' => '1+'
1332
'STDEVA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1333
'functionCall' => 'PHPExcel_Calculation_Functions::STDEVA',
1334
'argumentCount' => '1+'
1336
'STDEVP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1337
'functionCall' => 'PHPExcel_Calculation_Functions::STDEVP',
1338
'argumentCount' => '1+'
1340
'STDEVPA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1341
'functionCall' => 'PHPExcel_Calculation_Functions::STDEVPA',
1342
'argumentCount' => '1+'
1344
'STEYX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1345
'functionCall' => 'PHPExcel_Calculation_Functions::STEYX',
1346
'argumentCount' => '2'
1348
'SUBSTITUTE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1349
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1350
'argumentCount' => '3,4'
1352
'SUBTOTAL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1353
'functionCall' => 'PHPExcel_Calculation_Functions::SUBTOTAL',
1354
'argumentCount' => '2+'
1356
'SUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1357
'functionCall' => 'PHPExcel_Calculation_Functions::SUM',
1358
'argumentCount' => '1+'
1360
'SUMIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1361
'functionCall' => 'PHPExcel_Calculation_Functions::SUMIF',
1362
'argumentCount' => '2,3'
1364
'SUMIFS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1365
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1366
'argumentCount' => '?'
1368
'SUMPRODUCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1369
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1370
'argumentCount' => '1+'
1372
'SUMSQ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1373
'functionCall' => 'PHPExcel_Calculation_Functions::SUMSQ',
1374
'argumentCount' => '1+'
1376
'SUMX2MY2' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1377
'functionCall' => 'PHPExcel_Calculation_Functions::SUMX2MY2',
1378
'argumentCount' => '2'
1380
'SUMX2PY2' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1381
'functionCall' => 'PHPExcel_Calculation_Functions::SUMX2PY2',
1382
'argumentCount' => '2'
1384
'SUMXMY2' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1385
'functionCall' => 'PHPExcel_Calculation_Functions::SUMXMY2',
1386
'argumentCount' => '2'
1388
'SYD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1389
'functionCall' => 'PHPExcel_Calculation_Functions::SYD',
1390
'argumentCount' => '4'
1392
'T' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1393
'functionCall' => 'PHPExcel_Calculation_Functions::RETURNSTRING',
1394
'argumentCount' => '1'
1396
'TAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1397
'functionCall' => 'tan',
1398
'argumentCount' => '1'
1400
'TANH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1401
'functionCall' => 'tanh',
1402
'argumentCount' => '1'
1404
'TBILLEQ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1405
'functionCall' => 'PHPExcel_Calculation_Functions::TBILLEQ',
1406
'argumentCount' => '3'
1408
'TBILLPRICE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1409
'functionCall' => 'PHPExcel_Calculation_Functions::TBILLPRICE',
1410
'argumentCount' => '3'
1412
'TBILLYIELD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1413
'functionCall' => 'PHPExcel_Calculation_Functions::TBILLYIELD',
1414
'argumentCount' => '3'
1416
'TDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1417
'functionCall' => 'PHPExcel_Calculation_Functions::TDIST',
1418
'argumentCount' => '3'
1420
'TEXT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1421
'functionCall' => 'PHPExcel_Calculation_Functions::TEXTFORMAT',
1422
'argumentCount' => '2'
1424
'TIME' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1425
'functionCall' => 'PHPExcel_Calculation_Functions::TIME',
1426
'argumentCount' => '3'
1428
'TIMEVALUE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1429
'functionCall' => 'PHPExcel_Calculation_Functions::TIMEVALUE',
1430
'argumentCount' => '1'
1432
'TINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1433
'functionCall' => 'PHPExcel_Calculation_Functions::TINV',
1434
'argumentCount' => '2'
1436
'TODAY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1437
'functionCall' => 'PHPExcel_Calculation_Functions::DATENOW',
1438
'argumentCount' => '0'
1440
'TRANSPOSE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
1441
'functionCall' => 'PHPExcel_Calculation_Functions::TRANSPOSE',
1442
'argumentCount' => '1'
1444
'TREND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1445
'functionCall' => 'PHPExcel_Calculation_Functions::TREND',
1446
'argumentCount' => '1-4'
1448
'TRIM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1449
'functionCall' => 'PHPExcel_Calculation_Functions::TRIMSPACES',
1450
'argumentCount' => '1'
1452
'TRIMMEAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1453
'functionCall' => 'PHPExcel_Calculation_Functions::TRIMMEAN',
1454
'argumentCount' => '2'
1456
'TRUE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL,
1457
'functionCall' => 'PHPExcel_Calculation_Functions::LOGICAL_TRUE',
1458
'argumentCount' => '0'
1460
'TRUNC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG,
1461
'functionCall' => 'PHPExcel_Calculation_Functions::TRUNC',
1462
'argumentCount' => '1,2'
1464
'TTEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1465
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1466
'argumentCount' => '4'
1468
'TYPE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
1469
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1470
'argumentCount' => '1'
1472
'UPPER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1473
'functionCall' => 'PHPExcel_Calculation_Functions::UPPERCASE',
1474
'argumentCount' => '1'
1476
'USDOLLAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1477
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1478
'argumentCount' => '2'
1480
'VALUE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA,
1481
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1482
'argumentCount' => '1'
1484
'VAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1485
'functionCall' => 'PHPExcel_Calculation_Functions::VARFunc',
1486
'argumentCount' => '1+'
1488
'VARA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1489
'functionCall' => 'PHPExcel_Calculation_Functions::VARA',
1490
'argumentCount' => '1+'
1492
'VARP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1493
'functionCall' => 'PHPExcel_Calculation_Functions::VARP',
1494
'argumentCount' => '1+'
1496
'VARPA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1497
'functionCall' => 'PHPExcel_Calculation_Functions::VARPA',
1498
'argumentCount' => '1+'
1500
'VDB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1501
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1502
'argumentCount' => '5-7'
1504
'VERSION' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
1505
'functionCall' => 'PHPExcel_Calculation_Functions::VERSION',
1506
'argumentCount' => '0'
1508
'VLOOKUP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
1509
'functionCall' => 'PHPExcel_Calculation_Functions::VLOOKUP',
1510
'argumentCount' => '3,4'
1512
'WEEKDAY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1513
'functionCall' => 'PHPExcel_Calculation_Functions::DAYOFWEEK',
1514
'argumentCount' => '1,2'
1516
'WEEKNUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1517
'functionCall' => 'PHPExcel_Calculation_Functions::WEEKOFYEAR',
1518
'argumentCount' => '1,2'
1520
'WEIBULL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1521
'functionCall' => 'PHPExcel_Calculation_Functions::WEIBULL',
1522
'argumentCount' => '4'
1524
'WORKDAY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1525
'functionCall' => 'PHPExcel_Calculation_Functions::WORKDAY',
1526
'argumentCount' => '2+'
1528
'XIRR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1529
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1530
'argumentCount' => '2,3'
1532
'XNPV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1533
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1534
'argumentCount' => '3'
1536
'YEAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1537
'functionCall' => 'PHPExcel_Calculation_Functions::YEAR',
1538
'argumentCount' => '1'
1540
'YEARFRAC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME,
1541
'functionCall' => 'PHPExcel_Calculation_Functions::YEARFRAC',
1542
'argumentCount' => '2,3'
1544
'YIELD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1545
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1546
'argumentCount' => '6,7'
1548
'YIELDDISC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1549
'functionCall' => 'PHPExcel_Calculation_Functions::YIELDDISC',
1550
'argumentCount' => '4,5'
1552
'YIELDMAT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL,
1553
'functionCall' => 'PHPExcel_Calculation_Functions::YIELDMAT',
1554
'argumentCount' => '5,6'
1556
'ZTEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
1557
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
1558
'argumentCount' => '?'
1563
// Internal functions used for special control purposes
1564
private $_controlFunctions = array(
1565
'MKMATRIX' => array('argumentCount' => '*',
1566
'functionCall' => array('self','_mkMatrix')
1574
* Get an instance of this class
1577
* @return PHPExcel_Calculation
1579
public static function getInstance() {
1580
if (!isset(self::$_instance) || is_null(self::$_instance)) {
1581
self::$_instance = new PHPExcel_Calculation();
1584
return self::$_instance;
1585
} // function getInstance()
1589
* __clone implementation. Cloning should not be allowed in a Singleton!
1594
public final function __clone() {
1595
throw new Exception ( 'Cloning a Singleton is not allowed!' );
1596
} // function __clone()
1600
* Set the Array Return Type (Array or Value of first element in the array)
1603
* @param string $returnType Array return type
1604
* @return boolean Success or failure
1606
public static function setArrayReturnType($returnType) {
1607
if (($returnType == self::RETURN_ARRAY_AS_VALUE) ||
1608
($returnType == self::RETURN_ARRAY_AS_ARRAY)) {
1609
self::$returnArrayAsType = $returnType;
1613
} // function setExcelCalendar()
1617
* Return the Array Return Type (Array or Value of first element in the array)
1620
* @return string $returnType Array return type
1622
public static function getArrayReturnType() {
1623
return self::$returnArrayAsType;
1624
} // function getExcelCalendar()
1628
* Is calculation caching enabled?
1633
public function getCalculationCacheEnabled() {
1634
return $this->_calculationCacheEnabled;
1635
} // function getCalculationCacheEnabled()
1639
* Enable/disable calculation cache
1642
* @param boolean $pValue
1644
public function setCalculationCacheEnabled($pValue = true) {
1645
$this->_calculationCacheEnabled = $pValue;
1646
$this->clearCalculationCache();
1647
} // function setCalculationCacheEnabled()
1651
* Enable calculation cache
1653
public function enableCalculationCache() {
1654
$this->setCalculationCacheEnabled(true);
1655
} // function enableCalculationCache()
1659
* Disable calculation cache
1661
public function disableCalculationCache() {
1662
$this->setCalculationCacheEnabled(false);
1663
} // function disableCalculationCache()
1667
* Clear calculation cache
1669
public function clearCalculationCache() {
1670
$this->_calculationCache = array();
1671
} // function clearCalculationCache()
1675
* Get calculation cache expiration time
1679
public function getCalculationCacheExpirationTime() {
1680
return $this->_calculationCacheExpirationTime;
1681
} // getCalculationCacheExpirationTime()
1685
* Set calculation cache expiration time
1687
* @param float $pValue
1689
public function setCalculationCacheExpirationTime($pValue = 0.01) {
1690
$this->_calculationCacheExpirationTime = $pValue;
1691
} // function setCalculationCacheExpirationTime()
1697
* Wrap string values in quotes
1699
* @param mixed $value
1702
public static function _wrapResult($value) {
1703
if (is_string($value)) {
1704
// Error values cannot be "wrapped"
1705
if (preg_match('/^'.self::CALCULATION_REGEXP_ERROR.'$/i', $value, $match)) {
1706
// Return Excel errors "as is"
1709
// Return strings wrapped in quotes
1710
return '"'.$value.'"';
1711
// Convert numeric errors to NaN error
1712
} else if((is_float($value)) && ((is_nan($value)) || (is_infinite($value)))) {
1713
return PHPExcel_Calculation_Functions::NaN();
1717
} // function _wrapResult()
1721
* Remove quotes used as a wrapper to identify string values
1723
* @param mixed $value
1726
public static function _unwrapResult($value) {
1727
if (is_string($value)) {
1728
if ((strlen($value) > 0) && ($value{0} == '"') && (substr($value,-1) == '"')) {
1729
return substr($value,1,-1);
1731
// Convert numeric errors to NaN error
1732
} else if((is_float($value)) && ((is_nan($value)) || (is_infinite($value)))) {
1733
return PHPExcel_Calculation_Functions::NaN();
1736
} // function _unwrapResult()
1742
* Calculate cell value (using formula from a cell ID)
1743
* Retained for backward compatibility
1746
* @param PHPExcel_Cell $pCell Cell to calculate
1750
public function calculate(PHPExcel_Cell $pCell = null) {
1751
return $this->calculateCellValue($pCell);
1752
} // function calculate()
1756
* Calculate the value of a cell formula
1759
* @param PHPExcel_Cell $pCell Cell to calculate
1760
* @param Boolean $resetLog Flag indicating whether the debug log should be reset or not
1764
public function calculateCellValue(PHPExcel_Cell $pCell = null, $resetLog = true) {
1766
// Initialise the logging settings if requested
1767
$this->formulaError = null;
1768
$this->debugLog = array();
1769
$this->debugLogStack = array();
1772
// Read the formula from the cell
1773
if (is_null($pCell)) {
1776
$formula = $pCell->getValue();
1777
$cellID = $pCell->getCoordinate();
1779
// Execute the calculation for the cell formula
1780
return self::_unwrapResult($this->_calculateFormulaValue($formula, $cellID, $pCell));
1781
} // function calculateCellValue(
1785
* Validate and parse a formula string
1787
* @param string $formula Formula to parse
1791
public function parseFormula($formula) {
1792
// Basic validation that this is indeed a formula
1793
// We return an empty array if not
1794
$formula = trim($formula);
1795
if ($formula{0} != '=') return array();
1796
$formula = trim(substr($formula,1));
1797
$formulaLength = strlen($formula);
1798
if ($formulaLength < 1) return array();
1800
// Parse the formula and return the token stack
1801
return $this->_parseFormula($formula);
1802
} // function parseFormula()
1806
* Calculate the value of a formula
1808
* @param string $formula Formula to parse
1812
public function calculateFormula($formula, $cellID=null, PHPExcel_Cell $pCell = null) {
1813
// Initialise the logging settings
1814
$this->formulaError = null;
1815
$this->debugLog = array();
1816
$this->debugLogStack = array();
1818
// Disable calculation cacheing because it only applies to cell calculations, not straight formulae
1819
// But don't actually flush any cache
1820
$resetCache = $this->getCalculationCacheEnabled();
1821
$this->_calculationCacheEnabled = false;
1822
// Execute the calculation
1823
$result = self::_unwrapResult($this->_calculateFormulaValue($formula, $cellID, $pCell));
1824
// Reset calculation cacheing to its previous state
1825
$this->_calculationCacheEnabled = $resetCache;
1828
} // function calculateFormula()
1832
* Parse a cell formula and calculate its value
1834
* @param string $formula The formula to parse and calculate
1835
* @param string $cellID The ID (e.g. A3) of the cell that we are calculating
1836
* @param PHPExcel_Cell $pCell Cell to calculate
1840
public function _calculateFormulaValue($formula, $cellID=null, PHPExcel_Cell $pCell = null) {
1841
// echo '<b>'.$cellID.'</b><br />';
1844
// Basic validation that this is indeed a formula
1845
// We simply return the "cell value" (formula) if not
1846
$formula = trim($formula);
1847
if ($formula{0} != '=') return self::_wrapResult($formula);
1848
$formula = trim(substr($formula,1));
1849
$formulaLength = strlen($formula);
1850
if ($formulaLength < 1) return self::_wrapResult($formula);
1852
// Is calculation cacheing enabled?
1853
if (!is_null($cellID)) {
1854
if ($this->_calculationCacheEnabled) {
1855
// Is the value present in calculation cache?
1856
// echo 'Testing cache value<br />';
1857
if (isset($this->_calculationCache[$pCell->getParent()->getTitle()][$pCell->getCoordinate()])) {
1858
// echo 'Value is in cache<br />';
1859
$this->_writeDebug($cellID,'Testing cache value');
1860
// Is cache still valid?
1861
if ((time() + microtime()) - $this->_calculationCache[$pCell->getParent()->getTitle()][$pCell->getCoordinate()]['time'] < $this->_calculationCacheExpirationTime) {
1862
// echo 'Cache time is still valid<br />';
1863
$this->_writeDebug($cellID,'Retrieving value from cache');
1864
// Return the cached result
1865
$returnValue = $this->_calculationCache[$pCell->getParent()->getTitle()][$pCell->getCoordinate()]['data'];
1866
// echo 'Retrieving data value of '.$returnValue.' for '.$pCell->getCoordinate().' from cache<br />';
1867
if (is_array($returnValue)) {
1868
return array_shift(PHPExcel_Calculation_Functions::flattenArray($returnValue));
1870
return $returnValue;
1872
// echo 'Cache has expired<br />';
1873
$this->_writeDebug($cellID,'Cache value has expired');
1874
// Clear the cache if it's no longer valid
1875
unset($this->_calculationCache[$pCell->getParent()->getTitle()][$pCell->getCoordinate()]);
1881
$this->debugLogStack[] = $cellID;
1882
// Parse the formula onto the token stack and calculate the value
1883
$cellValue = $this->_processTokenStack($this->_parseFormula($formula), $cellID, $pCell);
1884
array_pop($this->debugLogStack);
1886
// Save to calculation cache
1887
if (!is_null($cellID)) {
1888
if ($this->_calculationCacheEnabled) {
1889
$this->_calculationCache[$pCell->getParent()->getTitle()][$pCell->getCoordinate()]['time'] = (time() + microtime());
1890
$this->_calculationCache[$pCell->getParent()->getTitle()][$pCell->getCoordinate()]['data'] = $cellValue;
1894
// Return the calculated value
1895
if (is_array($cellValue)) {
1896
$cellValue = array_shift(PHPExcel_Calculation_Functions::flattenArray($cellValue));
1900
} // function _calculateFormulaValue()
1904
* Ensure that paired matrix operands are both matrices and of the same size
1906
* @param mixed $operand1 First matrix operand
1907
* @param mixed $operand2 Second matrix operand
1909
private static function _checkMatrixOperands(&$operand1,&$operand2,$resize = 1) {
1910
// Examine each of the two operands, and turn them into an array if they aren't one already
1911
// Note that this function should only be called if one or both of the operand is already an array
1912
if (!is_array($operand1)) {
1913
list($matrixRows,$matrixColumns) = self::_getMatrixDimensions($operand2);
1914
$operand1 = array_fill(0,$matrixRows,array_fill(0,$matrixColumns,$operand1));
1916
} elseif (!is_array($operand2)) {
1917
list($matrixRows,$matrixColumns) = self::_getMatrixDimensions($operand1);
1918
$operand2 = array_fill(0,$matrixRows,array_fill(0,$matrixColumns,$operand2));
1922
// Given two matrices of (potentially) unequal size, convert the smaller in each dimension to match the larger
1924
self::_resizeMatricesExtend($operand1,$operand2);
1925
} elseif ($resize == 1) {
1926
self::_resizeMatricesShrink($operand1,$operand2);
1928
} // function _checkMatrixOperands()
1932
* Re-index a matrix with straight numeric keys starting from row 0, column 0
1934
* @param mixed $matrix matrix operand
1935
* @return array The re-indexed matrix
1937
private static function _reindexMatrixDimensions($matrix) {
1938
foreach($matrix as $rowKey => $rowValue) {
1939
$matrix[$rowKey] = array_values($rowValue);
1941
return array_values($matrix);
1942
} // function _getMatrixDimensions()
1946
* Read the dimensions of a matrix, and re-index it with straight numeric keys starting from row 0, column 0
1948
* @param mixed $matrix matrix operand
1949
* @return array An array comprising the number of rows, and number of columns
1951
private static function _getMatrixDimensions(&$matrix) {
1952
$matrixRows = count($matrix);
1954
foreach($matrix as $rowKey => $rowValue) {
1955
$colCount = count($rowValue);
1956
if ($colCount > $matrixColumns) {
1957
$matrixColumns = $colCount;
1959
$matrix[$rowKey] = array_values($rowValue);
1961
$matrix = array_values($matrix);
1962
return array($matrixRows,$matrixColumns);
1963
} // function _getMatrixDimensions()
1967
* Ensure that paired matrix operands are both matrices of the same size
1969
* @param mixed $matrix1 First matrix operand
1970
* @param mixed $matrix2 Second matrix operand
1972
private static function _resizeMatricesShrink(&$matrix1,&$matrix2) {
1973
list($matrix1Rows,$matrix1Columns) = self::_getMatrixDimensions($matrix1);
1974
list($matrix2Rows,$matrix2Columns) = self::_getMatrixDimensions($matrix2);
1976
if (($matrix2Columns < $matrix1Columns) || ($matrix2Rows < $matrix1Rows)) {
1977
if ($matrix2Columns < $matrix1Columns) {
1978
for ($i = 0; $i < $matrix1Rows; ++$i) {
1979
for ($j = $matrix2Columns; $j < $matrix1Columns; ++$j) {
1980
unset($matrix1[$i][$j]);
1984
if ($matrix2Rows < $matrix1Rows) {
1985
for ($i = $matrix2Rows; $i < $matrix1Rows; ++$i) {
1986
unset($matrix1[$i]);
1991
if (($matrix1Columns < $matrix2Columns) || ($matrix1Rows < $matrix2Rows)) {
1992
if ($matrix1Columns < $matrix2Columns) {
1993
for ($i = 0; $i < $matrix2Rows; ++$i) {
1994
for ($j = $matrix1Columns; $j < $matrix2Columns; ++$j) {
1995
unset($matrix2[$i][$j]);
1999
if ($matrix1Rows < $matrix2Rows) {
2000
for ($i = $matrix1Rows; $i < $matrix2Rows; ++$i) {
2001
unset($matrix2[$i]);
2005
} // function _resizeMatricesShrink()
2009
* Ensure that paired matrix operands are both matrices of the same size
2011
* @param mixed $matrix1 First matrix operand
2012
* @param mixed $matrix2 Second matrix operand
2014
private static function _resizeMatricesExtend(&$matrix1,&$matrix2) {
2015
list($matrix1Rows,$matrix1Columns) = self::_getMatrixDimensions($matrix1);
2016
list($matrix2Rows,$matrix2Columns) = self::_getMatrixDimensions($matrix2);
2018
if (($matrix2Columns < $matrix1Columns) || ($matrix2Rows < $matrix1Rows)) {
2019
if ($matrix2Columns < $matrix1Columns) {
2020
for ($i = 0; $i < $matrix2Rows; ++$i) {
2021
$x = $matrix2[$i][$matrix2Columns-1];
2022
for ($j = $matrix2Columns; $j < $matrix1Columns; ++$j) {
2023
$matrix2[$i][$j] = $x;
2027
if ($matrix2Rows < $matrix1Rows) {
2028
$x = $matrix2[$matrix2Rows-1];
2029
for ($i = 0; $i < $matrix1Rows; ++$i) {
2035
if (($matrix1Columns < $matrix2Columns) || ($matrix1Rows < $matrix2Rows)) {
2036
if ($matrix1Columns < $matrix2Columns) {
2037
for ($i = 0; $i < $matrix1Rows; ++$i) {
2038
$x = $matrix1[$i][$matrix1Columns-1];
2039
for ($j = $matrix1Columns; $j < $matrix2Columns; ++$j) {
2040
$matrix1[$i][$j] = $x;
2044
if ($matrix1Rows < $matrix2Rows) {
2045
$x = $matrix1[$matrix1Rows-1];
2046
for ($i = 0; $i < $matrix2Rows; ++$i) {
2051
} // function _resizeMatricesExtend()
2055
* Format details of an operand for display in the log (based on operand type)
2057
* @param mixed $value First matrix operand
2060
private static function _showValue($value) {
2061
if (is_array($value)) {
2064
foreach($value as $row) {
2065
if (is_array($row)) {
2066
if ($i > 0) { $retVal .= '; '; }
2068
foreach($row as $column) {
2069
if ($j > 0) { $retVal .= ', '; }
2074
if ($i > 0) { $retVal .= ', '; }
2079
return '{ '.$retVal.' }';
2080
} elseif(is_bool($value)) {
2081
return ($value) ? 'TRUE' : 'FALSE';
2085
} // function _showValue()
2089
* Format type and details of an operand for display in the log (based on operand type)
2091
* @param mixed $value First matrix operand
2094
private static function _showTypeDetails($value) {
2095
switch (gettype($value)) {
2098
$typeString = 'a floating point number';
2101
$typeString = 'an integer number';
2104
$typeString = 'a boolean';
2107
$typeString = 'a matrix';
2111
return 'an empty string';
2112
} elseif ($value{0} == '#') {
2113
return 'a '.$value.' error';
2115
$typeString = 'a string';
2119
return 'a null value';
2121
return $typeString.' with a value of '.self::_showValue($value);
2122
} // function _showTypeDetails()
2125
private static function _convertMatrixReferences($formula) {
2126
static $matrixReplaceFrom = array('{',';','}');
2127
static $matrixReplaceTo = array('MKMATRIX(MKMATRIX(','),MKMATRIX(','))');
2129
// Convert any Excel matrix references to the MKMATRIX() function
2130
if (strpos($formula,'{') !== false) {
2131
// Open and Closed counts used for trapping mismatched braces in the formula
2132
$openCount = $closeCount = 0;
2133
// If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators
2134
if (strpos($formula,'"') !== false) {
2135
// So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded
2137
$temp = explode('"',$formula);
2139
foreach($temp as &$value) {
2140
// Only count/replace in alternate array entries
2141
if (($i++ % 2) == 0) {
2142
$openCount += substr_count($value,'{');
2143
$closeCount += substr_count($value,'}');
2144
$value = str_replace($matrixReplaceFrom,$matrixReplaceTo,$value);
2148
// Then rebuild the formula string
2149
$formula = implode('"',$temp);
2151
// If there's no quoted strings, then we do a simple count/replace
2152
$openCount += substr_count($formula,'{');
2153
$closeCount += substr_count($formula,'}');
2154
$formula = str_replace($matrixReplaceFrom,$matrixReplaceTo,$formula);
2156
// Trap for mismatched braces and trigger an appropriate error
2157
if ($openCount < $closeCount) {
2158
if ($openCount > 0) {
2159
return $this->_raiseFormulaError("Formula Error: Mismatched matrix braces '}'");
2161
return $this->_raiseFormulaError("Formula Error: Unexpected '}' encountered");
2163
} elseif ($openCount > $closeCount) {
2164
if ($closeCount > 0) {
2165
return $this->_raiseFormulaError("Formula Error: Mismatched matrix braces '{'");
2167
return $this->_raiseFormulaError("Formula Error: Unexpected '{' encountered");
2173
} // function _convertMatrixReferences()
2176
private static function _mkMatrix() {
2177
return func_get_args();
2178
} // function _mkMatrix()
2181
// Convert infix to postfix notation
2182
private function _parseFormula($formula) {
2183
if (($formula = self::_convertMatrixReferences(trim($formula))) === false) {
2188
// These operators always work on two values
2189
// Array key is the operator, the value indicates whether this is a left or right associative operator
2190
$operatorAssociativity = array('^' => 0, // Exponentiation
2191
'*' => 0, '/' => 0, // Multiplication and Division
2192
'+' => 0, '-' => 0, // Addition and Subtraction
2193
'&' => 1, // Concatenation
2194
'>' => 0, '<' => 0, '=' => 0, '>=' => 0, '<=' => 0, '<>' => 0 // Comparison
2196
// Comparison (Boolean) Operators
2197
// These operators work on two values, but always return a boolean result
2198
$comparisonOperators = array('>', '<', '=', '>=', '<=', '<>');
2200
// Operator Precedence
2201
// This list includes all valid operators, whether binary (including boolean) or unary (such as %)
2202
// Array key is the operator, the value is its precedence
2203
$operatorPrecedence = array('_' => 6, // Negation
2204
'%' => 5, // Percentage
2205
'^' => 4, // Exponentiation
2206
'*' => 3, '/' => 3, // Multiplication and Division
2207
'+' => 2, '-' => 2, // Addition and Subtraction
2208
'&' => 1, // Concatenation
2209
'>' => 0, '<' => 0, '=' => 0, '>=' => 0, '<=' => 0, '<>' => 0 // Comparison
2212
$regexpMatchString = '/^('.self::CALCULATION_REGEXP_FUNCTION.
2213
'|'.self::CALCULATION_REGEXP_NUMBER.
2214
'|'.self::CALCULATION_REGEXP_STRING.
2215
'|'.self::CALCULATION_REGEXP_OPENBRACE.
2216
'|'.self::CALCULATION_REGEXP_CELLREF.
2217
'|'.self::CALCULATION_REGEXP_NAMEDRANGE.
2220
// Start with initialisation
2222
$stack = new PHPExcel_Token_Stack;
2224
$expectingOperator = false; // We use this test in syntax-checking the expression to determine when a
2225
// - is a negation or + is a positive operator rather than an operation
2226
$expectingOperand = false; // We use this test in syntax-checking the expression to determine whether an operand
2227
// should be null in a function call
2228
// The guts of the lexical parser
2229
// Loop through the formula extracting each operator and operand in turn
2231
// echo 'Assessing Expression <b>'.substr($formula, $index).'</b><br />';
2232
$opCharacter = $formula{$index}; // Get the first character of the value at the current index position
2233
// echo 'Initial character of expression block is '.$opCharacter.'<br />';
2234
if ((in_array($opCharacter, $comparisonOperators)) && (strlen($formula) > $index) && (in_array($formula{$index+1}, $comparisonOperators))) {
2235
$opCharacter .= $formula{++$index};
2236
// echo 'Initial character of expression block is comparison operator '.$opCharacter.'<br />';
2239
// Find out if we're currently at the beginning of a number, variable, cell reference, function, parenthesis or operand
2240
$isOperandOrFunction = preg_match($regexpMatchString, substr($formula, $index), $match);
2241
// echo '$isOperandOrFunction is '.(($isOperandOrFunction)?'True':'False').'<br />';
2243
if ($opCharacter == '-' && !$expectingOperator) { // Is it a negation instead of a minus?
2244
// echo 'Element is a Negation operator<br />';
2245
$stack->push('_'); // Put a negation on the stack
2246
++$index; // and drop the negation symbol
2247
} elseif ($opCharacter == '%' && $expectingOperator) {
2248
// echo 'Element is a Percentage operator<br />';
2249
$stack->push('%'); // Put a percentage on the stack
2251
} elseif ($opCharacter == '+' && !$expectingOperator) { // Positive (rather than plus) can be discarded?
2252
// echo 'Element is a Positive number, not Plus operator<br />';
2253
++$index; // Drop the redundant plus symbol
2254
} elseif (($opCharacter == '_') && (!$isOperandOrFunction)) { // We have to explicitly deny an underscore, because it's legal on
2255
return $this->_raiseFormulaError("Formula Error: Illegal character '_'"); // the stack but not in the input expression
2256
// Note that _ is a valid first character in named ranges
2257
// and this will need modifying soon when we start integrating
2258
// with PHPExcel proper
2260
} elseif ((in_array($opCharacter, $this->_operators) or $isOperandOrFunction) && $expectingOperator) { // Are we putting an operator on the stack?
2261
// echo 'Element with value '.$opCharacter.' is an Operator<br />';
2262
while($stack->count() > 0 &&
2263
($o2 = $stack->last()) &&
2264
in_array($o2, $this->_operators) &&
2265
($operatorAssociativity[$opCharacter] ? $operatorPrecedence[$opCharacter] < $operatorPrecedence[$o2] : $operatorPrecedence[$opCharacter] <= $operatorPrecedence[$o2])) {
2266
$output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output
2268
$stack->push($opCharacter); // Finally put our current operator onto the stack
2270
$expectingOperator = false;
2272
} elseif ($opCharacter == ')' && $expectingOperator) { // Are we expecting to close a parenthesis?
2273
// echo 'Element is a Closing bracket<br />';
2274
$expectingOperand = false;
2275
while (($o2 = $stack->pop()) != '(') { // Pop off the stack back to the last (
2276
if (is_null($o2)) return $this->_raiseFormulaError('Formula Error: Unexpected closing brace ")"');
2277
else $output[] = $o2;
2279
if (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $stack->last(2), $matches)) { // Did this parenthesis just close a function?
2280
$functionName = $matches[1]; // Get the function name
2281
// echo 'Closed Function is '.$functionName.'<br />';
2282
$argumentCount = $stack->pop(); // See how many arguments there were (argument count is the next value stored on the stack)
2283
// if ($argumentCount == 0) {
2284
// echo 'With no arguments<br />';
2285
// } elseif ($argumentCount == 1) {
2286
// echo 'With 1 argument<br />';
2288
// echo 'With '.$argumentCount.' arguments<br />';
2290
$output[] = $argumentCount; // Dump the argument count on the output
2291
$output[] = $stack->pop(); // Pop the function and push onto the output
2292
if (array_key_exists($functionName, $this->_controlFunctions)) {
2293
// echo 'Built-in function '.$functionName.'<br />';
2294
$expectedArgumentCount = $this->_controlFunctions[$functionName]['argumentCount'];
2295
$functionCall = $this->_controlFunctions[$functionName]['functionCall'];
2296
} elseif (array_key_exists($functionName, $this->_PHPExcelFunctions)) {
2297
// echo 'PHPExcel function '.$functionName.'<br />';
2298
$expectedArgumentCount = $this->_PHPExcelFunctions[$functionName]['argumentCount'];
2299
$functionCall = $this->_PHPExcelFunctions[$functionName]['functionCall'];
2300
} else { // did we somehow push a non-function on the stack? this should never happen
2301
return $this->_raiseFormulaError("Formula Error: Internal error, non-function on stack");
2303
// Check the argument count
2304
$argumentCountError = False;
2305
if (is_numeric($expectedArgumentCount)) {
2306
if ($expectedArgumentCount < 0) {
2307
// echo '$expectedArgumentCount is between 0 and '.abs($expectedArgumentCount).'<br />';
2308
if ($argumentCount > abs($expectedArgumentCount)) {
2309
$argumentCountError = True;
2310
$expectedArgumentCountString = 'no more than '.abs($expectedArgumentCount);
2313
// echo '$expectedArgumentCount is numeric '.$expectedArgumentCount.'<br />';
2314
if ($argumentCount != $expectedArgumentCount) {
2315
$argumentCountError = True;
2316
$expectedArgumentCountString = $expectedArgumentCount;
2319
} elseif ($expectedArgumentCount != '*') {
2320
$isOperandOrFunction = preg_match('/(\d*)([-+,])(\d*)/',$expectedArgumentCount,$argMatch);
2321
// print_r($argMatch);
2323
switch ($argMatch[2]) {
2325
if ($argumentCount < $argMatch[1]) {
2326
$argumentCountError = True;
2327
$expectedArgumentCountString = $argMatch[1].' or more ';
2331
if (($argumentCount < $argMatch[1]) || ($argumentCount > $argMatch[3])) {
2332
$argumentCountError = True;
2333
$expectedArgumentCountString = 'between '.$argMatch[1].' and '.$argMatch[3];
2337
if (($argumentCount != $argMatch[1]) && ($argumentCount != $argMatch[3])) {
2338
$argumentCountError = True;
2339
$expectedArgumentCountString = 'either '.$argMatch[1].' or '.$argMatch[3];
2344
if ($argumentCountError) {
2345
return $this->_raiseFormulaError("Formula Error: Wrong number of arguments for $functionName() function: $argumentCount given, ".$expectedArgumentCountString." expected");
2350
} elseif ($opCharacter == ',') { // Is this the comma separator for function arguments?
2351
// echo 'Element is a Function argument separator<br />';
2352
while (($o2 = $stack->pop()) != '(') {
2353
if (is_null($o2)) return $this->_raiseFormulaError("Formula Error: Unexpected ','");
2354
else $output[] = $o2; // pop the argument expression stuff and push onto the output
2356
// If we've a comma when we're expecting an operand, then what we actually have is a null operand;
2357
// so push a null onto the stack
2358
if (($expectingOperand) || (!$expectingOperator)) {
2359
$output[] = $this->_ExcelConstants['NULL'];
2361
// make sure there was a function
2362
if (!preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $stack->last(2), $matches))
2363
return $this->_raiseFormulaError("Formula Error: Unexpected ','");
2364
$stack->push($stack->pop()+1); // increment the argument count
2365
$stack->push('('); // put the ( back on, we'll need to pop back to it again
2366
$expectingOperator = false;
2367
$expectingOperand = true;
2370
} elseif ($opCharacter == '(' && !$expectingOperator) {
2371
// echo 'Element is an Opening Bracket<br />';
2375
} elseif ($isOperandOrFunction && !$expectingOperator) { // do we now have a function/variable/number?
2376
$expectingOperator = true;
2377
$expectingOperand = false;
2379
$length = strlen($val);
2380
// echo 'Element with value '.$val.' is an Operand, Variable, Constant, String, Number, Cell Reference or Function<br />';
2382
if (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $val, $matches)) {
2383
$val = preg_replace('/\s/','',$val);
2384
// echo 'Element '.$val.' is a Function<br />';
2385
if (array_key_exists(strtoupper($matches[1]), $this->_controlFunctions) || array_key_exists(strtoupper($matches[1]), $this->_PHPExcelFunctions)) { // it's a func
2386
$stack->push(strtoupper($val));
2387
$ax = preg_match('/^\s*(\s*\))/i', substr($formula, $index+$length), $amatch);
2390
$expectingOperator = true;
2393
$expectingOperator = false;
2396
} else { // it's a var w/ implicit multiplication
2400
} elseif (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $val, $matches)) {
2401
// echo 'Element '.$val.' is a Cell reference<br />';
2402
// Watch for this case-change when modifying to allow cell references in different worksheets...
2403
// Should only be applied to the actual cell column, not the worksheet name
2404
// $cellRef = strtoupper($val);
2405
// $output[] = $cellRef;
2407
// $expectingOperator = false;
2408
} else { // it's a variable, constant, string, number or boolean
2409
// echo 'Element is a Variable, Constant, String, Number or Boolean<br />';
2410
if ($opCharacter == '"') {
2411
// echo 'Element is a String<br />';
2412
$val = str_replace('""','"',$val);
2413
} elseif (is_numeric($val)) {
2414
// echo 'Element is a Number<br />';
2415
if ((strpos($val,'.') !== False) || (stripos($val,'e') !== False)) {
2416
// echo 'Casting '.$val.' to float<br />';
2417
$val = (float) $val;
2419
// echo 'Casting '.$val.' to integer<br />';
2420
$val = (integer) $val;
2422
// } elseif (array_key_exists(trim(strtoupper($val)), $this->_ExcelConstants)) {
2423
// $excelConstant = trim(strtoupper($val));
2424
// echo 'Element '.$val.' is an Excel Constant<br />';
2425
// $val = $this->_ExcelConstants[$excelConstant];
2431
} elseif ($opCharacter == ')') { // miscellaneous error checking
2432
if ($expectingOperand) {
2433
$output[] = $this->_ExcelConstants['NULL'];
2434
$expectingOperand = false;
2435
$expectingOperator = True;
2437
return $this->_raiseFormulaError("Formula Error: Unexpected ')'");
2439
} elseif (in_array($opCharacter, $this->_operators) && !$expectingOperator) {
2440
return $this->_raiseFormulaError("Formula Error: Unexpected operator '$opCharacter'");
2441
} else { // I don't even want to know what you did to get here
2442
return $this->_raiseFormulaError("Formula Error: An unexpected error occured");
2444
// Test for end of formula string
2445
if ($index == strlen($formula)) {
2446
// Did we end with an operator?.
2447
// Only valid for the % unary operator
2448
if ((in_array($opCharacter, $this->_operators)) && ($opCharacter != '%')) {
2449
return $this->_raiseFormulaError("Formula Error: Operator '$opCharacter' has no operands");
2454
// Ignore white space
2455
while (substr($formula, $index, 1) == ' ') {
2460
while (!is_null($opCharacter = $stack->pop())) { // pop everything off the stack and push onto output
2461
if ($opCharacter == '(') return $this->_raiseFormulaError("Formula Error: Expecting ')'"); // if there are any opening braces on the stack, then braces were unbalanced
2462
$output[] = $opCharacter;
2465
} // function _parseFormula()
2468
// evaluate postfix notation
2469
private function _processTokenStack($tokens, $cellID=null, PHPExcel_Cell $pCell = null) {
2470
if ($tokens == false) return false;
2472
$stack = new PHPExcel_Token_Stack;
2474
// Loop through each token in turn
2475
foreach ($tokens as $token) {
2476
// echo '<b>Token is '.$token.'</b><br />';
2477
// 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
2478
if (in_array($token, $this->_binaryOperators, true)) {
2479
// echo 'Token is a binary operator<br />';
2480
// We must have two operands, error if we don't
2481
if (is_null($operand2 = $stack->pop())) return $this->_raiseFormulaError('Internal error - Operand value missing from stack');
2482
if (is_null($operand1 = $stack->pop())) return $this->_raiseFormulaError('Internal error - Operand value missing from stack');
2483
// Log what we're doing
2484
$this->_writeDebug($cellID,'Evaluating '.self::_showValue($operand1).' '.$token.' '.self::_showValue($operand2));
2485
// Process the operation in the appropriate manner
2487
// Comparison (Boolean) Operators
2488
case '>' : // Greater than
2489
case '<' : // Less than
2490
case '>=' : // Greater than or Equal to
2491
case '<=' : // Less than or Equal to
2492
case '=' : // Equality
2493
case '<>' : // Inequality
2494
$this->_executeBinaryComparisonOperation($cellID,$operand1,$operand2,$token,$stack);
2497
case '+' : // Addition
2498
$this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'plusEquals',$stack);
2500
case '-' : // Subtraction
2501
$this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'minusEquals',$stack);
2503
case '*' : // Multiplication
2504
$this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'arrayTimesEquals',$stack);
2506
case '/' : // Division
2507
$this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'arrayRightDivide',$stack);
2509
case '^' : // Exponential
2510
$this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'power',$stack);
2512
case '&' : // Concatenation
2513
// If either of the operands is a matrix, we need to treat them both as matrices
2514
// (converting the other operand to a matrix if need be); then perform the required
2516
if ((is_array($operand1)) || (is_array($operand2))) {
2517
// Ensure that both operands are arrays/matrices
2518
self::_checkMatrixOperands($operand1,$operand2);
2520
// Convert operand 1 from a PHP array to a matrix
2521
$matrix = new Matrix($operand1);
2522
// Perform the required operation against the operand 1 matrix, passing in operand 2
2523
$matrixResult = $matrix->concat($operand2);
2524
$result = $matrixResult->getArray();
2525
} catch (Exception $ex) {
2526
$this->_writeDebug($cellID,'JAMA Matrix Exception: '.$ex->getMessage());
2527
$result = '#VALUE!';
2530
$result = '"'.str_replace('""','"',self::_unwrapResult($operand1,'"').self::_unwrapResult($operand2,'"')).'"';
2532
$this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($result));
2533
$stack->push($result);
2537
// if the token is a unary operator, pop one value off the stack, do the operation, and push it back on
2538
} elseif (($token === "_") || ($token === "%")) {
2539
// echo 'Token is a unary operator<br />';
2540
if (is_null($arg = $stack->pop())) return $this->_raiseFormulaError('Internal error - Operand value missing from stack');
2541
if ($token === "_") {
2542
// echo 'Token is a negation operator<br />';
2543
$this->_writeDebug($cellID,'Evaluating Negation of '.self::_showValue($arg));
2546
// echo 'Token is a percentile operator<br />';
2547
$this->_writeDebug($cellID,'Evaluating Percentile of '.self::_showValue($arg));
2550
if (is_array($arg)) {
2551
self::_checkMatrixOperands($arg,$multiplier);
2553
$matrix1 = new Matrix($arg);
2554
$matrixResult = $matrix1->arrayTimesEquals($multiplier);
2555
$result = $matrixResult->getArray();
2556
} catch (Exception $ex) {
2557
$this->_writeDebug($cellID,'JAMA Matrix Exception: '.$ex->getMessage());
2558
$result = '#VALUE!';
2562
$result = $multiplier * $arg;
2564
$this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($result));
2565
$stack->push($result);
2567
} elseif (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $token, $matches)) {
2568
// echo 'Element '.$token.' is a Cell reference<br />';
2569
if (isset($matches[8])) {
2570
// echo 'Reference is a Range of cells<br />';
2571
if (is_null($pCell)) {
2572
// We can't access the range, so return a REF error
2573
$cellValue = PHPExcel_Calculation_Functions::REF();
2575
$cellRef = $matches[6].$matches[7].':'.$matches[9].$matches[10];
2576
if ($matches[2] > '') {
2577
// echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'<br />';
2578
$this->_writeDebug($cellID,'Evaluating Cell Range '.$cellRef.' in worksheet '.$matches[2]);
2579
$cellValue = $this->extractCellRange($cellRef, $pCell->getParent()->getParent()->getSheetByName($matches[2]), false);
2580
$this->_writeDebug($cellID,'Evaluation Result for cells '.$cellRef.' in worksheet '.$matches[2].' is '.self::_showTypeDetails($cellValue));
2582
// echo '$cellRef='.$cellRef.' in current worksheet<br />';
2583
$this->_writeDebug($cellID,'Evaluating Cell Range '.$cellRef.' in current worksheet');
2584
$cellValue = $this->extractCellRange($cellRef, $pCell->getParent(), false);
2585
$this->_writeDebug($cellID,'Evaluation Result for cells '.$cellRef.' is '.self::_showTypeDetails($cellValue));
2589
// echo 'Reference is a single Cell<br />';
2590
if (is_null($pCell)) {
2591
// We can't access the cell, so return a REF error
2592
$cellValue = PHPExcel_Calculation_Functions::REF();
2594
$cellRef = $matches[6].$matches[7];
2595
if ($matches[2] > '') {
2596
// echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'<br />';
2597
$this->_writeDebug($cellID,'Evaluating Cell '.$cellRef.' in worksheet '.$matches[2]);
2598
if ($pCell->getParent()->cellExists($cellRef)) {
2599
$cellValue = $this->extractCellRange($cellRef, $pCell->getParent()->getParent()->getSheetByName($matches[2]), false);
2603
$this->_writeDebug($cellID,'Evaluation Result for cell '.$cellRef.' in worksheet '.$matches[2].' is '.self::_showTypeDetails($cellValue));
2605
// echo '$cellRef='.$cellRef.' in current worksheet<br />';
2606
$this->_writeDebug($cellID,'Evaluating Cell '.$cellRef.' in current worksheet');
2607
if ($pCell->getParent()->cellExists($cellRef)) {
2608
$cellValue = $pCell->getParent()->getCell($cellRef)->getCalculatedValue(false);
2612
$this->_writeDebug($cellID,'Evaluation Result for cell '.$cellRef.' is '.self::_showTypeDetails($cellValue));
2616
$stack->push($cellValue);
2618
// if the token is a function, pop arguments off the stack, hand them to the function, and push the result back on
2619
} elseif (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $token, $matches)) {
2620
// echo 'Token is a function<br />';
2621
$functionName = $matches[1];
2622
$argCount = $stack->pop();
2623
if ($functionName != 'MKMATRIX') {
2624
$this->_writeDebug($cellID,'Evaluating Function '.$functionName.'() with '.(($argCount == 0) ? 'no' : $argCount).' argument'.(($argCount == 1) ? '' : 's'));
2626
if ((array_key_exists($functionName, $this->_controlFunctions)) || (array_key_exists($functionName, $this->_PHPExcelFunctions))) { // function
2627
if (array_key_exists($functionName, $this->_controlFunctions)) {
2628
$functionCall = $this->_controlFunctions[$functionName]['functionCall'];
2629
} elseif (array_key_exists($functionName, $this->_PHPExcelFunctions)) {
2630
$functionCall = $this->_PHPExcelFunctions[$functionName]['functionCall'];
2632
// get the arguments for this function
2633
// echo 'Function '.$functionName.' expects '.$argCount.' arguments<br />';
2635
for ($i = $argCount; $i > 0; --$i) {
2636
$arg = $stack->pop();
2637
// if (is_null($arg)) return $this->_raiseFormulaError("internal error");
2640
// Reverse the order of the arguments
2642
// echo 'Arguments are: ';
2645
if ($functionName != 'MKMATRIX') {
2646
$argArrayVals = array();
2647
foreach($args as &$arg) {
2648
$argArrayVals[] = self::_showValue($arg);
2649
$arg = self::_unwrapResult($arg);
2652
$this->_writeDebug($cellID,'Evaluating '. $functionName.'( '.implode(', ',$argArrayVals).' )');
2654
// Process each argument in turn, building the return value as an array
2655
// if (($argCount == 1) && (is_array($args[1])) && ($functionName != 'MKMATRIX')) {
2656
// $operand1 = $args[1];
2657
// $this->_writeDebug($cellID,'Argument is a matrix: '.self::_showValue($operand1));
2658
// $result = array();
2660
// foreach($operand1 as $args) {
2661
// if (is_array($args)) {
2662
// foreach($args as $arg) {
2663
// $this->_writeDebug($cellID,'Evaluating '. $functionName.'( '.self::_showValue($arg).' )');
2664
// $r = call_user_func_array($functionCall,$arg);
2665
// $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($r));
2666
// $result[$row][] = $r;
2670
// $this->_writeDebug($cellID,'Evaluating '. $functionName.'( '.self::_showValue($args).' )');
2671
// $r = call_user_func_array($functionCall,$args);
2672
// $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($r));
2677
// Process the argument with the appropriate function call
2678
$result = call_user_func_array($functionCall,$args);
2680
if ($functionName != 'MKMATRIX') {
2681
$this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($result));
2683
$stack->push(self::_wrapResult($result));
2687
// if the token is a number, boolean, string or an Excel error, push it onto the stack
2688
if (array_key_exists(strtoupper($token), $this->_ExcelConstants)) {
2689
$excelConstant = strtoupper($token);
2690
// echo 'Token is a PHPExcel constant: '.$excelConstant.'<br />';
2691
$stack->push($this->_ExcelConstants[$excelConstant]);
2692
$this->_writeDebug($cellID,'Evaluating Constant '.$excelConstant.' as '.self::_showTypeDetails($this->_ExcelConstants[$excelConstant]));
2693
} elseif ((is_null($token)) || ($token == '') || (is_bool($token)) || (is_numeric($token)) || ($token{0} == '"') || ($token{0} == '#')) {
2694
// echo 'Token is a number, boolean, string or an Excel error<br />';
2695
$stack->push($token);
2696
// if the token is a constant, push the constant value on the stack
2697
} elseif (preg_match('/^'.self::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $token, $matches)) {
2698
// echo 'Token is a named range<br />';
2699
$namedRange = $matches[6];
2700
// echo 'Named Range is '.$namedRange.'<br />';
2701
$this->_writeDebug($cellID,'Evaluating Named Range '.$namedRange);
2702
$cellValue = $this->extractNamedRange($namedRange, $pCell->getParent(), false);
2703
$this->_writeDebug($cellID,'Evaluation Result for named range '.$namedRange.' is '.self::_showTypeDetails($cellValue));
2704
$stack->push($cellValue);
2706
return $this->_raiseFormulaError("undefined variable '$token'");
2710
// when we're out of tokens, the stack should have a single element, the final result
2711
if ($stack->count() != 1) return $this->_raiseFormulaError("internal error");
2712
$output = $stack->pop();
2713
if ((is_array($output)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) {
2714
return array_unshift(array_unshift($output));
2717
} // function _processTokenStack()
2720
private function _validateBinaryOperand($cellID,&$operand,&$stack) {
2721
// Numbers, matrices and booleans can pass straight through, as they're already valid
2722
if (is_string($operand)) {
2723
// We only need special validations for the operand if it is a string
2724
// Start by stripping off the quotation marks we use to identify true excel string values internally
2725
if ($operand > '' && $operand{0} == '"') { $operand = self::_unwrapResult($operand,'"'); }
2726
// If the string is a numeric value, we treat it as a numeric, so no further testing
2727
if (!is_numeric($operand)) {
2728
// If not a numeric, test to see if the value is an Excel error, and so can't be used in normal binary operations
2729
if ($operand > '' && $operand{0} == '#') {
2730
$stack->push($operand);
2731
$this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($operand));
2734
// If not a numeric, then it's a text string, and so can't be used in mathematical binary operations
2735
$stack->push('#VALUE!');
2736
$this->_writeDebug($cellID,'Evaluation Result is a '.self::_showTypeDetails('#VALUE!'));
2742
// return a true if the value of the operand is one that we can use in normal binary operations
2744
} // function _validateBinaryOperand()
2747
private function _executeBinaryComparisonOperation($cellID,$operand1,$operand2,$operation,&$stack) {
2748
// Validate the two operands
2750
// If we're dealing with non-matrix operations, execute the necessary operation
2751
switch ($operation) {
2754
$result = ($operand1 > $operand2);
2758
$result = ($operand1 < $operand2);
2762
$result = ($operand1 == $operand2);
2764
// Greater than or equal
2766
$result = ($operand1 >= $operand2);
2768
// Less than or equal
2770
$result = ($operand1 <= $operand2);
2774
$result = ($operand1 != $operand2);
2778
// Log the result details
2779
$this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($result));
2780
// And push the result onto the stack
2781
$stack->push($result);
2783
} // function _executeBinaryComparisonOperation()
2785
private function _executeNumericBinaryOperation($cellID,$operand1,$operand2,$operation,$matrixFunction,&$stack) {
2786
// Validate the two operands
2787
if (!$this->_validateBinaryOperand($cellID,$operand1,$stack)) return false;
2788
if (!$this->_validateBinaryOperand($cellID,$operand2,$stack)) return false;
2790
// If either of the operands is a matrix, we need to treat them both as matrices
2791
// (converting the other operand to a matrix if need be); then perform the required
2793
if ((is_array($operand1)) || (is_array($operand2))) {
2794
// Ensure that both operands are arrays/matrices
2795
self::_checkMatrixOperands($operand1,$operand2);
2797
// Convert operand 1 from a PHP array to a matrix
2798
$matrix = new Matrix($operand1);
2799
// Perform the required operation against the operand 1 matrix, passing in operand 2
2800
$matrixResult = $matrix->$matrixFunction($operand2);
2801
$result = $matrixResult->getArray();
2802
} catch (Exception $ex) {
2803
$this->_writeDebug($cellID,'JAMA Matrix Exception: '.$ex->getMessage());
2804
$result = '#VALUE!';
2807
// If we're dealing with non-matrix operations, execute the necessary operation
2808
switch ($operation) {
2811
$result = $operand1+$operand2;
2815
$result = $operand1-$operand2;
2819
$result = $operand1*$operand2;
2823
if ($operand2 == 0) {
2824
// Trap for Divide by Zero error
2825
$stack->push('#DIV/0!');
2826
$this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails('#DIV/0!'));
2829
$result = $operand1/$operand2;
2834
$result = pow($operand1,$operand2);
2839
// Log the result details
2840
$this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($result));
2841
// And push the result onto the stack
2842
$stack->push($result);
2844
} // function _executeNumericBinaryOperation()
2847
private function _writeDebug($cellID,$message) {
2848
// Only write the debug log if logging is enabled
2849
if ($this->writeDebugLog) {
2850
// $prefix = substr(implode(' -> ',$this->debugLogStack).' -> ',4+strlen($this->debugLogStack[0]));
2851
$prefix = implode(' -> ',$this->debugLogStack).' -> ';
2852
$this->debugLog[] = $prefix.$message;
2854
} // function _writeDebug()
2857
// trigger an error, but nicely, if need be
2858
private function _raiseFormulaError($errorMessage) {
2859
$this->formulaError = $errorMessage;
2860
if (!$this->suppressFormulaErrors) throw new Exception($errorMessage);
2861
trigger_error($errorMessage, E_USER_ERROR);
2862
} // function _raiseFormulaError()
2866
* Extract range values
2868
* @param string $pRange String based range representation
2869
* @param PHPExcel_Worksheet $pSheet Worksheet
2870
* @return mixed Array of values in range if range contains more than one element. Otherwise, a single value is returned.
2873
public function extractCellRange($pRange = 'A1', PHPExcel_Worksheet $pSheet = null, $resetLog=true) {
2875
$returnValue = array ( );
2877
// echo 'extractCellRange('.$pRange.')<br />';
2879
if (!is_null($pSheet)) {
2880
// Worksheet reference?
2881
// echo 'Current sheet name is '.$pSheet->getTitle().'<br />';
2882
// echo 'Range reference is '.$pRange.'<br />';
2883
if (strpos ($pRange, '!') !== false) {
2884
// echo '$pRange reference includes sheet reference<br />';
2885
$worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pRange, true);
2886
$pSheet = $pSheet->getParent()->getSheetByName($worksheetReference[0]);
2887
// echo 'New sheet name is '.$pSheet->getTitle().'<br />';
2888
$pRange = $worksheetReference[1];
2889
// echo 'Adjusted Range reference is '.$pRange.'<br />';
2893
$aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange);
2894
if (count($aReferences) == 1) {
2895
return $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog);
2898
// Extract cell data
2899
foreach ($aReferences as $reference) {
2901
list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($reference);
2903
$returnValue[$currentCol][$currentRow] = $pSheet->getCell($reference)->getCalculatedValue($resetLog);
2908
return $returnValue;
2909
} // function extractCellRange()
2913
* Extract range values
2915
* @param string $pRange String based range representation
2916
* @param PHPExcel_Worksheet $pSheet Worksheet
2917
* @return mixed Array of values in range if range contains more than one element. Otherwise, a single value is returned.
2920
public function extractNamedRange($pRange = 'A1', PHPExcel_Worksheet $pSheet = null, $resetLog=true) {
2922
$returnValue = array ( );
2924
// echo 'extractNamedRange('.$pRange.')<br />';
2926
if (!is_null($pSheet)) {
2927
// Worksheet reference?
2928
// echo 'Current sheet name is '.$pSheet->getTitle().'<br />';
2929
// echo 'Range reference is '.$pRange.'<br />';
2930
if (strpos ($pRange, '!') !== false) {
2931
// echo '$pRange reference includes sheet reference<br />';
2932
$worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pRange, true);
2933
$pSheet = $pSheet->getParent()->getSheetByName($worksheetReference[0]);
2934
// echo 'New sheet name is '.$pSheet->getTitle().'<br />';
2935
$pRange = $worksheetReference[1];
2936
// echo 'Adjusted Range reference is '.$pRange.'<br />';
2940
$namedRange = PHPExcel_NamedRange::resolveRange($pRange, $pSheet);
2941
if (!is_null($namedRange)) {
2942
// echo 'Named Range '.$pRange.' (';
2943
$pRange = $namedRange->getRange();
2944
// echo $pRange.') is in sheet '.$namedRange->getWorksheet()->getTitle().'<br />';
2945
if ($pSheet->getTitle() != $namedRange->getWorksheet()->getTitle()) {
2946
if (!$namedRange->getLocalOnly()) {
2947
$pSheet = $namedRange->getWorksheet();
2949
return $returnValue;
2955
$aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange);
2956
if (count($aReferences) == 1) {
2957
return $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog);
2960
// Extract cell data
2961
foreach ($aReferences as $reference) {
2963
list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($reference);
2964
// echo 'NAMED RANGE: $currentCol='.$currentCol.' $currentRow='.$currentRow.'<br />';
2965
$returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog);
2967
// print_r($returnValue);
2969
$returnValue = array_values($returnValue);
2970
foreach($returnValue as &$rr) {
2971
$rr = array_values($rr);
2974
// print_r($returnValue);
2979
return $returnValue;
2980
} // function extractNamedRange()
2984
* Is a specific function implemented?
2986
* @param string $pFunction Function Name
2989
public function isImplemented($pFunction = '') {
2990
$pFunction = strtoupper ($pFunction);
2991
if (isset ($this->_PHPExcelFunctions[$pFunction])) {
2992
return ($this->_PHPExcelFunctions[$pFunction]['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY');
2996
} // function isImplemented()
3000
* Get a list of all implemented functions as an array of function objects
3002
* @return array of PHPExcel_Calculation_Function
3004
public function listFunctions() {
3006
$returnValue = array();
3008
foreach($this->_PHPExcelFunctions as $functionName => $function) {
3009
if ($function['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY') {
3010
$returnValue[$functionName] = new PHPExcel_Calculation_Function($function['category'],
3012
$function['functionCall']
3018
return $returnValue;
3019
} // function listFunctions()
3023
* Get a list of implemented Excel function names
3027
public function listFunctionNames() {
3029
$returnValue = array();
3031
foreach ($this->_PHPExcelFunctions as $functionName => $function) {
3032
$returnValue[] = $functionName;
3036
return $returnValue;
3037
} // function listFunctionNames()
3039
} // class PHPExcel_Calculation
3045
class PHPExcel_Token_Stack {
3047
private $_stack = array();
3048
private $_count = 0;
3050
public function count() {
3051
return $this->_count;
3054
public function push($value) {
3055
$this->_stack[$this->_count++] = $value;
3058
public function pop() {
3059
if ($this->_count > 0) {
3060
return $this->_stack[--$this->_count];
3065
public function last($n=1) {
3066
if ($this->_count-$n < 0) {
3069
return $this->_stack[$this->_count-$n];
3072
function __construct() {
3075
} // class PHPExcel_Token_Stack