2010-08-26 19:14:53 +00:00
< ? php
/** PHPExcel root directory */
if ( ! defined ( 'PHPEXCEL_ROOT' )) {
2015-05-12 23:40:55 +00:00
/**
* @ ignore
*/
define ( 'PHPEXCEL_ROOT' , dirname ( __FILE__ ) . '/../' );
require ( PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php' );
2010-08-26 19:14:53 +00:00
}
2010-12-23 21:18:23 +00:00
if ( ! defined ( 'CALCULATION_REGEXP_CELLREF' )) {
2015-05-12 23:40:55 +00:00
// Test for support of \P (multibyte options) in PCRE
2015-05-13 16:00:22 +00:00
if ( defined ( 'PREG_BAD_UTF8_ERROR' )) {
2015-05-12 23:40:55 +00:00
// Cell reference (cell or range of cells, with or without a sheet reference)
2015-05-13 16:00:22 +00:00
define ( 'CALCULATION_REGEXP_CELLREF' , '((([^\s,!&%^\/\*\+<>=-]*)|(\'[^\']*\')|(\"[^\"]*\"))!)?\$?([a-z]{1,3})\$?(\d{1,7})' );
2015-05-12 23:40:55 +00:00
// Named Range of cells
2015-05-13 16:00:22 +00:00
define ( 'CALCULATION_REGEXP_NAMEDRANGE' , '((([^\s,!&%^\/\*\+<>=-]*)|(\'[^\']*\')|(\"[^\"]*\"))!)?([_A-Z][_A-Z0-9\.]*)' );
2015-05-12 23:40:55 +00:00
} else {
// Cell reference (cell or range of cells, with or without a sheet reference)
2015-05-13 16:00:22 +00:00
define ( 'CALCULATION_REGEXP_CELLREF' , '(((\w*)|(\'[^\']*\')|(\"[^\"]*\"))!)?\$?([a-z]{1,3})\$?(\d+)' );
2015-05-12 23:40:55 +00:00
// Named Range of cells
2015-05-13 16:00:22 +00:00
define ( 'CALCULATION_REGEXP_NAMEDRANGE' , '(((\w*)|(\'.*\')|(\".*\"))!)?([_A-Z][_A-Z0-9\.]*)' );
2015-05-12 23:40:55 +00:00
}
2010-12-23 21:18:23 +00:00
}
2010-08-26 19:14:53 +00:00
/**
2013-04-30 11:45:13 +00:00
* PHPExcel_Calculation ( Multiton )
2010-08-26 19:14:53 +00:00
*
2015-05-13 16:00:22 +00:00
* Copyright ( c ) 2006 - 2015 PHPExcel
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
*
* @ category PHPExcel
* @ package PHPExcel_Calculation
* @ copyright Copyright ( c ) 2006 - 2015 PHPExcel ( http :// www . codeplex . com / PHPExcel )
* @ license http :// www . gnu . org / licenses / old - licenses / lgpl - 2.1 . txt LGPL
* @ version ##VERSION##, ##DATE##
2010-08-26 19:14:53 +00:00
*/
2015-05-13 16:00:22 +00:00
class PHPExcel_Calculation
{
2015-05-12 23:40:55 +00:00
/** Constants */
/** Regular Expressions */
// Numeric operand
const CALCULATION_REGEXP_NUMBER = '[-+]?\d*\.?\d+(e[-+]?\d+)?' ;
// String operand
const CALCULATION_REGEXP_STRING = '"(?:[^"]|"")*"' ;
// Opening bracket
const CALCULATION_REGEXP_OPENBRACE = '\(' ;
// Function (allow for the old @ symbol that could be used to prefix a function, but we'll ignore it)
const CALCULATION_REGEXP_FUNCTION = '@?([A-Z][A-Z0-9\.]*)[\s]*\(' ;
// Cell reference (cell or range of cells, with or without a sheet reference)
const CALCULATION_REGEXP_CELLREF = CALCULATION_REGEXP_CELLREF ;
// Named Range of cells
const CALCULATION_REGEXP_NAMEDRANGE = CALCULATION_REGEXP_NAMEDRANGE ;
// Error
const CALCULATION_REGEXP_ERROR = '\#[A-Z][A-Z0_\/]*[!\?]?' ;
/** constants */
const RETURN_ARRAY_AS_ERROR = 'error' ;
const RETURN_ARRAY_AS_VALUE = 'value' ;
const RETURN_ARRAY_AS_ARRAY = 'array' ;
2015-05-13 16:00:22 +00:00
private static $returnArrayAsType = self :: RETURN_ARRAY_AS_VALUE ;
2015-05-12 23:40:55 +00:00
/**
* Instance of this class
*
* @ access private
* @ var PHPExcel_Calculation
*/
private static $_instance ;
/**
* Instance of the workbook this Calculation Engine is using
*
* @ access private
* @ var PHPExcel
*/
2013-02-04 17:26:27 +00:00
private $_workbook ;
2015-05-12 23:40:55 +00:00
/**
* List of instances of the calculation engine that we ' ve instantiated for individual workbooks
*
* @ access private
* @ var PHPExcel_Calculation []
*/
2013-02-04 17:26:27 +00:00
private static $_workbookSets ;
2015-05-12 23:40:55 +00:00
/**
* Calculation cache
*
* @ access private
* @ var array
*/
private $_calculationCache = array ();
/**
* Calculation cache enabled
*
* @ access private
* @ var boolean
*/
2015-05-13 16:00:22 +00:00
private $_calculationCacheEnabled = true ;
2015-05-12 23:40:55 +00:00
/**
* List of operators that can be used within formulae
* The true / false value indicates whether it is a binary operator or a unary operator
*
* @ access private
* @ var array
*/
2015-05-13 16:00:22 +00:00
private static $_operators = array (
'+' => true , '-' => true , '*' => true , '/' => true ,
'^' => true , '&' => true , '%' => false , '~' => false ,
'>' => true , '<' => true , '=' => true , '>=' => true ,
'<=' => true , '<>' => true , '|' => true , ':' => true
);
2015-05-12 23:40:55 +00:00
/**
* List of binary operators ( those that expect two operands )
*
* @ access private
* @ var array
*/
2015-05-13 16:00:22 +00:00
private static $_binaryOperators = array (
'+' => true , '-' => true , '*' => true , '/' => true ,
'^' => true , '&' => true , '>' => true , '<' => true ,
'=' => true , '>=' => true , '<=' => true , '<>' => true ,
'|' => true , ':' => true
);
2015-05-12 23:40:55 +00:00
/**
* The debug log generated by the calculation engine
*
* @ access private
* @ var PHPExcel_CalcEngine_Logger
*
*/
private $debugLog ;
/**
* Flag to determine how formula errors should be handled
* If true , then a user error will be triggered
* If false , then an exception will be thrown
*
* @ access public
* @ var boolean
*
*/
2015-05-13 16:00:22 +00:00
public $suppressFormulaErrors = false ;
2015-05-12 23:40:55 +00:00
/**
* Error message for any error that was raised / thrown by the calculation engine
*
* @ access public
* @ var string
*
*/
2015-05-13 16:00:22 +00:00
public $formulaError = null ;
2015-05-12 23:40:55 +00:00
/**
* An array of the nested cell references accessed by the calculation engine , used for the debug log
*
* @ access private
* @ var array of string
*
*/
private $_cyclicReferenceStack ;
private $_cellStack = array ();
/**
* Current iteration counter for cyclic formulae
* If the value is 0 ( or less ) then cyclic formulae will throw an exception ,
* otherwise they will iterate to the limit defined here before returning a result
*
* @ var integer
*
*/
private $_cyclicFormulaCount = 1 ;
private $_cyclicFormulaCell = '' ;
/**
* Number of iterations for cyclic formulae
*
* @ var integer
*
*/
public $cyclicFormulaCount = 1 ;
/**
* Precision used for calculations
*
* @ var integer
*
*/
private $_savedPrecision = 14 ;
/**
* The current locale setting
*
* @ var string
*
*/
private static $_localeLanguage = 'en_us' ; // US English (default locale)
/**
* List of available locale settings
* Note that this is read for the locale subdirectory only when requested
*
* @ var string []
*
*/
2015-05-13 16:00:22 +00:00
private static $_validLocaleLanguages = array (
'en' // English (default language)
);
2015-05-12 23:40:55 +00:00
/**
* Locale - specific argument separator for function arguments
*
* @ var string
*
*/
private static $_localeArgumentSeparator = ',' ;
private static $_localeFunctions = array ();
/**
* Locale - specific translations for Excel constants ( True , False and Null )
*
* @ var string []
*
*/
2015-05-13 16:00:22 +00:00
public static $_localeBoolean = array (
'TRUE' => 'TRUE' ,
'FALSE' => 'FALSE' ,
'NULL' => 'NULL'
);
2015-05-12 23:40:55 +00:00
/**
* Excel constant string translations to their PHP equivalents
* Constant conversion from text name / value to actual ( datatyped ) value
*
* @ var string []
*
*/
2015-05-13 16:00:22 +00:00
private static $_ExcelConstants = array (
'TRUE' => true ,
'FALSE' => false ,
'NULL' => null
);
2015-05-12 23:40:55 +00:00
// PHPExcel functions
private static $_PHPExcelFunctions = array ( // PHPExcel functions
'ABS' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'abs' ,
'argumentCount' => '1'
),
'ACCRINT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::ACCRINT' ,
'argumentCount' => '4-7'
),
'ACCRINTM' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::ACCRINTM' ,
'argumentCount' => '3-5'
),
'ACOS' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'acos' ,
'argumentCount' => '1'
),
'ACOSH' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'acosh' ,
'argumentCount' => '1'
),
'ADDRESS' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOOKUP_AND_REFERENCE ,
'functionCall' => 'PHPExcel_Calculation_LookupRef::CELL_ADDRESS' ,
'argumentCount' => '2-5'
),
'AMORDEGRC' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::AMORDEGRC' ,
'argumentCount' => '6,7'
),
'AMORLINC' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::AMORLINC' ,
'argumentCount' => '6,7'
),
'AND' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOGICAL ,
'functionCall' => 'PHPExcel_Calculation_Logical::LOGICAL_AND' ,
'argumentCount' => '1+'
),
'AREAS' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOOKUP_AND_REFERENCE ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '1'
),
'ASC' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '1'
),
'ASIN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'asin' ,
'argumentCount' => '1'
),
'ASINH' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'asinh' ,
'argumentCount' => '1'
),
'ATAN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'atan' ,
'argumentCount' => '1'
),
'ATAN2' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::ATAN2' ,
'argumentCount' => '2'
),
'ATANH' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'atanh' ,
'argumentCount' => '1'
),
'AVEDEV' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::AVEDEV' ,
'argumentCount' => '1+'
),
'AVERAGE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::AVERAGE' ,
'argumentCount' => '1+'
),
'AVERAGEA' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::AVERAGEA' ,
'argumentCount' => '1+'
),
'AVERAGEIF' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::AVERAGEIF' ,
'argumentCount' => '2,3'
),
'AVERAGEIFS' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '3+'
),
'BAHTTEXT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '1'
),
'BESSELI' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::BESSELI' ,
'argumentCount' => '2'
),
'BESSELJ' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::BESSELJ' ,
'argumentCount' => '2'
),
'BESSELK' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::BESSELK' ,
'argumentCount' => '2'
),
'BESSELY' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::BESSELY' ,
'argumentCount' => '2'
),
'BETADIST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::BETADIST' ,
'argumentCount' => '3-5'
),
'BETAINV' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::BETAINV' ,
'argumentCount' => '3-5'
),
'BIN2DEC' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::BINTODEC' ,
'argumentCount' => '1'
),
'BIN2HEX' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::BINTOHEX' ,
'argumentCount' => '1,2'
),
'BIN2OCT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::BINTOOCT' ,
'argumentCount' => '1,2'
),
'BINOMDIST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::BINOMDIST' ,
'argumentCount' => '4'
),
'CEILING' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::CEILING' ,
'argumentCount' => '2'
),
'CELL' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_INFORMATION ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '1,2'
),
'CHAR' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::CHARACTER' ,
'argumentCount' => '1'
),
'CHIDIST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::CHIDIST' ,
'argumentCount' => '2'
),
'CHIINV' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::CHIINV' ,
'argumentCount' => '2'
),
'CHITEST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '2'
),
'CHOOSE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOOKUP_AND_REFERENCE ,
'functionCall' => 'PHPExcel_Calculation_LookupRef::CHOOSE' ,
'argumentCount' => '2+'
),
'CLEAN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::TRIMNONPRINTABLE' ,
'argumentCount' => '1'
),
'CODE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::ASCIICODE' ,
'argumentCount' => '1'
),
'COLUMN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOOKUP_AND_REFERENCE ,
'functionCall' => 'PHPExcel_Calculation_LookupRef::COLUMN' ,
'argumentCount' => '-1' ,
2015-05-13 16:00:22 +00:00
'passByReference' => array ( true )
2015-05-12 23:40:55 +00:00
),
'COLUMNS' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOOKUP_AND_REFERENCE ,
'functionCall' => 'PHPExcel_Calculation_LookupRef::COLUMNS' ,
'argumentCount' => '1'
),
'COMBIN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::COMBIN' ,
'argumentCount' => '2'
),
'COMPLEX' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::COMPLEX' ,
'argumentCount' => '2,3'
),
'CONCATENATE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::CONCATENATE' ,
'argumentCount' => '1+'
),
'CONFIDENCE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::CONFIDENCE' ,
'argumentCount' => '3'
),
'CONVERT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::CONVERTUOM' ,
'argumentCount' => '3'
),
'CORREL' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::CORREL' ,
'argumentCount' => '2'
),
'COS' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'cos' ,
'argumentCount' => '1'
),
'COSH' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'cosh' ,
'argumentCount' => '1'
),
'COUNT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::COUNT' ,
'argumentCount' => '1+'
),
'COUNTA' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::COUNTA' ,
'argumentCount' => '1+'
),
'COUNTBLANK' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::COUNTBLANK' ,
'argumentCount' => '1'
),
'COUNTIF' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::COUNTIF' ,
'argumentCount' => '2'
),
'COUNTIFS' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '2'
),
'COUPDAYBS' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::COUPDAYBS' ,
'argumentCount' => '3,4'
),
'COUPDAYS' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::COUPDAYS' ,
'argumentCount' => '3,4'
),
'COUPDAYSNC' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::COUPDAYSNC' ,
'argumentCount' => '3,4'
),
'COUPNCD' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::COUPNCD' ,
'argumentCount' => '3,4'
),
'COUPNUM' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::COUPNUM' ,
'argumentCount' => '3,4'
),
'COUPPCD' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::COUPPCD' ,
'argumentCount' => '3,4'
),
'COVAR' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::COVAR' ,
'argumentCount' => '2'
),
'CRITBINOM' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::CRITBINOM' ,
'argumentCount' => '3'
),
'CUBEKPIMEMBER' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_CUBE ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '?'
),
'CUBEMEMBER' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_CUBE ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '?'
),
'CUBEMEMBERPROPERTY' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_CUBE ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '?'
),
'CUBERANKEDMEMBER' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_CUBE ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '?'
),
'CUBESET' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_CUBE ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '?'
),
'CUBESETCOUNT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_CUBE ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '?'
),
'CUBEVALUE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_CUBE ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '?'
),
'CUMIPMT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::CUMIPMT' ,
'argumentCount' => '6'
),
'CUMPRINC' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::CUMPRINC' ,
'argumentCount' => '6'
),
'DATE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::DATE' ,
'argumentCount' => '3'
),
'DATEDIF' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::DATEDIF' ,
'argumentCount' => '2,3'
),
'DATEVALUE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::DATEVALUE' ,
'argumentCount' => '1'
),
'DAVERAGE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATABASE ,
'functionCall' => 'PHPExcel_Calculation_Database::DAVERAGE' ,
'argumentCount' => '3'
),
'DAY' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::DAYOFMONTH' ,
'argumentCount' => '1'
),
'DAYS360' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::DAYS360' ,
'argumentCount' => '2,3'
),
'DB' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::DB' ,
'argumentCount' => '4,5'
),
'DCOUNT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATABASE ,
'functionCall' => 'PHPExcel_Calculation_Database::DCOUNT' ,
'argumentCount' => '3'
),
'DCOUNTA' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATABASE ,
'functionCall' => 'PHPExcel_Calculation_Database::DCOUNTA' ,
'argumentCount' => '3'
),
'DDB' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::DDB' ,
'argumentCount' => '4,5'
),
'DEC2BIN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::DECTOBIN' ,
'argumentCount' => '1,2'
),
'DEC2HEX' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::DECTOHEX' ,
'argumentCount' => '1,2'
),
'DEC2OCT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::DECTOOCT' ,
'argumentCount' => '1,2'
),
'DEGREES' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'rad2deg' ,
'argumentCount' => '1'
),
'DELTA' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::DELTA' ,
'argumentCount' => '1,2'
),
'DEVSQ' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::DEVSQ' ,
'argumentCount' => '1+'
),
'DGET' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATABASE ,
'functionCall' => 'PHPExcel_Calculation_Database::DGET' ,
'argumentCount' => '3'
),
'DISC' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::DISC' ,
'argumentCount' => '4,5'
),
'DMAX' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATABASE ,
'functionCall' => 'PHPExcel_Calculation_Database::DMAX' ,
'argumentCount' => '3'
),
'DMIN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATABASE ,
'functionCall' => 'PHPExcel_Calculation_Database::DMIN' ,
'argumentCount' => '3'
),
'DOLLAR' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::DOLLAR' ,
'argumentCount' => '1,2'
),
'DOLLARDE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::DOLLARDE' ,
'argumentCount' => '2'
),
'DOLLARFR' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::DOLLARFR' ,
'argumentCount' => '2'
),
'DPRODUCT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATABASE ,
'functionCall' => 'PHPExcel_Calculation_Database::DPRODUCT' ,
'argumentCount' => '3'
),
'DSTDEV' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATABASE ,
'functionCall' => 'PHPExcel_Calculation_Database::DSTDEV' ,
'argumentCount' => '3'
),
'DSTDEVP' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATABASE ,
'functionCall' => 'PHPExcel_Calculation_Database::DSTDEVP' ,
'argumentCount' => '3'
),
'DSUM' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATABASE ,
'functionCall' => 'PHPExcel_Calculation_Database::DSUM' ,
'argumentCount' => '3'
),
'DURATION' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '5,6'
),
'DVAR' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATABASE ,
'functionCall' => 'PHPExcel_Calculation_Database::DVAR' ,
'argumentCount' => '3'
),
'DVARP' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATABASE ,
'functionCall' => 'PHPExcel_Calculation_Database::DVARP' ,
'argumentCount' => '3'
),
'EDATE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::EDATE' ,
'argumentCount' => '2'
),
'EFFECT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::EFFECT' ,
'argumentCount' => '2'
),
'EOMONTH' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::EOMONTH' ,
'argumentCount' => '2'
),
'ERF' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::ERF' ,
'argumentCount' => '1,2'
),
'ERFC' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::ERFC' ,
'argumentCount' => '1'
),
'ERROR.TYPE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_INFORMATION ,
'functionCall' => 'PHPExcel_Calculation_Functions::ERROR_TYPE' ,
'argumentCount' => '1'
),
'EVEN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::EVEN' ,
'argumentCount' => '1'
),
'EXACT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '2'
),
'EXP' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'exp' ,
'argumentCount' => '1'
),
'EXPONDIST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::EXPONDIST' ,
'argumentCount' => '3'
),
'FACT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::FACT' ,
'argumentCount' => '1'
),
'FACTDOUBLE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::FACTDOUBLE' ,
'argumentCount' => '1'
),
'FALSE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOGICAL ,
'functionCall' => 'PHPExcel_Calculation_Logical::FALSE' ,
'argumentCount' => '0'
),
'FDIST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '3'
),
'FIND' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::SEARCHSENSITIVE' ,
'argumentCount' => '2,3'
),
'FINDB' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::SEARCHSENSITIVE' ,
'argumentCount' => '2,3'
),
'FINV' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '3'
),
'FISHER' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::FISHER' ,
'argumentCount' => '1'
),
'FISHERINV' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::FISHERINV' ,
'argumentCount' => '1'
),
'FIXED' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::FIXEDFORMAT' ,
'argumentCount' => '1-3'
),
'FLOOR' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::FLOOR' ,
'argumentCount' => '2'
),
'FORECAST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::FORECAST' ,
'argumentCount' => '3'
),
'FREQUENCY' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '2'
),
'FTEST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '2'
),
'FV' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::FV' ,
'argumentCount' => '3-5'
),
'FVSCHEDULE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::FVSCHEDULE' ,
'argumentCount' => '2'
),
'GAMMADIST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::GAMMADIST' ,
'argumentCount' => '4'
),
'GAMMAINV' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::GAMMAINV' ,
'argumentCount' => '3'
),
'GAMMALN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::GAMMALN' ,
'argumentCount' => '1'
),
'GCD' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::GCD' ,
'argumentCount' => '1+'
),
'GEOMEAN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::GEOMEAN' ,
'argumentCount' => '1+'
),
'GESTEP' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::GESTEP' ,
'argumentCount' => '1,2'
),
'GETPIVOTDATA' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOOKUP_AND_REFERENCE ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '2+'
),
'GROWTH' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::GROWTH' ,
'argumentCount' => '1-4'
),
'HARMEAN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::HARMEAN' ,
'argumentCount' => '1+'
),
'HEX2BIN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::HEXTOBIN' ,
'argumentCount' => '1,2'
),
'HEX2DEC' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::HEXTODEC' ,
'argumentCount' => '1'
),
'HEX2OCT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::HEXTOOCT' ,
'argumentCount' => '1,2'
),
'HLOOKUP' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOOKUP_AND_REFERENCE ,
'functionCall' => 'PHPExcel_Calculation_LookupRef::HLOOKUP' ,
'argumentCount' => '3,4'
),
'HOUR' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::HOUROFDAY' ,
'argumentCount' => '1'
),
'HYPERLINK' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOOKUP_AND_REFERENCE ,
'functionCall' => 'PHPExcel_Calculation_LookupRef::HYPERLINK' ,
'argumentCount' => '1,2' ,
2015-05-13 16:00:22 +00:00
'passCellReference' => true
2015-05-12 23:40:55 +00:00
),
'HYPGEOMDIST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::HYPGEOMDIST' ,
'argumentCount' => '4'
),
'IF' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOGICAL ,
'functionCall' => 'PHPExcel_Calculation_Logical::STATEMENT_IF' ,
'argumentCount' => '1-3'
),
'IFERROR' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOGICAL ,
'functionCall' => 'PHPExcel_Calculation_Logical::IFERROR' ,
'argumentCount' => '2'
),
'IMABS' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::IMABS' ,
'argumentCount' => '1'
),
'IMAGINARY' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::IMAGINARY' ,
'argumentCount' => '1'
),
'IMARGUMENT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::IMARGUMENT' ,
'argumentCount' => '1'
),
'IMCONJUGATE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::IMCONJUGATE' ,
'argumentCount' => '1'
),
'IMCOS' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::IMCOS' ,
'argumentCount' => '1'
),
'IMDIV' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::IMDIV' ,
'argumentCount' => '2'
),
'IMEXP' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::IMEXP' ,
'argumentCount' => '1'
),
'IMLN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::IMLN' ,
'argumentCount' => '1'
),
'IMLOG10' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::IMLOG10' ,
'argumentCount' => '1'
),
'IMLOG2' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::IMLOG2' ,
'argumentCount' => '1'
),
'IMPOWER' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::IMPOWER' ,
'argumentCount' => '2'
),
'IMPRODUCT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::IMPRODUCT' ,
'argumentCount' => '1+'
),
'IMREAL' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::IMREAL' ,
'argumentCount' => '1'
),
'IMSIN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::IMSIN' ,
'argumentCount' => '1'
),
'IMSQRT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::IMSQRT' ,
'argumentCount' => '1'
),
'IMSUB' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::IMSUB' ,
'argumentCount' => '2'
),
'IMSUM' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::IMSUM' ,
'argumentCount' => '1+'
),
'INDEX' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOOKUP_AND_REFERENCE ,
'functionCall' => 'PHPExcel_Calculation_LookupRef::INDEX' ,
'argumentCount' => '1-4'
),
'INDIRECT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOOKUP_AND_REFERENCE ,
'functionCall' => 'PHPExcel_Calculation_LookupRef::INDIRECT' ,
'argumentCount' => '1,2' ,
2015-05-13 16:00:22 +00:00
'passCellReference' => true
2015-05-12 23:40:55 +00:00
),
'INFO' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_INFORMATION ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '1'
),
'INT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::INT' ,
'argumentCount' => '1'
),
'INTERCEPT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::INTERCEPT' ,
'argumentCount' => '2'
),
'INTRATE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::INTRATE' ,
'argumentCount' => '4,5'
),
'IPMT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::IPMT' ,
'argumentCount' => '4-6'
),
'IRR' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::IRR' ,
'argumentCount' => '1,2'
),
'ISBLANK' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_INFORMATION ,
'functionCall' => 'PHPExcel_Calculation_Functions::IS_BLANK' ,
'argumentCount' => '1'
),
'ISERR' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_INFORMATION ,
'functionCall' => 'PHPExcel_Calculation_Functions::IS_ERR' ,
'argumentCount' => '1'
),
'ISERROR' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_INFORMATION ,
'functionCall' => 'PHPExcel_Calculation_Functions::IS_ERROR' ,
'argumentCount' => '1'
),
'ISEVEN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_INFORMATION ,
'functionCall' => 'PHPExcel_Calculation_Functions::IS_EVEN' ,
'argumentCount' => '1'
),
'ISLOGICAL' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_INFORMATION ,
'functionCall' => 'PHPExcel_Calculation_Functions::IS_LOGICAL' ,
'argumentCount' => '1'
),
'ISNA' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_INFORMATION ,
'functionCall' => 'PHPExcel_Calculation_Functions::IS_NA' ,
'argumentCount' => '1'
),
'ISNONTEXT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_INFORMATION ,
'functionCall' => 'PHPExcel_Calculation_Functions::IS_NONTEXT' ,
'argumentCount' => '1'
),
'ISNUMBER' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_INFORMATION ,
'functionCall' => 'PHPExcel_Calculation_Functions::IS_NUMBER' ,
'argumentCount' => '1'
),
'ISODD' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_INFORMATION ,
'functionCall' => 'PHPExcel_Calculation_Functions::IS_ODD' ,
'argumentCount' => '1'
),
'ISPMT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::ISPMT' ,
'argumentCount' => '4'
),
'ISREF' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_INFORMATION ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '1'
),
'ISTEXT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_INFORMATION ,
'functionCall' => 'PHPExcel_Calculation_Functions::IS_TEXT' ,
'argumentCount' => '1'
),
'JIS' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '1'
),
'KURT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::KURT' ,
'argumentCount' => '1+'
),
'LARGE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::LARGE' ,
'argumentCount' => '2'
),
'LCM' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::LCM' ,
'argumentCount' => '1+'
),
'LEFT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::LEFT' ,
'argumentCount' => '1,2'
),
'LEFTB' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::LEFT' ,
'argumentCount' => '1,2'
),
'LEN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::STRINGLENGTH' ,
'argumentCount' => '1'
),
'LENB' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::STRINGLENGTH' ,
'argumentCount' => '1'
),
'LINEST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::LINEST' ,
'argumentCount' => '1-4'
),
'LN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'log' ,
'argumentCount' => '1'
),
'LOG' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::LOG_BASE' ,
'argumentCount' => '1,2'
),
'LOG10' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'log10' ,
'argumentCount' => '1'
),
'LOGEST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::LOGEST' ,
'argumentCount' => '1-4'
),
'LOGINV' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::LOGINV' ,
'argumentCount' => '3'
),
'LOGNORMDIST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::LOGNORMDIST' ,
'argumentCount' => '3'
),
'LOOKUP' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOOKUP_AND_REFERENCE ,
'functionCall' => 'PHPExcel_Calculation_LookupRef::LOOKUP' ,
'argumentCount' => '2,3'
),
'LOWER' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::LOWERCASE' ,
'argumentCount' => '1'
),
'MATCH' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOOKUP_AND_REFERENCE ,
'functionCall' => 'PHPExcel_Calculation_LookupRef::MATCH' ,
'argumentCount' => '2,3'
),
'MAX' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::MAX' ,
'argumentCount' => '1+'
),
'MAXA' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::MAXA' ,
'argumentCount' => '1+'
),
'MAXIF' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::MAXIF' ,
'argumentCount' => '2+'
),
'MDETERM' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::MDETERM' ,
'argumentCount' => '1'
),
'MDURATION' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '5,6'
),
'MEDIAN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::MEDIAN' ,
'argumentCount' => '1+'
),
'MEDIANIF' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '2+'
),
'MID' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::MID' ,
'argumentCount' => '3'
),
'MIDB' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::MID' ,
'argumentCount' => '3'
),
'MIN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::MIN' ,
'argumentCount' => '1+'
),
'MINA' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::MINA' ,
'argumentCount' => '1+'
),
'MINIF' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::MINIF' ,
'argumentCount' => '2+'
),
'MINUTE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::MINUTEOFHOUR' ,
'argumentCount' => '1'
),
'MINVERSE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::MINVERSE' ,
'argumentCount' => '1'
),
'MIRR' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::MIRR' ,
'argumentCount' => '3'
),
'MMULT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::MMULT' ,
'argumentCount' => '2'
),
'MOD' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::MOD' ,
'argumentCount' => '2'
),
'MODE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::MODE' ,
'argumentCount' => '1+'
),
'MONTH' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::MONTHOFYEAR' ,
'argumentCount' => '1'
),
'MROUND' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::MROUND' ,
'argumentCount' => '2'
),
'MULTINOMIAL' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::MULTINOMIAL' ,
'argumentCount' => '1+'
),
'N' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_INFORMATION ,
'functionCall' => 'PHPExcel_Calculation_Functions::N' ,
'argumentCount' => '1'
),
'NA' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_INFORMATION ,
'functionCall' => 'PHPExcel_Calculation_Functions::NA' ,
'argumentCount' => '0'
),
'NEGBINOMDIST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::NEGBINOMDIST' ,
'argumentCount' => '3'
),
'NETWORKDAYS' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::NETWORKDAYS' ,
'argumentCount' => '2+'
),
'NOMINAL' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::NOMINAL' ,
'argumentCount' => '2'
),
'NORMDIST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::NORMDIST' ,
'argumentCount' => '4'
),
'NORMINV' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::NORMINV' ,
'argumentCount' => '3'
),
'NORMSDIST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::NORMSDIST' ,
'argumentCount' => '1'
),
'NORMSINV' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::NORMSINV' ,
'argumentCount' => '1'
),
'NOT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOGICAL ,
'functionCall' => 'PHPExcel_Calculation_Logical::NOT' ,
'argumentCount' => '1'
),
'NOW' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::DATETIMENOW' ,
'argumentCount' => '0'
),
'NPER' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::NPER' ,
'argumentCount' => '3-5'
),
'NPV' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::NPV' ,
'argumentCount' => '2+'
),
'OCT2BIN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::OCTTOBIN' ,
'argumentCount' => '1,2'
),
'OCT2DEC' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::OCTTODEC' ,
'argumentCount' => '1'
),
'OCT2HEX' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_ENGINEERING ,
'functionCall' => 'PHPExcel_Calculation_Engineering::OCTTOHEX' ,
'argumentCount' => '1,2'
),
'ODD' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::ODD' ,
'argumentCount' => '1'
),
'ODDFPRICE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '8,9'
),
'ODDFYIELD' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '8,9'
),
'ODDLPRICE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '7,8'
),
'ODDLYIELD' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '7,8'
),
'OFFSET' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOOKUP_AND_REFERENCE ,
'functionCall' => 'PHPExcel_Calculation_LookupRef::OFFSET' ,
'argumentCount' => '3,5' ,
2015-05-13 16:00:22 +00:00
'passCellReference' => true ,
'passByReference' => array ( true )
2015-05-12 23:40:55 +00:00
),
'OR' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOGICAL ,
'functionCall' => 'PHPExcel_Calculation_Logical::LOGICAL_OR' ,
'argumentCount' => '1+'
),
'PEARSON' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::CORREL' ,
'argumentCount' => '2'
),
'PERCENTILE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::PERCENTILE' ,
'argumentCount' => '2'
),
'PERCENTRANK' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::PERCENTRANK' ,
'argumentCount' => '2,3'
),
'PERMUT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::PERMUT' ,
'argumentCount' => '2'
),
'PHONETIC' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '1'
),
'PI' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'pi' ,
'argumentCount' => '0'
),
'PMT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::PMT' ,
'argumentCount' => '3-5'
),
'POISSON' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::POISSON' ,
'argumentCount' => '3'
),
'POWER' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::POWER' ,
'argumentCount' => '2'
),
'PPMT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::PPMT' ,
'argumentCount' => '4-6'
),
'PRICE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::PRICE' ,
'argumentCount' => '6,7'
),
'PRICEDISC' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::PRICEDISC' ,
'argumentCount' => '4,5'
),
'PRICEMAT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::PRICEMAT' ,
'argumentCount' => '5,6'
),
'PROB' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '3,4'
),
'PRODUCT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::PRODUCT' ,
'argumentCount' => '1+'
),
'PROPER' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::PROPERCASE' ,
'argumentCount' => '1'
),
'PV' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::PV' ,
'argumentCount' => '3-5'
),
'QUARTILE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::QUARTILE' ,
'argumentCount' => '2'
),
'QUOTIENT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::QUOTIENT' ,
'argumentCount' => '2'
),
'RADIANS' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'deg2rad' ,
'argumentCount' => '1'
),
'RAND' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::RAND' ,
'argumentCount' => '0'
),
'RANDBETWEEN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::RAND' ,
'argumentCount' => '2'
),
'RANK' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::RANK' ,
'argumentCount' => '2,3'
),
'RATE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::RATE' ,
'argumentCount' => '3-6'
),
'RECEIVED' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::RECEIVED' ,
'argumentCount' => '4-5'
),
'REPLACE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::REPLACE' ,
'argumentCount' => '4'
),
'REPLACEB' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::REPLACE' ,
'argumentCount' => '4'
),
'REPT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'str_repeat' ,
'argumentCount' => '2'
),
'RIGHT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::RIGHT' ,
'argumentCount' => '1,2'
),
'RIGHTB' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::RIGHT' ,
'argumentCount' => '1,2'
),
'ROMAN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::ROMAN' ,
'argumentCount' => '1,2'
),
'ROUND' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'round' ,
'argumentCount' => '2'
),
'ROUNDDOWN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::ROUNDDOWN' ,
'argumentCount' => '2'
),
'ROUNDUP' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::ROUNDUP' ,
'argumentCount' => '2'
),
'ROW' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOOKUP_AND_REFERENCE ,
'functionCall' => 'PHPExcel_Calculation_LookupRef::ROW' ,
'argumentCount' => '-1' ,
2015-05-13 16:00:22 +00:00
'passByReference' => array ( true )
2015-05-12 23:40:55 +00:00
),
'ROWS' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOOKUP_AND_REFERENCE ,
'functionCall' => 'PHPExcel_Calculation_LookupRef::ROWS' ,
'argumentCount' => '1'
),
'RSQ' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::RSQ' ,
'argumentCount' => '2'
),
'RTD' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOOKUP_AND_REFERENCE ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '1+'
),
'SEARCH' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::SEARCHINSENSITIVE' ,
'argumentCount' => '2,3'
),
'SEARCHB' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::SEARCHINSENSITIVE' ,
'argumentCount' => '2,3'
),
'SECOND' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::SECONDOFMINUTE' ,
'argumentCount' => '1'
),
'SERIESSUM' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::SERIESSUM' ,
'argumentCount' => '4'
),
'SIGN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::SIGN' ,
'argumentCount' => '1'
),
'SIN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'sin' ,
'argumentCount' => '1'
),
'SINH' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'sinh' ,
'argumentCount' => '1'
),
'SKEW' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::SKEW' ,
'argumentCount' => '1+'
),
'SLN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::SLN' ,
'argumentCount' => '3'
),
'SLOPE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::SLOPE' ,
'argumentCount' => '2'
),
'SMALL' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::SMALL' ,
'argumentCount' => '2'
),
'SQRT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'sqrt' ,
'argumentCount' => '1'
),
'SQRTPI' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::SQRTPI' ,
'argumentCount' => '1'
),
'STANDARDIZE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::STANDARDIZE' ,
'argumentCount' => '3'
),
'STDEV' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::STDEV' ,
'argumentCount' => '1+'
),
'STDEVA' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::STDEVA' ,
'argumentCount' => '1+'
),
'STDEVP' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::STDEVP' ,
'argumentCount' => '1+'
),
'STDEVPA' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::STDEVPA' ,
'argumentCount' => '1+'
),
'STEYX' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::STEYX' ,
'argumentCount' => '2'
),
'SUBSTITUTE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::SUBSTITUTE' ,
'argumentCount' => '3,4'
),
'SUBTOTAL' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::SUBTOTAL' ,
'argumentCount' => '2+'
),
'SUM' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::SUM' ,
'argumentCount' => '1+'
),
'SUMIF' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::SUMIF' ,
'argumentCount' => '2,3'
),
'SUMIFS' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '?'
),
'SUMPRODUCT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::SUMPRODUCT' ,
'argumentCount' => '1+'
),
'SUMSQ' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::SUMSQ' ,
'argumentCount' => '1+'
),
'SUMX2MY2' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::SUMX2MY2' ,
'argumentCount' => '2'
),
'SUMX2PY2' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::SUMX2PY2' ,
'argumentCount' => '2'
),
'SUMXMY2' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::SUMXMY2' ,
'argumentCount' => '2'
),
'SYD' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::SYD' ,
'argumentCount' => '4'
),
'T' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::RETURNSTRING' ,
'argumentCount' => '1'
),
'TAN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'tan' ,
'argumentCount' => '1'
),
'TANH' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'tanh' ,
'argumentCount' => '1'
),
'TBILLEQ' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::TBILLEQ' ,
'argumentCount' => '3'
),
'TBILLPRICE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::TBILLPRICE' ,
'argumentCount' => '3'
),
'TBILLYIELD' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::TBILLYIELD' ,
'argumentCount' => '3'
),
'TDIST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::TDIST' ,
'argumentCount' => '3'
),
'TEXT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::TEXTFORMAT' ,
'argumentCount' => '2'
),
'TIME' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::TIME' ,
'argumentCount' => '3'
),
'TIMEVALUE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::TIMEVALUE' ,
'argumentCount' => '1'
),
'TINV' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::TINV' ,
'argumentCount' => '2'
),
'TODAY' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::DATENOW' ,
'argumentCount' => '0'
),
'TRANSPOSE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOOKUP_AND_REFERENCE ,
'functionCall' => 'PHPExcel_Calculation_LookupRef::TRANSPOSE' ,
'argumentCount' => '1'
),
'TREND' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::TREND' ,
'argumentCount' => '1-4'
),
'TRIM' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::TRIMSPACES' ,
'argumentCount' => '1'
),
'TRIMMEAN' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::TRIMMEAN' ,
'argumentCount' => '2'
),
'TRUE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOGICAL ,
'functionCall' => 'PHPExcel_Calculation_Logical::TRUE' ,
'argumentCount' => '0'
),
'TRUNC' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_MATH_AND_TRIG ,
'functionCall' => 'PHPExcel_Calculation_MathTrig::TRUNC' ,
'argumentCount' => '1,2'
),
'TTEST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '4'
),
'TYPE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_INFORMATION ,
'functionCall' => 'PHPExcel_Calculation_Functions::TYPE' ,
'argumentCount' => '1'
),
'UPPER' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::UPPERCASE' ,
'argumentCount' => '1'
),
'USDOLLAR' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '2'
),
'VALUE' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_TEXT_AND_DATA ,
'functionCall' => 'PHPExcel_Calculation_TextData::VALUE' ,
'argumentCount' => '1'
),
'VAR' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::VARFunc' ,
'argumentCount' => '1+'
),
'VARA' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::VARA' ,
'argumentCount' => '1+'
),
'VARP' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::VARP' ,
'argumentCount' => '1+'
),
'VARPA' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::VARPA' ,
'argumentCount' => '1+'
),
'VDB' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '5-7'
),
'VERSION' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_INFORMATION ,
'functionCall' => 'PHPExcel_Calculation_Functions::VERSION' ,
'argumentCount' => '0'
),
'VLOOKUP' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_LOOKUP_AND_REFERENCE ,
'functionCall' => 'PHPExcel_Calculation_LookupRef::VLOOKUP' ,
'argumentCount' => '3,4'
),
'WEEKDAY' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::DAYOFWEEK' ,
'argumentCount' => '1,2'
),
'WEEKNUM' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::WEEKOFYEAR' ,
'argumentCount' => '1,2'
),
'WEIBULL' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::WEIBULL' ,
'argumentCount' => '4'
),
'WORKDAY' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::WORKDAY' ,
'argumentCount' => '2+'
),
'XIRR' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::XIRR' ,
'argumentCount' => '2,3'
),
'XNPV' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::XNPV' ,
'argumentCount' => '3'
),
'YEAR' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::YEAR' ,
'argumentCount' => '1'
),
'YEARFRAC' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_DATE_AND_TIME ,
'functionCall' => 'PHPExcel_Calculation_DateTime::YEARFRAC' ,
'argumentCount' => '2,3'
),
'YIELD' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY' ,
'argumentCount' => '6,7'
),
'YIELDDISC' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::YIELDDISC' ,
'argumentCount' => '4,5'
),
'YIELDMAT' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_FINANCIAL ,
'functionCall' => 'PHPExcel_Calculation_Financial::YIELDMAT' ,
'argumentCount' => '5,6'
),
'ZTEST' => array ( 'category' => PHPExcel_Calculation_Function :: CATEGORY_STATISTICAL ,
'functionCall' => 'PHPExcel_Calculation_Statistical::ZTEST' ,
'argumentCount' => '2-3'
)
);
// Internal functions used for special control purposes
private static $_controlFunctions = array (
2015-05-13 16:00:22 +00:00
'MKMATRIX' => array (
'argumentCount' => '*' ,
'functionCall' => 'self::_mkMatrix'
)
);
2015-05-12 23:40:55 +00:00
2015-05-13 16:00:22 +00:00
private function __construct ( PHPExcel $workbook = null )
{
2015-05-12 23:40:55 +00:00
$setPrecision = ( PHP_INT_SIZE == 4 ) ? 14 : 16 ;
$this -> _savedPrecision = ini_get ( 'precision' );
if ( $this -> _savedPrecision < $setPrecision ) {
2015-05-13 16:00:22 +00:00
ini_set ( 'precision' , $setPrecision );
2015-05-12 23:40:55 +00:00
}
$this -> delta = 1 * pow ( 10 , - $setPrecision );
2015-05-13 16:00:22 +00:00
if ( $workbook !== null ) {
2015-05-12 23:40:55 +00:00
self :: $_workbookSets [ $workbook -> getID ()] = $this ;
}
$this -> _workbook = $workbook ;
$this -> _cyclicReferenceStack = new PHPExcel_CalcEngine_CyclicReferenceStack ();
$this -> _debugLog = new PHPExcel_CalcEngine_Logger ( $this -> _cyclicReferenceStack );
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
2015-05-13 16:00:22 +00:00
public function __destruct ()
{
2015-05-12 23:40:55 +00:00
if ( $this -> _savedPrecision != ini_get ( 'precision' )) {
2015-05-13 16:00:22 +00:00
ini_set ( 'precision' , $this -> _savedPrecision );
2015-05-12 23:40:55 +00:00
}
}
2015-05-13 16:00:22 +00:00
private static function _loadLocales ()
{
2015-05-12 23:40:55 +00:00
$localeFileDirectory = PHPEXCEL_ROOT . 'PHPExcel/locale/' ;
2015-05-13 16:00:22 +00:00
foreach ( glob ( $localeFileDirectory . '/*' , GLOB_ONLYDIR ) as $filename ) {
$filename = substr ( $filename , strlen ( $localeFileDirectory ) + 1 );
2015-05-12 23:40:55 +00:00
if ( $filename != 'en' ) {
self :: $_validLocaleLanguages [] = $filename ;
}
}
}
/**
* Get an instance of this class
*
* @ access public
* @ param PHPExcel $workbook Injected workbook for working with a PHPExcel object ,
* or NULL to create a standalone claculation engine
* @ return PHPExcel_Calculation
*/
2015-05-13 16:00:22 +00:00
public static function getInstance ( PHPExcel $workbook = null )
{
if ( $workbook !== null ) {
2015-05-12 23:40:55 +00:00
if ( isset ( self :: $_workbookSets [ $workbook -> getID ()])) {
return self :: $_workbookSets [ $workbook -> getID ()];
}
return new PHPExcel_Calculation ( $workbook );
}
2015-05-13 16:00:22 +00:00
if ( ! isset ( self :: $_instance ) || ( self :: $_instance === null )) {
2015-05-12 23:40:55 +00:00
self :: $_instance = new PHPExcel_Calculation ();
}
return self :: $_instance ;
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Unset an instance of this class
*
* @ access public
* @ param PHPExcel $workbook Injected workbook identifying the instance to unset
*/
2015-05-13 16:00:22 +00:00
public static function unsetInstance ( PHPExcel $workbook = null )
{
if ( $workbook !== null ) {
2015-05-12 23:40:55 +00:00
if ( isset ( self :: $_workbookSets [ $workbook -> getID ()])) {
unset ( self :: $_workbookSets [ $workbook -> getID ()]);
}
}
}
/**
* Flush the calculation cache for any existing instance of this class
* but only if a PHPExcel_Calculation instance exists
*
* @ access public
* @ return null
*/
2015-05-13 16:00:22 +00:00
public function flushInstance ()
{
2015-05-12 23:40:55 +00:00
$this -> clearCalculationCache ();
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Get the debuglog for this claculation engine instance
*
* @ access public
* @ return PHPExcel_CalcEngine_Logger
*/
2015-05-13 16:00:22 +00:00
public function getDebugLog ()
{
2015-05-12 23:40:55 +00:00
return $this -> _debugLog ;
2013-02-04 17:26:27 +00:00
}
2010-08-26 19:14:53 +00:00
2015-05-12 23:40:55 +00:00
/**
* __clone implementation . Cloning should not be allowed in a Singleton !
*
* @ access public
* @ throws PHPExcel_Calculation_Exception
*/
2015-05-13 16:00:22 +00:00
final public function __clone ()
{
throw new PHPExcel_Calculation_Exception ( 'Cloning the calculation engine is not allowed!' );
}
2015-05-12 23:40:55 +00:00
/**
* Return the locale - specific translation of TRUE
*
* @ access public
* @ return string locale - specific translation of TRUE
*/
2015-05-13 16:00:22 +00:00
public static function getTRUE ()
{
2015-05-12 23:40:55 +00:00
return self :: $_localeBoolean [ 'TRUE' ];
}
/**
* Return the locale - specific translation of FALSE
*
* @ access public
* @ return string locale - specific translation of FALSE
*/
2015-05-13 16:00:22 +00:00
public static function getFALSE ()
{
2015-05-12 23:40:55 +00:00
return self :: $_localeBoolean [ 'FALSE' ];
}
/**
* Set the Array Return Type ( Array or Value of first element in the array )
*
* @ access public
* @ param string $returnType Array return type
* @ return boolean Success or failure
*/
2015-05-13 16:00:22 +00:00
public static function setArrayReturnType ( $returnType )
{
2015-05-12 23:40:55 +00:00
if (( $returnType == self :: RETURN_ARRAY_AS_VALUE ) ||
( $returnType == self :: RETURN_ARRAY_AS_ERROR ) ||
( $returnType == self :: RETURN_ARRAY_AS_ARRAY )) {
self :: $returnArrayAsType = $returnType ;
2015-05-13 16:00:22 +00:00
return true ;
2015-05-12 23:40:55 +00:00
}
2015-05-13 16:00:22 +00:00
return false ;
}
2015-05-12 23:40:55 +00:00
/**
* Return the Array Return Type ( Array or Value of first element in the array )
*
* @ access public
* @ return string $returnType Array return type
*/
2015-05-13 16:00:22 +00:00
public static function getArrayReturnType ()
{
2015-05-12 23:40:55 +00:00
return self :: $returnArrayAsType ;
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Is calculation caching enabled ?
*
* @ access public
* @ return boolean
*/
2015-05-13 16:00:22 +00:00
public function getCalculationCacheEnabled ()
{
2015-05-12 23:40:55 +00:00
return $this -> _calculationCacheEnabled ;
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Enable / disable calculation cache
*
* @ access public
* @ param boolean $pValue
*/
2015-05-13 16:00:22 +00:00
public function setCalculationCacheEnabled ( $pValue = true )
{
2015-05-12 23:40:55 +00:00
$this -> _calculationCacheEnabled = $pValue ;
$this -> clearCalculationCache ();
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Enable calculation cache
*/
2015-05-13 16:00:22 +00:00
public function enableCalculationCache ()
{
$this -> setCalculationCacheEnabled ( true );
}
2015-05-12 23:40:55 +00:00
/**
* Disable calculation cache
*/
2015-05-13 16:00:22 +00:00
public function disableCalculationCache ()
{
$this -> setCalculationCacheEnabled ( false );
}
2015-05-12 23:40:55 +00:00
/**
* Clear calculation cache
*/
2015-05-13 16:00:22 +00:00
public function clearCalculationCache ()
{
2015-05-12 23:40:55 +00:00
$this -> _calculationCache = array ();
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Clear calculation cache for a specified worksheet
*
* @ param string $worksheetName
*/
2015-05-13 16:00:22 +00:00
public function clearCalculationCacheForWorksheet ( $worksheetName )
{
2015-05-12 23:40:55 +00:00
if ( isset ( $this -> _calculationCache [ $worksheetName ])) {
unset ( $this -> _calculationCache [ $worksheetName ]);
}
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Rename calculation cache for a specified worksheet
*
* @ param string $fromWorksheetName
* @ param string $toWorksheetName
*/
2015-05-13 16:00:22 +00:00
public function renameCalculationCacheForWorksheet ( $fromWorksheetName , $toWorksheetName )
{
2015-05-12 23:40:55 +00:00
if ( isset ( $this -> _calculationCache [ $fromWorksheetName ])) {
$this -> _calculationCache [ $toWorksheetName ] = & $this -> _calculationCache [ $fromWorksheetName ];
unset ( $this -> _calculationCache [ $fromWorksheetName ]);
}
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Get the currently defined locale code
*
* @ return string
*/
2015-05-13 16:00:22 +00:00
public function getLocale ()
{
2015-05-12 23:40:55 +00:00
return self :: $_localeLanguage ;
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Set the locale code
*
* @ param string $locale The locale to use for formula translation
* @ return boolean
*/
2015-05-13 16:00:22 +00:00
public function setLocale ( $locale = 'en_us' )
{
2015-05-12 23:40:55 +00:00
// Identify our locale and language
$language = $locale = strtolower ( $locale );
2015-05-13 16:00:22 +00:00
if ( strpos ( $locale , '_' ) !== false ) {
list ( $language ) = explode ( '_' , $locale );
2015-05-12 23:40:55 +00:00
}
2015-05-13 16:00:22 +00:00
if ( count ( self :: $_validLocaleLanguages ) == 1 ) {
2015-05-12 23:40:55 +00:00
self :: _loadLocales ();
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
// Test whether we have any language data for this language (any locale)
2015-05-13 16:00:22 +00:00
if ( in_array ( $language , self :: $_validLocaleLanguages )) {
2015-05-12 23:40:55 +00:00
// initialise language/locale settings
self :: $_localeFunctions = array ();
self :: $_localeArgumentSeparator = ',' ;
self :: $_localeBoolean = array ( 'TRUE' => 'TRUE' , 'FALSE' => 'FALSE' , 'NULL' => 'NULL' );
// Default is English, if user isn't requesting english, then read the necessary data from the locale files
if ( $locale != 'en_us' ) {
// Search for a file with a list of function names for locale
2015-05-13 16:00:22 +00:00
$functionNamesFile = PHPEXCEL_ROOT . 'PHPExcel' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR . str_replace ( '_' , DIRECTORY_SEPARATOR , $locale ) . DIRECTORY_SEPARATOR . 'functions' ;
2015-05-12 23:40:55 +00:00
if ( ! file_exists ( $functionNamesFile )) {
// If there isn't a locale specific function file, look for a language specific function file
$functionNamesFile = PHPEXCEL_ROOT . 'PHPExcel' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR . $language . DIRECTORY_SEPARATOR . 'functions' ;
if ( ! file_exists ( $functionNamesFile )) {
2015-05-13 16:00:22 +00:00
return false ;
2015-05-12 23:40:55 +00:00
}
}
// Retrieve the list of locale or language specific function names
2015-05-13 16:00:22 +00:00
$localeFunctions = file ( $functionNamesFile , FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES );
2015-05-12 23:40:55 +00:00
foreach ( $localeFunctions as $localeFunction ) {
2015-05-13 16:00:22 +00:00
list ( $localeFunction ) = explode ( '##' , $localeFunction ); // Strip out comments
if ( strpos ( $localeFunction , '=' ) !== false ) {
list ( $fName , $lfName ) = explode ( '=' , $localeFunction );
2015-05-12 23:40:55 +00:00
$fName = trim ( $fName );
$lfName = trim ( $lfName );
if (( isset ( self :: $_PHPExcelFunctions [ $fName ])) && ( $lfName != '' ) && ( $fName != $lfName )) {
self :: $_localeFunctions [ $fName ] = $lfName ;
}
}
}
// Default the TRUE and FALSE constants to the locale names of the TRUE() and FALSE() functions
2015-05-13 16:00:22 +00:00
if ( isset ( self :: $_localeFunctions [ 'TRUE' ])) {
self :: $_localeBoolean [ 'TRUE' ] = self :: $_localeFunctions [ 'TRUE' ];
}
if ( isset ( self :: $_localeFunctions [ 'FALSE' ])) {
self :: $_localeBoolean [ 'FALSE' ] = self :: $_localeFunctions [ 'FALSE' ];
}
2015-05-12 23:40:55 +00:00
2015-05-13 16:00:22 +00:00
$configFile = PHPEXCEL_ROOT . 'PHPExcel' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR . str_replace ( '_' , DIRECTORY_SEPARATOR , $locale ) . DIRECTORY_SEPARATOR . 'config' ;
2015-05-12 23:40:55 +00:00
if ( ! file_exists ( $configFile )) {
$configFile = PHPEXCEL_ROOT . 'PHPExcel' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR . $language . DIRECTORY_SEPARATOR . 'config' ;
}
if ( file_exists ( $configFile )) {
2015-05-13 16:00:22 +00:00
$localeSettings = file ( $configFile , FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES );
2015-05-12 23:40:55 +00:00
foreach ( $localeSettings as $localeSetting ) {
2015-05-13 16:00:22 +00:00
list ( $localeSetting ) = explode ( '##' , $localeSetting ); // Strip out comments
if ( strpos ( $localeSetting , '=' ) !== false ) {
list ( $settingName , $settingValue ) = explode ( '=' , $localeSetting );
2015-05-12 23:40:55 +00:00
$settingName = strtoupper ( trim ( $settingName ));
switch ( $settingName ) {
2015-05-13 16:00:22 +00:00
case 'ARGUMENTSEPARATOR' :
2015-05-12 23:40:55 +00:00
self :: $_localeArgumentSeparator = trim ( $settingValue );
break ;
}
}
}
}
}
self :: $functionReplaceFromExcel = self :: $functionReplaceToExcel =
2015-05-13 16:00:22 +00:00
self :: $functionReplaceFromLocale = self :: $functionReplaceToLocale = null ;
2015-05-12 23:40:55 +00:00
self :: $_localeLanguage = $locale ;
2015-05-13 16:00:22 +00:00
return true ;
2015-05-12 23:40:55 +00:00
}
2015-05-13 16:00:22 +00:00
return false ;
}
2015-05-12 23:40:55 +00:00
2015-05-13 16:00:22 +00:00
public static function _translateSeparator ( $fromSeparator , $toSeparator , $formula , & $inBraces )
{
2015-05-12 23:40:55 +00:00
$strlen = mb_strlen ( $formula );
for ( $i = 0 ; $i < $strlen ; ++ $i ) {
2015-05-13 16:00:22 +00:00
$chr = mb_substr ( $formula , $i , 1 );
2015-05-12 23:40:55 +00:00
switch ( $chr ) {
2015-05-13 16:00:22 +00:00
case '{' :
$inBraces = true ;
break ;
case '}' :
$inBraces = false ;
break ;
case $fromSeparator :
if ( ! $inBraces ) {
$formula = mb_substr ( $formula , 0 , $i ) . $toSeparator . mb_substr ( $formula , $i + 1 );
}
2015-05-12 23:40:55 +00:00
}
}
return $formula ;
}
2015-05-13 16:00:22 +00:00
private static function _translateFormula ( $from , $to , $formula , $fromSeparator , $toSeparator )
{
2015-05-12 23:40:55 +00:00
// Convert any Excel function names to the required language
if ( self :: $_localeLanguage !== 'en_us' ) {
2015-05-13 16:00:22 +00:00
$inBraces = false ;
2015-05-12 23:40:55 +00:00
// If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators
2015-05-13 16:00:22 +00:00
if ( strpos ( $formula , '"' ) !== false ) {
2015-05-12 23:40:55 +00:00
// So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded
// the formula
2015-05-13 16:00:22 +00:00
$temp = explode ( '"' , $formula );
$i = false ;
foreach ( $temp as & $value ) {
2015-05-12 23:40:55 +00:00
// Only count/replace in alternating array entries
if ( $i = ! $i ) {
2015-05-13 16:00:22 +00:00
$value = preg_replace ( $from , $to , $value );
$value = self :: _translateSeparator ( $fromSeparator , $toSeparator , $value , $inBraces );
2015-05-12 23:40:55 +00:00
}
}
unset ( $value );
// Then rebuild the formula string
2015-05-13 16:00:22 +00:00
$formula = implode ( '"' , $temp );
2015-05-12 23:40:55 +00:00
} else {
// If there's no quoted strings, then we do a simple count/replace
2015-05-13 16:00:22 +00:00
$formula = preg_replace ( $from , $to , $formula );
$formula = self :: _translateSeparator ( $fromSeparator , $toSeparator , $formula , $inBraces );
2015-05-12 23:40:55 +00:00
}
}
return $formula ;
}
2015-05-13 16:00:22 +00:00
private static $functionReplaceFromExcel = null ;
private static $functionReplaceToLocale = null ;
2015-05-12 23:40:55 +00:00
2015-05-13 16:00:22 +00:00
public function _translateFormulaToLocale ( $formula )
{
if ( self :: $functionReplaceFromExcel === null ) {
2015-05-12 23:40:55 +00:00
self :: $functionReplaceFromExcel = array ();
2015-05-13 16:00:22 +00:00
foreach ( array_keys ( self :: $_localeFunctions ) as $excelFunctionName ) {
2015-05-12 23:40:55 +00:00
self :: $functionReplaceFromExcel [] = '/(@?[^\w\.])' . preg_quote ( $excelFunctionName ) . '([\s]*\()/Ui' ;
}
2015-05-13 16:00:22 +00:00
foreach ( array_keys ( self :: $_localeBoolean ) as $excelBoolean ) {
2015-05-12 23:40:55 +00:00
self :: $functionReplaceFromExcel [] = '/(@?[^\w\.])' . preg_quote ( $excelBoolean ) . '([^\w\.])/Ui' ;
}
}
2015-05-13 16:00:22 +00:00
if ( self :: $functionReplaceToLocale === null ) {
2015-05-12 23:40:55 +00:00
self :: $functionReplaceToLocale = array ();
2015-05-13 16:00:22 +00:00
foreach ( array_values ( self :: $_localeFunctions ) as $localeFunctionName ) {
2015-05-12 23:40:55 +00:00
self :: $functionReplaceToLocale [] = '$1' . trim ( $localeFunctionName ) . '$2' ;
}
2015-05-13 16:00:22 +00:00
foreach ( array_values ( self :: $_localeBoolean ) as $localeBoolean ) {
2015-05-12 23:40:55 +00:00
self :: $functionReplaceToLocale [] = '$1' . trim ( $localeBoolean ) . '$2' ;
}
}
2015-05-13 16:00:22 +00:00
return self :: _translateFormula ( self :: $functionReplaceFromExcel , self :: $functionReplaceToLocale , $formula , ',' , self :: $_localeArgumentSeparator );
}
2015-05-12 23:40:55 +00:00
2015-05-13 16:00:22 +00:00
private static $functionReplaceFromLocale = null ;
private static $functionReplaceToExcel = null ;
2015-05-12 23:40:55 +00:00
2015-05-13 16:00:22 +00:00
public function _translateFormulaToEnglish ( $formula )
{
if ( self :: $functionReplaceFromLocale === null ) {
2015-05-12 23:40:55 +00:00
self :: $functionReplaceFromLocale = array ();
2015-05-13 16:00:22 +00:00
foreach ( array_values ( self :: $_localeFunctions ) as $localeFunctionName ) {
2015-05-12 23:40:55 +00:00
self :: $functionReplaceFromLocale [] = '/(@?[^\w\.])' . preg_quote ( $localeFunctionName ) . '([\s]*\()/Ui' ;
}
2015-05-13 16:00:22 +00:00
foreach ( array_values ( self :: $_localeBoolean ) as $excelBoolean ) {
2015-05-12 23:40:55 +00:00
self :: $functionReplaceFromLocale [] = '/(@?[^\w\.])' . preg_quote ( $excelBoolean ) . '([^\w\.])/Ui' ;
}
}
2015-05-13 16:00:22 +00:00
if ( self :: $functionReplaceToExcel === null ) {
2015-05-12 23:40:55 +00:00
self :: $functionReplaceToExcel = array ();
2015-05-13 16:00:22 +00:00
foreach ( array_keys ( self :: $_localeFunctions ) as $excelFunctionName ) {
2015-05-12 23:40:55 +00:00
self :: $functionReplaceToExcel [] = '$1' . trim ( $excelFunctionName ) . '$2' ;
}
2015-05-13 16:00:22 +00:00
foreach ( array_keys ( self :: $_localeBoolean ) as $excelBoolean ) {
2015-05-12 23:40:55 +00:00
self :: $functionReplaceToExcel [] = '$1' . trim ( $excelBoolean ) . '$2' ;
}
}
2015-05-13 16:00:22 +00:00
return self :: _translateFormula ( self :: $functionReplaceFromLocale , self :: $functionReplaceToExcel , $formula , self :: $_localeArgumentSeparator , ',' );
}
2015-05-12 23:40:55 +00:00
2015-05-13 16:00:22 +00:00
public static function _localeFunc ( $function )
{
2015-05-12 23:40:55 +00:00
if ( self :: $_localeLanguage !== 'en_us' ) {
2015-05-13 16:00:22 +00:00
$functionName = trim ( $function , '(' );
2015-05-12 23:40:55 +00:00
if ( isset ( self :: $_localeFunctions [ $functionName ])) {
$brace = ( $functionName != $function );
$function = self :: $_localeFunctions [ $functionName ];
2015-05-13 16:00:22 +00:00
if ( $brace ) {
$function .= '(' ;
}
2015-05-12 23:40:55 +00:00
}
}
return $function ;
}
/**
* Wrap string values in quotes
*
* @ param mixed $value
* @ return mixed
*/
2015-05-13 16:00:22 +00:00
public static function _wrapResult ( $value )
{
2015-05-12 23:40:55 +00:00
if ( is_string ( $value )) {
// Error values cannot be "wrapped"
if ( preg_match ( '/^' . self :: CALCULATION_REGEXP_ERROR . '$/i' , $value , $match )) {
// Return Excel errors "as is"
return $value ;
}
// Return strings wrapped in quotes
return '"' . $value . '"' ;
// Convert numeric errors to NaN error
2015-05-13 16:00:22 +00:00
} elseif (( is_float ( $value )) && (( is_nan ( $value )) || ( is_infinite ( $value )))) {
2015-05-12 23:40:55 +00:00
return PHPExcel_Calculation_Functions :: NaN ();
}
return $value ;
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Remove quotes used as a wrapper to identify string values
*
* @ param mixed $value
* @ return mixed
*/
2015-05-13 16:00:22 +00:00
public static function _unwrapResult ( $value )
{
2015-05-12 23:40:55 +00:00
if ( is_string ( $value )) {
2015-05-13 16:00:22 +00:00
if (( isset ( $value { 0 })) && ( $value { 0 } == '"' ) && ( substr ( $value , - 1 ) == '"' )) {
return substr ( $value , 1 , - 1 );
2015-05-12 23:40:55 +00:00
}
// Convert numeric errors to NaN error
2015-05-13 16:00:22 +00:00
} elseif (( is_float ( $value )) && (( is_nan ( $value )) || ( is_infinite ( $value )))) {
2015-05-12 23:40:55 +00:00
return PHPExcel_Calculation_Functions :: NaN ();
}
return $value ;
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Calculate cell value ( using formula from a cell ID )
* Retained for backward compatibility
*
* @ access public
* @ param PHPExcel_Cell $pCell Cell to calculate
* @ return mixed
* @ throws PHPExcel_Calculation_Exception
*/
2015-05-13 16:00:22 +00:00
public function calculate ( PHPExcel_Cell $pCell = null )
{
2015-05-12 23:40:55 +00:00
try {
return $this -> calculateCellValue ( $pCell );
} catch ( PHPExcel_Exception $e ) {
throw new PHPExcel_Calculation_Exception ( $e -> getMessage ());
}
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Calculate the value of a cell formula
*
* @ access public
* @ param PHPExcel_Cell $pCell Cell to calculate
* @ param Boolean $resetLog Flag indicating whether the debug log should be reset or not
* @ return mixed
* @ throws PHPExcel_Calculation_Exception
*/
2015-05-13 16:00:22 +00:00
public function calculateCellValue ( PHPExcel_Cell $pCell = null , $resetLog = true )
{
if ( $pCell === null ) {
return null ;
2015-05-12 23:40:55 +00:00
}
$returnArrayAsType = self :: $returnArrayAsType ;
if ( $resetLog ) {
// Initialise the logging settings if requested
$this -> formulaError = null ;
$this -> _debugLog -> clearLog ();
$this -> _cyclicReferenceStack -> clear ();
$this -> _cyclicFormulaCount = 1 ;
self :: $returnArrayAsType = self :: RETURN_ARRAY_AS_ARRAY ;
}
// Execute the calculation for the cell formula
2014-07-15 22:33:06 +00:00
$this -> _cellStack [] = array (
'sheet' => $pCell -> getWorksheet () -> getTitle (),
'cell' => $pCell -> getCoordinate (),
);
2015-05-12 23:40:55 +00:00
try {
$result = self :: _unwrapResult ( $this -> _calculateFormulaValue ( $pCell -> getValue (), $pCell -> getCoordinate (), $pCell ));
2014-07-15 22:33:06 +00:00
$cellAddress = array_pop ( $this -> _cellStack );
$this -> _workbook -> getSheetByName ( $cellAddress [ 'sheet' ]) -> getCell ( $cellAddress [ 'cell' ]);
2015-05-12 23:40:55 +00:00
} catch ( PHPExcel_Exception $e ) {
2014-07-15 22:33:06 +00:00
$cellAddress = array_pop ( $this -> _cellStack );
$this -> _workbook -> getSheetByName ( $cellAddress [ 'sheet' ]) -> getCell ( $cellAddress [ 'cell' ]);
2015-05-12 23:40:55 +00:00
throw new PHPExcel_Calculation_Exception ( $e -> getMessage ());
}
if (( is_array ( $result )) && ( self :: $returnArrayAsType != self :: RETURN_ARRAY_AS_ARRAY )) {
self :: $returnArrayAsType = $returnArrayAsType ;
$testResult = PHPExcel_Calculation_Functions :: flattenArray ( $result );
if ( self :: $returnArrayAsType == self :: RETURN_ARRAY_AS_ERROR ) {
return PHPExcel_Calculation_Functions :: VALUE ();
}
// If there's only a single cell in the array, then we allow it
if ( count ( $testResult ) != 1 ) {
// If keys are numeric, then it's a matrix result rather than a cell range result, so we permit it
$r = array_keys ( $result );
$r = array_shift ( $r );
2015-05-13 16:00:22 +00:00
if ( ! is_numeric ( $r )) {
return PHPExcel_Calculation_Functions :: VALUE ();
}
2015-05-12 23:40:55 +00:00
if ( is_array ( $result [ $r ])) {
$c = array_keys ( $result [ $r ]);
$c = array_shift ( $c );
if ( ! is_numeric ( $c )) {
return PHPExcel_Calculation_Functions :: VALUE ();
}
}
}
$result = array_shift ( $testResult );
}
self :: $returnArrayAsType = $returnArrayAsType ;
2015-05-13 16:00:22 +00:00
if ( $result === null ) {
2015-05-12 23:40:55 +00:00
return 0 ;
2015-05-13 16:00:22 +00:00
} elseif (( is_float ( $result )) && (( is_nan ( $result )) || ( is_infinite ( $result )))) {
2015-05-12 23:40:55 +00:00
return PHPExcel_Calculation_Functions :: NaN ();
}
return $result ;
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Validate and parse a formula string
*
* @ param string $formula Formula to parse
* @ return array
* @ throws PHPExcel_Calculation_Exception
*/
2015-05-13 16:00:22 +00:00
public function parseFormula ( $formula )
{
2015-05-12 23:40:55 +00:00
// Basic validation that this is indeed a formula
// We return an empty array if not
$formula = trim ( $formula );
2015-05-13 16:00:22 +00:00
if (( ! isset ( $formula { 0 })) || ( $formula { 0 } != '=' )) {
return array ();
}
$formula = ltrim ( substr ( $formula , 1 ));
if ( ! isset ( $formula { 0 })) {
return array ();
}
2015-05-12 23:40:55 +00:00
// Parse the formula and return the token stack
return $this -> _parseFormula ( $formula );
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Calculate the value of a formula
*
* @ param string $formula Formula to parse
* @ param string $cellID Address of the cell to calculate
* @ param PHPExcel_Cell $pCell Cell to calculate
* @ return mixed
* @ throws PHPExcel_Calculation_Exception
*/
2015-05-13 16:00:22 +00:00
public function calculateFormula ( $formula , $cellID = null , PHPExcel_Cell $pCell = null )
{
2015-05-12 23:40:55 +00:00
// Initialise the logging settings
$this -> formulaError = null ;
$this -> _debugLog -> clearLog ();
$this -> _cyclicReferenceStack -> clear ();
// Disable calculation cacheing because it only applies to cell calculations, not straight formulae
// But don't actually flush any cache
$resetCache = $this -> getCalculationCacheEnabled ();
2015-05-13 16:00:22 +00:00
$this -> _calculationCacheEnabled = false ;
2015-05-12 23:40:55 +00:00
// Execute the calculation
try {
$result = self :: _unwrapResult ( $this -> _calculateFormulaValue ( $formula , $cellID , $pCell ));
} catch ( PHPExcel_Exception $e ) {
throw new PHPExcel_Calculation_Exception ( $e -> getMessage ());
}
// Reset calculation cacheing to its previous state
$this -> _calculationCacheEnabled = $resetCache ;
return $result ;
2015-05-13 16:00:22 +00:00
}
2010-08-26 19:14:53 +00:00
2015-05-13 16:00:22 +00:00
public function getValueFromCache ( $cellReference , & $cellValue )
{
2015-05-12 23:40:55 +00:00
// Is calculation cacheing enabled?
// Is the value present in calculation cache?
$this -> _debugLog -> writeDebugLog ( 'Testing cache value for cell ' , $cellReference );
if (( $this -> _calculationCacheEnabled ) && ( isset ( $this -> _calculationCache [ $cellReference ]))) {
$this -> _debugLog -> writeDebugLog ( 'Retrieving value for cell ' , $cellReference , ' from cache' );
// Return the cached result
$cellValue = $this -> _calculationCache [ $cellReference ];
2015-05-13 16:00:22 +00:00
return true ;
2015-05-12 23:40:55 +00:00
}
2015-05-13 16:00:22 +00:00
return false ;
2013-02-11 14:11:36 +00:00
}
2015-05-13 16:00:22 +00:00
public function saveValueToCache ( $cellReference , $cellValue )
{
2015-05-12 23:40:55 +00:00
if ( $this -> _calculationCacheEnabled ) {
$this -> _calculationCache [ $cellReference ] = $cellValue ;
}
}
/**
* Parse a cell formula and calculate its value
*
* @ param string $formula The formula to parse and calculate
* @ param string $cellID The ID ( e . g . A3 ) of the cell that we are calculating
* @ param PHPExcel_Cell $pCell Cell to calculate
* @ return mixed
* @ throws PHPExcel_Calculation_Exception
*/
2015-05-13 16:00:22 +00:00
public function _calculateFormulaValue ( $formula , $cellID = null , PHPExcel_Cell $pCell = null )
{
2015-05-12 23:40:55 +00:00
$cellValue = null ;
// Basic validation that this is indeed a formula
// We simply return the cell value if not
$formula = trim ( $formula );
2015-05-13 16:00:22 +00:00
if ( $formula { 0 } != '=' ) {
return self :: _wrapResult ( $formula );
}
2015-05-12 23:40:55 +00:00
$formula = ltrim ( substr ( $formula , 1 ));
2015-05-13 16:00:22 +00:00
if ( ! isset ( $formula { 0 })) {
return self :: _wrapResult ( $formula );
}
2015-05-12 23:40:55 +00:00
2015-05-13 16:00:22 +00:00
$pCellParent = ( $pCell !== null ) ? $pCell -> getWorksheet () : null ;
$wsTitle = ( $pCellParent !== null ) ? $pCellParent -> getTitle () : " \x00 Wrk " ;
2014-12-05 23:59:41 +00:00
$wsCellReference = $wsTitle . '!' . $cellID ;
2013-02-11 14:11:36 +00:00
2015-05-13 16:00:22 +00:00
if (( $cellID !== null ) && ( $this -> getValueFromCache ( $wsCellReference , $cellValue ))) {
2015-05-12 23:40:55 +00:00
return $cellValue ;
}
2010-08-26 19:14:53 +00:00
2015-05-12 23:40:55 +00:00
if (( $wsTitle { 0 } !== " \x00 " ) && ( $this -> _cyclicReferenceStack -> onStack ( $wsCellReference ))) {
2014-12-05 23:59:41 +00:00
if ( $this -> cyclicFormulaCount <= 0 ) {
2014-09-13 15:12:45 +00:00
$this -> _cyclicFormulaCell = '' ;
2015-05-12 23:40:55 +00:00
return $this -> _raiseFormulaError ( 'Cyclic Reference in Formula' );
} elseif ( $this -> _cyclicFormulaCell === $wsCellReference ) {
++ $this -> _cyclicFormulaCount ;
if ( $this -> _cyclicFormulaCount >= $this -> cyclicFormulaCount ) {
2014-09-13 15:12:45 +00:00
$this -> _cyclicFormulaCell = '' ;
2015-05-12 23:40:55 +00:00
return $cellValue ;
}
} elseif ( $this -> _cyclicFormulaCell == '' ) {
if ( $this -> _cyclicFormulaCount >= $this -> cyclicFormulaCount ) {
return $cellValue ;
}
$this -> _cyclicFormulaCell = $wsCellReference ;
}
}
// Parse the formula onto the token stack and calculate the value
$this -> _cyclicReferenceStack -> push ( $wsCellReference );
$cellValue = $this -> _processTokenStack ( $this -> _parseFormula ( $formula , $pCell ), $cellID , $pCell );
$this -> _cyclicReferenceStack -> pop ();
// Save to calculation cache
2015-05-13 16:00:22 +00:00
if ( $cellID !== null ) {
2015-05-12 23:40:55 +00:00
$this -> saveValueToCache ( $wsCellReference , $cellValue );
}
// Return the calculated value
return $cellValue ;
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Ensure that paired matrix operands are both matrices and of the same size
*
* @ param mixed & $operand1 First matrix operand
* @ param mixed & $operand2 Second matrix operand
* @ param integer $resize Flag indicating whether the matrices should be resized to match
* and ( if so ), whether the smaller dimension should grow or the
* larger should shrink .
* 0 = no resize
* 1 = shrink to fit
* 2 = extend to fit
*/
2015-05-13 16:00:22 +00:00
private static function _checkMatrixOperands ( & $operand1 , & $operand2 , $resize = 1 )
{
2015-05-12 23:40:55 +00:00
// Examine each of the two operands, and turn them into an array if they aren't one already
// Note that this function should only be called if one or both of the operand is already an array
if ( ! is_array ( $operand1 )) {
2015-05-13 16:00:22 +00:00
list ( $matrixRows , $matrixColumns ) = self :: _getMatrixDimensions ( $operand2 );
$operand1 = array_fill ( 0 , $matrixRows , array_fill ( 0 , $matrixColumns , $operand1 ));
2015-05-12 23:40:55 +00:00
$resize = 0 ;
} elseif ( ! is_array ( $operand2 )) {
2015-05-13 16:00:22 +00:00
list ( $matrixRows , $matrixColumns ) = self :: _getMatrixDimensions ( $operand1 );
$operand2 = array_fill ( 0 , $matrixRows , array_fill ( 0 , $matrixColumns , $operand2 ));
2015-05-12 23:40:55 +00:00
$resize = 0 ;
}
2015-05-13 16:00:22 +00:00
list ( $matrix1Rows , $matrix1Columns ) = self :: _getMatrixDimensions ( $operand1 );
list ( $matrix2Rows , $matrix2Columns ) = self :: _getMatrixDimensions ( $operand2 );
2015-05-12 23:40:55 +00:00
if (( $matrix1Rows == $matrix2Columns ) && ( $matrix2Rows == $matrix1Columns )) {
$resize = 1 ;
}
if ( $resize == 2 ) {
// Given two matrices of (potentially) unequal size, convert the smaller in each dimension to match the larger
2015-05-13 16:00:22 +00:00
self :: _resizeMatricesExtend ( $operand1 , $operand2 , $matrix1Rows , $matrix1Columns , $matrix2Rows , $matrix2Columns );
2015-05-12 23:40:55 +00:00
} elseif ( $resize == 1 ) {
// Given two matrices of (potentially) unequal size, convert the larger in each dimension to match the smaller
2015-05-13 16:00:22 +00:00
self :: _resizeMatricesShrink ( $operand1 , $operand2 , $matrix1Rows , $matrix1Columns , $matrix2Rows , $matrix2Columns );
2015-05-12 23:40:55 +00:00
}
2015-05-13 16:00:22 +00:00
return array ( $matrix1Rows , $matrix1Columns , $matrix2Rows , $matrix2Columns );
}
2015-05-12 23:40:55 +00:00
/**
* Read the dimensions of a matrix , and re - index it with straight numeric keys starting from row 0 , column 0
*
* @ param mixed & $matrix matrix operand
* @ return array An array comprising the number of rows , and number of columns
*/
2015-05-13 16:00:22 +00:00
public static function _getMatrixDimensions ( & $matrix )
{
2015-05-12 23:40:55 +00:00
$matrixRows = count ( $matrix );
$matrixColumns = 0 ;
2015-05-13 16:00:22 +00:00
foreach ( $matrix as $rowKey => $rowValue ) {
$matrixColumns = max ( count ( $rowValue ), $matrixColumns );
2015-05-12 23:40:55 +00:00
if ( ! is_array ( $rowValue )) {
$matrix [ $rowKey ] = array ( $rowValue );
} else {
$matrix [ $rowKey ] = array_values ( $rowValue );
}
}
$matrix = array_values ( $matrix );
2015-05-13 16:00:22 +00:00
return array ( $matrixRows , $matrixColumns );
}
2015-05-12 23:40:55 +00:00
/**
* Ensure that paired matrix operands are both matrices of the same size
*
* @ param mixed & $matrix1 First matrix operand
* @ param mixed & $matrix2 Second matrix operand
* @ param integer $matrix1Rows Row size of first matrix operand
* @ param integer $matrix1Columns Column size of first matrix operand
* @ param integer $matrix2Rows Row size of second matrix operand
* @ param integer $matrix2Columns Column size of second matrix operand
*/
2015-05-13 16:00:22 +00:00
private static function _resizeMatricesShrink ( & $matrix1 , & $matrix2 , $matrix1Rows , $matrix1Columns , $matrix2Rows , $matrix2Columns )
{
2015-05-12 23:40:55 +00:00
if (( $matrix2Columns < $matrix1Columns ) || ( $matrix2Rows < $matrix1Rows )) {
if ( $matrix2Rows < $matrix1Rows ) {
for ( $i = $matrix2Rows ; $i < $matrix1Rows ; ++ $i ) {
unset ( $matrix1 [ $i ]);
}
}
if ( $matrix2Columns < $matrix1Columns ) {
for ( $i = 0 ; $i < $matrix1Rows ; ++ $i ) {
for ( $j = $matrix2Columns ; $j < $matrix1Columns ; ++ $j ) {
unset ( $matrix1 [ $i ][ $j ]);
}
}
}
}
if (( $matrix1Columns < $matrix2Columns ) || ( $matrix1Rows < $matrix2Rows )) {
if ( $matrix1Rows < $matrix2Rows ) {
for ( $i = $matrix1Rows ; $i < $matrix2Rows ; ++ $i ) {
unset ( $matrix2 [ $i ]);
}
}
if ( $matrix1Columns < $matrix2Columns ) {
for ( $i = 0 ; $i < $matrix2Rows ; ++ $i ) {
for ( $j = $matrix1Columns ; $j < $matrix2Columns ; ++ $j ) {
unset ( $matrix2 [ $i ][ $j ]);
}
}
}
}
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Ensure that paired matrix operands are both matrices of the same size
*
* @ param mixed & $matrix1 First matrix operand
* @ param mixed & $matrix2 Second matrix operand
* @ param integer $matrix1Rows Row size of first matrix operand
* @ param integer $matrix1Columns Column size of first matrix operand
* @ param integer $matrix2Rows Row size of second matrix operand
* @ param integer $matrix2Columns Column size of second matrix operand
*/
2015-05-13 16:00:22 +00:00
private static function _resizeMatricesExtend ( & $matrix1 , & $matrix2 , $matrix1Rows , $matrix1Columns , $matrix2Rows , $matrix2Columns )
{
2015-05-12 23:40:55 +00:00
if (( $matrix2Columns < $matrix1Columns ) || ( $matrix2Rows < $matrix1Rows )) {
if ( $matrix2Columns < $matrix1Columns ) {
for ( $i = 0 ; $i < $matrix2Rows ; ++ $i ) {
$x = $matrix2 [ $i ][ $matrix2Columns - 1 ];
for ( $j = $matrix2Columns ; $j < $matrix1Columns ; ++ $j ) {
$matrix2 [ $i ][ $j ] = $x ;
}
}
}
if ( $matrix2Rows < $matrix1Rows ) {
$x = $matrix2 [ $matrix2Rows - 1 ];
for ( $i = 0 ; $i < $matrix1Rows ; ++ $i ) {
$matrix2 [ $i ] = $x ;
}
}
}
if (( $matrix1Columns < $matrix2Columns ) || ( $matrix1Rows < $matrix2Rows )) {
if ( $matrix1Columns < $matrix2Columns ) {
for ( $i = 0 ; $i < $matrix1Rows ; ++ $i ) {
$x = $matrix1 [ $i ][ $matrix1Columns - 1 ];
for ( $j = $matrix1Columns ; $j < $matrix2Columns ; ++ $j ) {
$matrix1 [ $i ][ $j ] = $x ;
}
}
}
if ( $matrix1Rows < $matrix2Rows ) {
$x = $matrix1 [ $matrix1Rows - 1 ];
for ( $i = 0 ; $i < $matrix2Rows ; ++ $i ) {
$matrix1 [ $i ] = $x ;
}
}
}
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Format details of an operand for display in the log ( based on operand type )
*
* @ param mixed $value First matrix operand
* @ return mixed
*/
2015-05-13 16:00:22 +00:00
private function _showValue ( $value )
{
2015-05-12 23:40:55 +00:00
if ( $this -> _debugLog -> getWriteDebugLog ()) {
$testArray = PHPExcel_Calculation_Functions :: flattenArray ( $value );
if ( count ( $testArray ) == 1 ) {
$value = array_pop ( $testArray );
}
if ( is_array ( $value )) {
$returnMatrix = array ();
$pad = $rpad = ', ' ;
2015-05-13 16:00:22 +00:00
foreach ( $value as $row ) {
2015-05-12 23:40:55 +00:00
if ( is_array ( $row )) {
2015-05-13 16:00:22 +00:00
$returnMatrix [] = implode ( $pad , array_map ( array ( $this , '_showValue' ), $row ));
2015-05-12 23:40:55 +00:00
$rpad = '; ' ;
} else {
$returnMatrix [] = $this -> _showValue ( $row );
}
}
2015-05-13 16:00:22 +00:00
return '{ ' . implode ( $rpad , $returnMatrix ) . ' }' ;
} elseif ( is_string ( $value ) && ( trim ( $value , '"' ) == $value )) {
2015-05-12 23:40:55 +00:00
return '"' . $value . '"' ;
2015-05-13 16:00:22 +00:00
} elseif ( is_bool ( $value )) {
2015-05-12 23:40:55 +00:00
return ( $value ) ? self :: $_localeBoolean [ 'TRUE' ] : self :: $_localeBoolean [ 'FALSE' ];
}
}
return PHPExcel_Calculation_Functions :: flattenSingleValue ( $value );
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Format type and details of an operand for display in the log ( based on operand type )
*
* @ param mixed $value First matrix operand
* @ return mixed
*/
2015-05-13 16:00:22 +00:00
private function _showTypeDetails ( $value )
{
2015-05-12 23:40:55 +00:00
if ( $this -> _debugLog -> getWriteDebugLog ()) {
$testArray = PHPExcel_Calculation_Functions :: flattenArray ( $value );
if ( count ( $testArray ) == 1 ) {
$value = array_pop ( $testArray );
}
2015-05-13 16:00:22 +00:00
if ( $value === null ) {
2015-05-12 23:40:55 +00:00
return 'a NULL value' ;
} elseif ( is_float ( $value )) {
$typeString = 'a floating point number' ;
2015-05-13 16:00:22 +00:00
} elseif ( is_int ( $value )) {
2015-05-12 23:40:55 +00:00
$typeString = 'an integer number' ;
2015-05-13 16:00:22 +00:00
} elseif ( is_bool ( $value )) {
2015-05-12 23:40:55 +00:00
$typeString = 'a boolean' ;
2015-05-13 16:00:22 +00:00
} elseif ( is_array ( $value )) {
2015-05-12 23:40:55 +00:00
$typeString = 'a matrix' ;
} else {
if ( $value == '' ) {
return 'an empty string' ;
} elseif ( $value { 0 } == '#' ) {
return 'a ' . $value . ' error' ;
} else {
$typeString = 'a string' ;
}
}
return $typeString . ' with a value of ' . $this -> _showValue ( $value );
}
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
2015-05-13 16:00:22 +00:00
private function _convertMatrixReferences ( $formula )
{
static $matrixReplaceFrom = array ( '{' , ';' , '}' );
static $matrixReplaceTo = array ( 'MKMATRIX(MKMATRIX(' , '),MKMATRIX(' , '))' );
2015-05-12 23:40:55 +00:00
// Convert any Excel matrix references to the MKMATRIX() function
2015-05-13 16:00:22 +00:00
if ( strpos ( $formula , '{' ) !== false ) {
2015-05-12 23:40:55 +00:00
// If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators
2015-05-13 16:00:22 +00:00
if ( strpos ( $formula , '"' ) !== false ) {
2015-05-12 23:40:55 +00:00
// So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded
// the formula
2015-05-13 16:00:22 +00:00
$temp = explode ( '"' , $formula );
2015-05-12 23:40:55 +00:00
// Open and Closed counts used for trapping mismatched braces in the formula
$openCount = $closeCount = 0 ;
2015-05-13 16:00:22 +00:00
$i = false ;
foreach ( $temp as & $value ) {
2015-05-12 23:40:55 +00:00
// Only count/replace in alternating array entries
if ( $i = ! $i ) {
2015-05-13 16:00:22 +00:00
$openCount += substr_count ( $value , '{' );
$closeCount += substr_count ( $value , '}' );
$value = str_replace ( $matrixReplaceFrom , $matrixReplaceTo , $value );
2015-05-12 23:40:55 +00:00
}
}
unset ( $value );
// Then rebuild the formula string
2015-05-13 16:00:22 +00:00
$formula = implode ( '"' , $temp );
2015-05-12 23:40:55 +00:00
} else {
// If there's no quoted strings, then we do a simple count/replace
2015-05-13 16:00:22 +00:00
$openCount = substr_count ( $formula , '{' );
$closeCount = substr_count ( $formula , '}' );
$formula = str_replace ( $matrixReplaceFrom , $matrixReplaceTo , $formula );
2015-05-12 23:40:55 +00:00
}
// Trap for mismatched braces and trigger an appropriate error
if ( $openCount < $closeCount ) {
if ( $openCount > 0 ) {
return $this -> _raiseFormulaError ( " Formula Error: Mismatched matrix braces '}' " );
} else {
return $this -> _raiseFormulaError ( " Formula Error: Unexpected '}' encountered " );
}
} elseif ( $openCount > $closeCount ) {
if ( $closeCount > 0 ) {
return $this -> _raiseFormulaError ( " Formula Error: Mismatched matrix braces ' { ' " );
} else {
return $this -> _raiseFormulaError ( " Formula Error: Unexpected ' { ' encountered " );
}
}
}
return $formula ;
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
2015-05-13 16:00:22 +00:00
private static function _mkMatrix ()
{
2015-05-12 23:40:55 +00:00
return func_get_args ();
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
// Binary Operators
// These operators always work on two values
// Array key is the operator, the value indicates whether this is a left or right associative operator
private static $_operatorAssociativity = array (
'^' => 0 , // Exponentiation
'*' => 0 , '/' => 0 , // Multiplication and Division
'+' => 0 , '-' => 0 , // Addition and Subtraction
'&' => 0 , // Concatenation
'|' => 0 , ':' => 0 , // Intersect and Range
'>' => 0 , '<' => 0 , '=' => 0 , '>=' => 0 , '<=' => 0 , '<>' => 0 // Comparison
);
// Comparison (Boolean) Operators
// These operators work on two values, but always return a boolean result
2015-05-13 16:00:22 +00:00
private static $_comparisonOperators = array ( '>' => true , '<' => true , '=' => true , '>=' => true , '<=' => true , '<>' => true );
2015-05-12 23:40:55 +00:00
// Operator Precedence
// This list includes all valid operators, whether binary (including boolean) or unary (such as %)
// Array key is the operator, the value is its precedence
private static $_operatorPrecedence = array (
':' => 8 , // Range
'|' => 7 , // Intersect
'~' => 6 , // Negation
'%' => 5 , // Percentage
'^' => 4 , // Exponentiation
'*' => 3 , '/' => 3 , // Multiplication and Division
'+' => 2 , '-' => 2 , // Addition and Subtraction
'&' => 1 , // Concatenation
'>' => 0 , '<' => 0 , '=' => 0 , '>=' => 0 , '<=' => 0 , '<>' => 0 // Comparison
);
// Convert infix to postfix notation
2015-05-13 16:00:22 +00:00
private function _parseFormula ( $formula , PHPExcel_Cell $pCell = null )
{
if (( $formula = $this -> _convertMatrixReferences ( trim ( $formula ))) === false ) {
return false ;
2015-05-12 23:40:55 +00:00
}
// If we're using cell caching, then $pCell may well be flushed back to the cache (which detaches the parent worksheet),
// so we store the parent worksheet so that we can re-attach it when necessary
2015-05-13 16:00:22 +00:00
$pCellParent = ( $pCell !== null ) ? $pCell -> getWorksheet () : null ;
2015-05-12 23:40:55 +00:00
$regexpMatchString = '/^(' . self :: CALCULATION_REGEXP_FUNCTION .
'|' . self :: CALCULATION_REGEXP_CELLREF .
'|' . self :: CALCULATION_REGEXP_NUMBER .
'|' . self :: CALCULATION_REGEXP_STRING .
'|' . self :: CALCULATION_REGEXP_OPENBRACE .
'|' . self :: CALCULATION_REGEXP_NAMEDRANGE .
'|' . self :: CALCULATION_REGEXP_ERROR .
')/si' ;
// Start with initialisation
$index = 0 ;
$stack = new PHPExcel_Calculation_Token_Stack ;
$output = array ();
2015-05-13 16:00:22 +00:00
$expectingOperator = false ; // We use this test in syntax-checking the expression to determine when a
2015-05-12 23:40:55 +00:00
// - is a negation or + is a positive operator rather than an operation
2015-05-13 16:00:22 +00:00
$expectingOperand = false ; // We use this test in syntax-checking the expression to determine whether an operand
2015-05-12 23:40:55 +00:00
// should be null in a function call
// The guts of the lexical parser
// Loop through the formula extracting each operator and operand in turn
2015-05-13 16:00:22 +00:00
while ( true ) {
//echo 'Assessing Expression '.substr($formula, $index), PHP_EOL;
2015-05-12 23:40:55 +00:00
$opCharacter = $formula { $index }; // Get the first character of the value at the current index position
2015-05-13 16:00:22 +00:00
//echo 'Initial character of expression block is '.$opCharacter, PHP_EOL;
2015-05-12 23:40:55 +00:00
if (( isset ( self :: $_comparisonOperators [ $opCharacter ])) && ( strlen ( $formula ) > $index ) && ( isset ( self :: $_comparisonOperators [ $formula { $index + 1 }]))) {
$opCharacter .= $formula { ++ $index };
2013-02-11 14:11:36 +00:00
//echo 'Initial character of expression block is comparison operator '.$opCharacter.PHP_EOL;
2015-05-12 23:40:55 +00:00
}
2010-08-26 19:14:53 +00:00
2015-05-12 23:40:55 +00:00
// Find out if we're currently at the beginning of a number, variable, cell reference, function, parenthesis or operand
$isOperandOrFunction = preg_match ( $regexpMatchString , substr ( $formula , $index ), $match );
2013-02-11 14:11:36 +00:00
//echo '$isOperandOrFunction is '.(($isOperandOrFunction) ? 'True' : 'False').PHP_EOL;
//var_dump($match);
2010-08-26 19:14:53 +00:00
2015-05-12 23:40:55 +00:00
if ( $opCharacter == '-' && ! $expectingOperator ) { // Is it a negation instead of a minus?
2015-05-13 16:00:22 +00:00
//echo 'Element is a Negation operator', PHP_EOL;
$stack -> push ( 'Unary Operator' , '~' ); // Put a negation on the stack
2015-05-12 23:40:55 +00:00
++ $index ; // and drop the negation symbol
} elseif ( $opCharacter == '%' && $expectingOperator ) {
2015-05-13 16:00:22 +00:00
//echo 'Element is a Percentage operator', PHP_EOL;
$stack -> push ( 'Unary Operator' , '%' ); // Put a percentage on the stack
2015-05-12 23:40:55 +00:00
++ $index ;
} elseif ( $opCharacter == '+' && ! $expectingOperator ) { // Positive (unary plus rather than binary operator plus) can be discarded?
2015-05-13 16:00:22 +00:00
//echo 'Element is a Positive number, not Plus operator', PHP_EOL;
2015-05-12 23:40:55 +00:00
++ $index ; // Drop the redundant plus symbol
} elseif ((( $opCharacter == '~' ) || ( $opCharacter == '|' )) && ( ! $isOperandOrFunction )) { // We have to explicitly deny a tilde or pipe, because they are legal
return $this -> _raiseFormulaError ( " Formula Error: Illegal character '~' " ); // on the stack but not in the input expression
2010-08-26 19:14:53 +00:00
2015-05-12 23:40:55 +00:00
} elseif (( isset ( self :: $_operators [ $opCharacter ]) or $isOperandOrFunction ) && $expectingOperator ) { // Are we putting an operator on the stack?
2015-05-13 16:00:22 +00:00
//echo 'Element with value '.$opCharacter.' is an Operator', PHP_EOL;
while ( $stack -> count () > 0 &&
2015-05-12 23:40:55 +00:00
( $o2 = $stack -> last ()) &&
isset ( self :: $_operators [ $o2 [ 'value' ]]) &&
@ ( self :: $_operatorAssociativity [ $opCharacter ] ? self :: $_operatorPrecedence [ $opCharacter ] < self :: $_operatorPrecedence [ $o2 [ 'value' ]] : self :: $_operatorPrecedence [ $opCharacter ] <= self :: $_operatorPrecedence [ $o2 [ 'value' ]])) {
$output [] = $stack -> pop (); // Swap operands and higher precedence operators from the stack to the output
}
2015-05-13 16:00:22 +00:00
$stack -> push ( 'Binary Operator' , $opCharacter ); // Finally put our current operator onto the stack
2015-05-12 23:40:55 +00:00
++ $index ;
2015-05-13 16:00:22 +00:00
$expectingOperator = false ;
2015-05-12 23:40:55 +00:00
} elseif ( $opCharacter == ')' && $expectingOperator ) { // Are we expecting to close a parenthesis?
2015-05-13 16:00:22 +00:00
//echo 'Element is a Closing bracket', PHP_EOL;
$expectingOperand = false ;
2015-05-12 23:40:55 +00:00
while (( $o2 = $stack -> pop ()) && $o2 [ 'value' ] != '(' ) { // Pop off the stack back to the last (
2015-05-13 16:00:22 +00:00
if ( $o2 === null ) {
return $this -> _raiseFormulaError ( 'Formula Error: Unexpected closing brace ")"' );
} else {
$output [] = $o2 ;
}
2015-05-12 23:40:55 +00:00
}
$d = $stack -> last ( 2 );
if ( preg_match ( '/^' . self :: CALCULATION_REGEXP_FUNCTION . '$/i' , $d [ 'value' ], $matches )) { // Did this parenthesis just close a function?
$functionName = $matches [ 1 ]; // Get the function name
2015-05-13 16:00:22 +00:00
//echo 'Closed Function is '.$functionName, PHP_EOL;
2015-05-12 23:40:55 +00:00
$d = $stack -> pop ();
$argumentCount = $d [ 'value' ]; // See how many arguments there were (argument count is the next value stored on the stack)
2013-02-11 14:11:36 +00:00
//if ($argumentCount == 0) {
2015-05-13 16:00:22 +00:00
// echo 'With no arguments', PHP_EOL;
2013-02-11 14:11:36 +00:00
//} elseif ($argumentCount == 1) {
2015-05-13 16:00:22 +00:00
// echo 'With 1 argument', PHP_EOL;
2013-02-11 14:11:36 +00:00
//} else {
2015-05-13 16:00:22 +00:00
// echo 'With '.$argumentCount.' arguments', PHP_EOL;
2013-02-11 14:11:36 +00:00
//}
2015-05-12 23:40:55 +00:00
$output [] = $d ; // Dump the argument count on the output
$output [] = $stack -> pop (); // Pop the function and push onto the output
if ( isset ( self :: $_controlFunctions [ $functionName ])) {
2015-05-13 16:00:22 +00:00
//echo 'Built-in function '.$functionName, PHP_EOL;
2015-05-12 23:40:55 +00:00
$expectedArgumentCount = self :: $_controlFunctions [ $functionName ][ 'argumentCount' ];
$functionCall = self :: $_controlFunctions [ $functionName ][ 'functionCall' ];
} elseif ( isset ( self :: $_PHPExcelFunctions [ $functionName ])) {
2015-05-13 16:00:22 +00:00
//echo 'PHPExcel function '.$functionName, PHP_EOL;
2015-05-12 23:40:55 +00:00
$expectedArgumentCount = self :: $_PHPExcelFunctions [ $functionName ][ 'argumentCount' ];
$functionCall = self :: $_PHPExcelFunctions [ $functionName ][ 'functionCall' ];
} else { // did we somehow push a non-function on the stack? this should never happen
return $this -> _raiseFormulaError ( " Formula Error: Internal error, non-function on stack " );
}
// Check the argument count
2015-05-13 16:00:22 +00:00
$argumentCountError = false ;
2015-05-12 23:40:55 +00:00
if ( is_numeric ( $expectedArgumentCount )) {
if ( $expectedArgumentCount < 0 ) {
2015-05-13 16:00:22 +00:00
//echo '$expectedArgumentCount is between 0 and '.abs($expectedArgumentCount), PHP_EOL;
2015-05-12 23:40:55 +00:00
if ( $argumentCount > abs ( $expectedArgumentCount )) {
2015-05-13 16:00:22 +00:00
$argumentCountError = true ;
2015-05-12 23:40:55 +00:00
$expectedArgumentCountString = 'no more than ' . abs ( $expectedArgumentCount );
}
} else {
2015-05-13 16:00:22 +00:00
//echo '$expectedArgumentCount is numeric '.$expectedArgumentCount, PHP_EOL;
2015-05-12 23:40:55 +00:00
if ( $argumentCount != $expectedArgumentCount ) {
2015-05-13 16:00:22 +00:00
$argumentCountError = true ;
2015-05-12 23:40:55 +00:00
$expectedArgumentCountString = $expectedArgumentCount ;
}
}
} elseif ( $expectedArgumentCount != '*' ) {
2015-05-13 16:00:22 +00:00
$isOperandOrFunction = preg_match ( '/(\d*)([-+,])(\d*)/' , $expectedArgumentCount , $argMatch );
2013-02-11 14:11:36 +00:00
//print_r($argMatch);
//echo PHP_EOL;
2015-05-12 23:40:55 +00:00
switch ( $argMatch [ 2 ]) {
2015-05-13 16:00:22 +00:00
case '+' :
2015-05-12 23:40:55 +00:00
if ( $argumentCount < $argMatch [ 1 ]) {
2015-05-13 16:00:22 +00:00
$argumentCountError = true ;
2015-05-12 23:40:55 +00:00
$expectedArgumentCountString = $argMatch [ 1 ] . ' or more ' ;
}
break ;
2015-05-13 16:00:22 +00:00
case '-' :
2015-05-12 23:40:55 +00:00
if (( $argumentCount < $argMatch [ 1 ]) || ( $argumentCount > $argMatch [ 3 ])) {
2015-05-13 16:00:22 +00:00
$argumentCountError = true ;
2015-05-12 23:40:55 +00:00
$expectedArgumentCountString = 'between ' . $argMatch [ 1 ] . ' and ' . $argMatch [ 3 ];
}
break ;
2015-05-13 16:00:22 +00:00
case ',' :
2015-05-12 23:40:55 +00:00
if (( $argumentCount != $argMatch [ 1 ]) && ( $argumentCount != $argMatch [ 3 ])) {
2015-05-13 16:00:22 +00:00
$argumentCountError = true ;
2015-05-12 23:40:55 +00:00
$expectedArgumentCountString = 'either ' . $argMatch [ 1 ] . ' or ' . $argMatch [ 3 ];
}
break ;
}
}
if ( $argumentCountError ) {
return $this -> _raiseFormulaError ( " Formula Error: Wrong number of arguments for $functionName () function: $argumentCount given, " . $expectedArgumentCountString . " expected " );
}
}
++ $index ;
} elseif ( $opCharacter == ',' ) { // Is this the separator for function arguments?
2015-05-13 16:00:22 +00:00
//echo 'Element is a Function argument separator', PHP_EOL;
2015-05-12 23:40:55 +00:00
while (( $o2 = $stack -> pop ()) && $o2 [ 'value' ] != '(' ) { // Pop off the stack back to the last (
2015-05-13 16:00:22 +00:00
if ( $o2 === null ) {
return $this -> _raiseFormulaError ( " Formula Error: Unexpected , " );
} else {
$output [] = $o2 ; // pop the argument expression stuff and push onto the output
}
2015-05-12 23:40:55 +00:00
}
// If we've a comma when we're expecting an operand, then what we actually have is a null operand;
// so push a null onto the stack
if (( $expectingOperand ) || ( ! $expectingOperator )) {
2015-05-13 16:00:22 +00:00
$output [] = array ( 'type' => 'NULL Value' , 'value' => self :: $_ExcelConstants [ 'NULL' ], 'reference' => null );
2015-05-12 23:40:55 +00:00
}
// make sure there was a function
$d = $stack -> last ( 2 );
2015-05-13 16:00:22 +00:00
if ( ! preg_match ( '/^' . self :: CALCULATION_REGEXP_FUNCTION . '$/i' , $d [ 'value' ], $matches )) {
2015-05-12 23:40:55 +00:00
return $this -> _raiseFormulaError ( " Formula Error: Unexpected , " );
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
$d = $stack -> pop ();
2015-05-13 16:00:22 +00:00
$stack -> push ( $d [ 'type' ], ++ $d [ 'value' ], $d [ 'reference' ]); // increment the argument count
2015-05-12 23:40:55 +00:00
$stack -> push ( 'Brace' , '(' ); // put the ( back on, we'll need to pop back to it again
2015-05-13 16:00:22 +00:00
$expectingOperator = false ;
$expectingOperand = true ;
2015-05-12 23:40:55 +00:00
++ $index ;
} elseif ( $opCharacter == '(' && ! $expectingOperator ) {
// echo 'Element is an Opening Bracket<br />';
$stack -> push ( 'Brace' , '(' );
++ $index ;
} elseif ( $isOperandOrFunction && ! $expectingOperator ) { // do we now have a function/variable/number?
2015-05-13 16:00:22 +00:00
$expectingOperator = true ;
$expectingOperand = false ;
2015-05-12 23:40:55 +00:00
$val = $match [ 1 ];
$length = strlen ( $val );
// echo 'Element with value '.$val.' is an Operand, Variable, Constant, String, Number, Cell Reference or Function<br />';
if ( preg_match ( '/^' . self :: CALCULATION_REGEXP_FUNCTION . '$/i' , $val , $matches )) {
2015-05-13 16:00:22 +00:00
$val = preg_replace ( '/\s/u' , '' , $val );
2015-05-12 23:40:55 +00:00
// echo 'Element '.$val.' is a Function<br />';
if ( isset ( self :: $_PHPExcelFunctions [ strtoupper ( $matches [ 1 ])]) || isset ( self :: $_controlFunctions [ strtoupper ( $matches [ 1 ])])) { // it's a function
$stack -> push ( 'Function' , strtoupper ( $val ));
$ax = preg_match ( '/^\s*(\s*\))/ui' , substr ( $formula , $index + $length ), $amatch );
if ( $ax ) {
$stack -> push ( 'Operand Count for Function ' . strtoupper ( $val ) . ')' , 0 );
2015-05-13 16:00:22 +00:00
$expectingOperator = true ;
2015-05-12 23:40:55 +00:00
} else {
$stack -> push ( 'Operand Count for Function ' . strtoupper ( $val ) . ')' , 1 );
2015-05-13 16:00:22 +00:00
$expectingOperator = false ;
2015-05-12 23:40:55 +00:00
}
$stack -> push ( 'Brace' , '(' );
} else { // it's a var w/ implicit multiplication
2015-05-13 16:00:22 +00:00
$output [] = array ( 'type' => 'Value' , 'value' => $matches [ 1 ], 'reference' => null );
2015-05-12 23:40:55 +00:00
}
} elseif ( preg_match ( '/^' . self :: CALCULATION_REGEXP_CELLREF . '$/i' , $val , $matches )) {
// echo 'Element '.$val.' is a Cell reference<br />';
// Watch for this case-change when modifying to allow cell references in different worksheets...
// Should only be applied to the actual cell column, not the worksheet name
// If the last entry on the stack was a : operator, then we have a cell range reference
$testPrevOp = $stack -> last ( 1 );
if ( $testPrevOp [ 'value' ] == ':' ) {
// If we have a worksheet reference, then we're playing with a 3D reference
if ( $matches [ 2 ] == '' ) {
// Otherwise, we 'inherit' the worksheet reference from the start cell reference
// The start of the cell range reference should be the last entry in $output
$startCellRef = $output [ count ( $output ) - 1 ][ 'value' ];
preg_match ( '/^' . self :: CALCULATION_REGEXP_CELLREF . '$/i' , $startCellRef , $startMatches );
if ( $startMatches [ 2 ] > '' ) {
$val = $startMatches [ 2 ] . '!' . $val ;
}
} else {
return $this -> _raiseFormulaError ( " 3D Range references are not yet supported " );
}
}
$output [] = array ( 'type' => 'Cell Reference' , 'value' => $val , 'reference' => $val );
// $expectingOperator = FALSE;
} else { // it's a variable, constant, string, number or boolean
// echo 'Element is a Variable, Constant, String, Number or Boolean<br />';
// If the last entry on the stack was a : operator, then we may have a row or column range reference
$testPrevOp = $stack -> last ( 1 );
if ( $testPrevOp [ 'value' ] == ':' ) {
$startRowColRef = $output [ count ( $output ) - 1 ][ 'value' ];
$rangeWS1 = '' ;
2015-05-13 16:00:22 +00:00
if ( strpos ( '!' , $startRowColRef ) !== false ) {
list ( $rangeWS1 , $startRowColRef ) = explode ( '!' , $startRowColRef );
}
if ( $rangeWS1 != '' ) {
$rangeWS1 .= '!' ;
2015-05-12 23:40:55 +00:00
}
$rangeWS2 = $rangeWS1 ;
2015-05-13 16:00:22 +00:00
if ( strpos ( '!' , $val ) !== false ) {
list ( $rangeWS2 , $val ) = explode ( '!' , $val );
}
if ( $rangeWS2 != '' ) {
$rangeWS2 .= '!' ;
2015-05-12 23:40:55 +00:00
}
if (( is_integer ( $startRowColRef )) && ( ctype_digit ( $val )) &&
( $startRowColRef <= 1048576 ) && ( $val <= 1048576 )) {
// Row range
2015-05-13 16:00:22 +00:00
$endRowColRef = ( $pCellParent !== null ) ? $pCellParent -> getHighestColumn () : 'XFD' ; // Max 16,384 columns for Excel2007
2015-05-12 23:40:55 +00:00
$output [ count ( $output ) - 1 ][ 'value' ] = $rangeWS1 . 'A' . $startRowColRef ;
$val = $rangeWS2 . $endRowColRef . $val ;
} elseif (( ctype_alpha ( $startRowColRef )) && ( ctype_alpha ( $val )) &&
( strlen ( $startRowColRef ) <= 3 ) && ( strlen ( $val ) <= 3 )) {
// Column range
2015-05-13 16:00:22 +00:00
$endRowColRef = ( $pCellParent !== null ) ? $pCellParent -> getHighestRow () : 1048576 ; // Max 1,048,576 rows for Excel2007
2015-05-12 23:40:55 +00:00
$output [ count ( $output ) - 1 ][ 'value' ] = $rangeWS1 . strtoupper ( $startRowColRef ) . '1' ;
$val = $rangeWS2 . $val . $endRowColRef ;
}
}
2015-05-13 16:00:22 +00:00
$localeConstant = false ;
2015-05-12 23:40:55 +00:00
if ( $opCharacter == '"' ) {
// echo 'Element is a String<br />';
// UnEscape any quotes within the string
2015-05-13 16:00:22 +00:00
$val = self :: _wrapResult ( str_replace ( '""' , '"' , self :: _unwrapResult ( $val )));
2015-05-12 23:40:55 +00:00
} elseif ( is_numeric ( $val )) {
// echo 'Element is a Number<br />';
2015-05-13 16:00:22 +00:00
if (( strpos ( $val , '.' ) !== false ) || ( stripos ( $val , 'e' ) !== false ) || ( $val > PHP_INT_MAX ) || ( $val < - PHP_INT_MAX )) {
2015-05-12 23:40:55 +00:00
// echo 'Casting '.$val.' to float<br />';
$val = ( float ) $val ;
} else {
// echo 'Casting '.$val.' to integer<br />';
$val = ( integer ) $val ;
}
} elseif ( isset ( self :: $_ExcelConstants [ trim ( strtoupper ( $val ))])) {
$excelConstant = trim ( strtoupper ( $val ));
// echo 'Element '.$excelConstant.' is an Excel Constant<br />';
$val = self :: $_ExcelConstants [ $excelConstant ];
2015-05-13 16:00:22 +00:00
} elseif (( $localeConstant = array_search ( trim ( strtoupper ( $val )), self :: $_localeBoolean )) !== false ) {
2015-05-12 23:40:55 +00:00
// echo 'Element '.$localeConstant.' is an Excel Constant<br />';
$val = self :: $_ExcelConstants [ $localeConstant ];
}
2015-05-13 16:00:22 +00:00
$details = array ( 'type' => 'Value' , 'value' => $val , 'reference' => null );
if ( $localeConstant ) {
$details [ 'localeValue' ] = $localeConstant ;
}
2015-05-12 23:40:55 +00:00
$output [] = $details ;
}
$index += $length ;
} elseif ( $opCharacter == '$' ) { // absolute row or column range
++ $index ;
} elseif ( $opCharacter == ')' ) { // miscellaneous error checking
if ( $expectingOperand ) {
2015-05-13 16:00:22 +00:00
$output [] = array ( 'type' => 'NULL Value' , 'value' => self :: $_ExcelConstants [ 'NULL' ], 'reference' => null );
$expectingOperand = false ;
$expectingOperator = true ;
2015-05-12 23:40:55 +00:00
} else {
return $this -> _raiseFormulaError ( " Formula Error: Unexpected ')' " );
}
} elseif ( isset ( self :: $_operators [ $opCharacter ]) && ! $expectingOperator ) {
return $this -> _raiseFormulaError ( " Formula Error: Unexpected operator ' $opCharacter ' " );
} else { // I don't even want to know what you did to get here
return $this -> _raiseFormulaError ( " Formula Error: An unexpected error occured " );
}
// Test for end of formula string
if ( $index == strlen ( $formula )) {
// Did we end with an operator?.
// Only valid for the % unary operator
if (( isset ( self :: $_operators [ $opCharacter ])) && ( $opCharacter != '%' )) {
return $this -> _raiseFormulaError ( " Formula Error: Operator ' $opCharacter ' has no operands " );
} else {
break ;
}
}
// Ignore white space
while (( $formula { $index } == " \n " ) || ( $formula { $index } == " \r " )) {
++ $index ;
}
if ( $formula { $index } == ' ' ) {
while ( $formula { $index } == ' ' ) {
++ $index ;
}
// If we're expecting an operator, but only have a space between the previous and next operands (and both are
// Cell References) then we have an INTERSECTION operator
// echo 'Possible Intersect Operator<br />';
if (( $expectingOperator ) && ( preg_match ( '/^' . self :: CALCULATION_REGEXP_CELLREF . '.*/Ui' , substr ( $formula , $index ), $match )) &&
( $output [ count ( $output ) - 1 ][ 'type' ] == 'Cell Reference' )) {
// echo 'Element is an Intersect Operator<br />';
2015-05-13 16:00:22 +00:00
while ( $stack -> count () > 0 &&
2015-05-12 23:40:55 +00:00
( $o2 = $stack -> last ()) &&
isset ( self :: $_operators [ $o2 [ 'value' ]]) &&
@ ( self :: $_operatorAssociativity [ $opCharacter ] ? self :: $_operatorPrecedence [ $opCharacter ] < self :: $_operatorPrecedence [ $o2 [ 'value' ]] : self :: $_operatorPrecedence [ $opCharacter ] <= self :: $_operatorPrecedence [ $o2 [ 'value' ]])) {
$output [] = $stack -> pop (); // Swap operands and higher precedence operators from the stack to the output
}
2015-05-13 16:00:22 +00:00
$stack -> push ( 'Binary Operator' , '|' ); // Put an Intersect Operator on the stack
$expectingOperator = false ;
2015-05-12 23:40:55 +00:00
}
}
}
2015-05-13 16:00:22 +00:00
while (( $op = $stack -> pop ()) !== null ) { // pop everything off the stack and push onto output
if (( is_array ( $op ) && $op [ 'value' ] == '(' ) || ( $op === '(' )) {
2015-05-12 23:40:55 +00:00
return $this -> _raiseFormulaError ( " Formula Error: Expecting ')' " ); // if there are any opening braces on the stack, then braces were unbalanced
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
$output [] = $op ;
}
return $output ;
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
private static function _dataTestReference ( & $operandData )
{
$operand = $operandData [ 'value' ];
2015-05-13 16:00:22 +00:00
if (( $operandData [ 'reference' ] === null ) && ( is_array ( $operand ))) {
2015-05-12 23:40:55 +00:00
$rKeys = array_keys ( $operand );
$rowKey = array_shift ( $rKeys );
$cKeys = array_keys ( array_keys ( $operand [ $rowKey ]));
$colKey = array_shift ( $cKeys );
if ( ctype_upper ( $colKey )) {
$operandData [ 'reference' ] = $colKey . $rowKey ;
}
}
return $operand ;
}
// evaluate postfix notation
2015-05-13 16:00:22 +00:00
private function _processTokenStack ( $tokens , $cellID = null , PHPExcel_Cell $pCell = null )
{
if ( $tokens == false ) {
return false ;
}
2015-05-12 23:40:55 +00:00
// If we're using cell caching, then $pCell may well be flushed back to the cache (which detaches the parent cell collection),
// so we store the parent cell collection so that we can re-attach it when necessary
2015-05-13 16:00:22 +00:00
$pCellWorksheet = ( $pCell !== null ) ? $pCell -> getWorksheet () : null ;
$pCellParent = ( $pCell !== null ) ? $pCell -> getParent () : null ;
2015-05-12 23:40:55 +00:00
$stack = new PHPExcel_Calculation_Token_Stack ;
// Loop through each token in turn
foreach ( $tokens as $tokenData ) {
// print_r($tokenData);
// echo '<br />';
$token = $tokenData [ 'value' ];
// echo '<b>Token is '.$token.'</b><br />';
// 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
if ( isset ( self :: $_binaryOperators [ $token ])) {
// echo 'Token is a binary operator<br />';
// We must have two operands, error if we don't
2015-05-13 16:00:22 +00:00
if (( $operand2Data = $stack -> pop ()) === null ) {
return $this -> _raiseFormulaError ( 'Internal error - Operand value missing from stack' );
}
if (( $operand1Data = $stack -> pop ()) === null ) {
return $this -> _raiseFormulaError ( 'Internal error - Operand value missing from stack' );
}
2015-05-12 23:40:55 +00:00
$operand1 = self :: _dataTestReference ( $operand1Data );
$operand2 = self :: _dataTestReference ( $operand2Data );
// Log what we're doing
if ( $token == ':' ) {
$this -> _debugLog -> writeDebugLog ( 'Evaluating Range ' , $this -> _showValue ( $operand1Data [ 'reference' ]), ' ' , $token , ' ' , $this -> _showValue ( $operand2Data [ 'reference' ]));
} else {
$this -> _debugLog -> writeDebugLog ( 'Evaluating ' , $this -> _showValue ( $operand1 ), ' ' , $token , ' ' , $this -> _showValue ( $operand2 ));
}
// Process the operation in the appropriate manner
switch ( $token ) {
// Comparison (Boolean) Operators
2015-05-13 16:00:22 +00:00
case '>' : // Greater than
case '<' : // Less than
case '>=' : // Greater than or Equal to
case '<=' : // Less than or Equal to
case '=' : // Equality
case '<>' : // Inequality
$this -> _executeBinaryComparisonOperation ( $cellID , $operand1 , $operand2 , $token , $stack );
2015-05-12 23:40:55 +00:00
break ;
// Binary Operators
2015-05-13 16:00:22 +00:00
case ':' : // Range
2015-05-12 23:40:55 +00:00
$sheet1 = $sheet2 = '' ;
2015-05-13 16:00:22 +00:00
if ( strpos ( $operand1Data [ 'reference' ], '!' ) !== false ) {
list ( $sheet1 , $operand1Data [ 'reference' ]) = explode ( '!' , $operand1Data [ 'reference' ]);
2015-05-12 23:40:55 +00:00
} else {
2015-05-13 16:00:22 +00:00
$sheet1 = ( $pCellParent !== null ) ? $pCellWorksheet -> getTitle () : '' ;
2015-05-12 23:40:55 +00:00
}
2015-05-13 16:00:22 +00:00
if ( strpos ( $operand2Data [ 'reference' ], '!' ) !== false ) {
list ( $sheet2 , $operand2Data [ 'reference' ]) = explode ( '!' , $operand2Data [ 'reference' ]);
2015-05-12 23:40:55 +00:00
} else {
$sheet2 = $sheet1 ;
}
if ( $sheet1 == $sheet2 ) {
2015-05-13 16:00:22 +00:00
if ( $operand1Data [ 'reference' ] === null ) {
2015-05-12 23:40:55 +00:00
if (( trim ( $operand1Data [ 'value' ]) != '' ) && ( is_numeric ( $operand1Data [ 'value' ]))) {
$operand1Data [ 'reference' ] = $pCell -> getColumn () . $operand1Data [ 'value' ];
} elseif ( trim ( $operand1Data [ 'reference' ]) == '' ) {
$operand1Data [ 'reference' ] = $pCell -> getCoordinate ();
} else {
$operand1Data [ 'reference' ] = $operand1Data [ 'value' ] . $pCell -> getRow ();
}
}
2015-05-13 16:00:22 +00:00
if ( $operand2Data [ 'reference' ] === null ) {
2015-05-12 23:40:55 +00:00
if (( trim ( $operand2Data [ 'value' ]) != '' ) && ( is_numeric ( $operand2Data [ 'value' ]))) {
$operand2Data [ 'reference' ] = $pCell -> getColumn () . $operand2Data [ 'value' ];
} elseif ( trim ( $operand2Data [ 'reference' ]) == '' ) {
$operand2Data [ 'reference' ] = $pCell -> getCoordinate ();
} else {
$operand2Data [ 'reference' ] = $operand2Data [ 'value' ] . $pCell -> getRow ();
}
}
2015-05-13 16:00:22 +00:00
$oData = array_merge ( explode ( ':' , $operand1Data [ 'reference' ]), explode ( ':' , $operand2Data [ 'reference' ]));
2015-05-12 23:40:55 +00:00
$oCol = $oRow = array ();
2015-05-13 16:00:22 +00:00
foreach ( $oData as $oDatum ) {
2015-05-12 23:40:55 +00:00
$oCR = PHPExcel_Cell :: coordinateFromString ( $oDatum );
$oCol [] = PHPExcel_Cell :: columnIndexFromString ( $oCR [ 0 ]) - 1 ;
$oRow [] = $oCR [ 1 ];
}
$cellRef = PHPExcel_Cell :: stringFromColumnIndex ( min ( $oCol )) . min ( $oRow ) . ':' . PHPExcel_Cell :: stringFromColumnIndex ( max ( $oCol )) . max ( $oRow );
2015-05-13 16:00:22 +00:00
if ( $pCellParent !== null ) {
$cellValue = $this -> extractCellRange ( $cellRef , $this -> _workbook -> getSheetByName ( $sheet1 ), false );
2015-05-12 23:40:55 +00:00
} else {
return $this -> _raiseFormulaError ( 'Unable to access Cell Reference' );
}
2015-05-13 16:00:22 +00:00
$stack -> push ( 'Cell Reference' , $cellValue , $cellRef );
2015-05-12 23:40:55 +00:00
} else {
2015-05-13 16:00:22 +00:00
$stack -> push ( 'Error' , PHPExcel_Calculation_Functions :: REF (), null );
2015-05-12 23:40:55 +00:00
}
break ;
2015-05-13 16:00:22 +00:00
case '+' : // Addition
$this -> _executeNumericBinaryOperation ( $cellID , $operand1 , $operand2 , $token , 'plusEquals' , $stack );
2015-05-12 23:40:55 +00:00
break ;
2015-05-13 16:00:22 +00:00
case '-' : // Subtraction
$this -> _executeNumericBinaryOperation ( $cellID , $operand1 , $operand2 , $token , 'minusEquals' , $stack );
2015-05-12 23:40:55 +00:00
break ;
2015-05-13 16:00:22 +00:00
case '*' : // Multiplication
$this -> _executeNumericBinaryOperation ( $cellID , $operand1 , $operand2 , $token , 'arrayTimesEquals' , $stack );
2015-05-12 23:40:55 +00:00
break ;
2015-05-13 16:00:22 +00:00
case '/' : // Division
$this -> _executeNumericBinaryOperation ( $cellID , $operand1 , $operand2 , $token , 'arrayRightDivide' , $stack );
2015-05-12 23:40:55 +00:00
break ;
2015-05-13 16:00:22 +00:00
case '^' : // Exponential
$this -> _executeNumericBinaryOperation ( $cellID , $operand1 , $operand2 , $token , 'power' , $stack );
2015-05-12 23:40:55 +00:00
break ;
2015-05-13 16:00:22 +00:00
case '&' : // Concatenation
2015-05-12 23:40:55 +00:00
// If either of the operands is a matrix, we need to treat them both as matrices
// (converting the other operand to a matrix if need be); then perform the required
// matrix operation
if ( is_bool ( $operand1 )) {
$operand1 = ( $operand1 ) ? self :: $_localeBoolean [ 'TRUE' ] : self :: $_localeBoolean [ 'FALSE' ];
}
if ( is_bool ( $operand2 )) {
$operand2 = ( $operand2 ) ? self :: $_localeBoolean [ 'TRUE' ] : self :: $_localeBoolean [ 'FALSE' ];
}
if (( is_array ( $operand1 )) || ( is_array ( $operand2 ))) {
// Ensure that both operands are arrays/matrices
2015-05-13 16:00:22 +00:00
self :: _checkMatrixOperands ( $operand1 , $operand2 , 2 );
2015-05-12 23:40:55 +00:00
try {
// Convert operand 1 from a PHP array to a matrix
$matrix = new PHPExcel_Shared_JAMA_Matrix ( $operand1 );
// Perform the required operation against the operand 1 matrix, passing in operand 2
$matrixResult = $matrix -> concat ( $operand2 );
$result = $matrixResult -> getArray ();
} catch ( PHPExcel_Exception $ex ) {
$this -> _debugLog -> writeDebugLog ( 'JAMA Matrix Exception: ' , $ex -> getMessage ());
$result = '#VALUE!' ;
}
} else {
2015-05-13 16:00:22 +00:00
$result = '"' . str_replace ( '""' , '"' , self :: _unwrapResult ( $operand1 , '"' ) . self :: _unwrapResult ( $operand2 , '"' )) . '"' ;
2015-05-12 23:40:55 +00:00
}
$this -> _debugLog -> writeDebugLog ( 'Evaluation Result is ' , $this -> _showTypeDetails ( $result ));
2015-05-13 16:00:22 +00:00
$stack -> push ( 'Value' , $result );
2015-05-12 23:40:55 +00:00
break ;
2015-05-13 16:00:22 +00:00
case '|' : // Intersect
$rowIntersect = array_intersect_key ( $operand1 , $operand2 );
2015-05-12 23:40:55 +00:00
$cellIntersect = $oCol = $oRow = array ();
2015-05-13 16:00:22 +00:00
foreach ( array_keys ( $rowIntersect ) as $row ) {
2015-05-12 23:40:55 +00:00
$oRow [] = $row ;
2015-05-13 16:00:22 +00:00
foreach ( $rowIntersect [ $row ] as $col => $data ) {
2015-05-12 23:40:55 +00:00
$oCol [] = PHPExcel_Cell :: columnIndexFromString ( $col ) - 1 ;
2015-05-13 16:00:22 +00:00
$cellIntersect [ $row ] = array_intersect_key ( $operand1 [ $row ], $operand2 [ $row ]);
2015-05-12 23:40:55 +00:00
}
}
$cellRef = PHPExcel_Cell :: stringFromColumnIndex ( min ( $oCol )) . min ( $oRow ) . ':' . PHPExcel_Cell :: stringFromColumnIndex ( max ( $oCol )) . max ( $oRow );
$this -> _debugLog -> writeDebugLog ( 'Evaluation Result is ' , $this -> _showTypeDetails ( $cellIntersect ));
2015-05-13 16:00:22 +00:00
$stack -> push ( 'Value' , $cellIntersect , $cellRef );
2015-05-12 23:40:55 +00:00
break ;
}
// if the token is a unary operator, pop one value off the stack, do the operation, and push it back on
} elseif (( $token === '~' ) || ( $token === '%' )) {
// echo 'Token is a unary operator<br />';
2015-05-13 16:00:22 +00:00
if (( $arg = $stack -> pop ()) === null ) {
return $this -> _raiseFormulaError ( 'Internal error - Operand value missing from stack' );
}
2015-05-12 23:40:55 +00:00
$arg = $arg [ 'value' ];
if ( $token === '~' ) {
// echo 'Token is a negation operator<br />';
$this -> _debugLog -> writeDebugLog ( 'Evaluating Negation of ' , $this -> _showValue ( $arg ));
$multiplier = - 1 ;
} else {
// echo 'Token is a percentile operator<br />';
$this -> _debugLog -> writeDebugLog ( 'Evaluating Percentile of ' , $this -> _showValue ( $arg ));
$multiplier = 0.01 ;
}
if ( is_array ( $arg )) {
2015-05-13 16:00:22 +00:00
self :: _checkMatrixOperands ( $arg , $multiplier , 2 );
2015-05-12 23:40:55 +00:00
try {
$matrix1 = new PHPExcel_Shared_JAMA_Matrix ( $arg );
$matrixResult = $matrix1 -> arrayTimesEquals ( $multiplier );
$result = $matrixResult -> getArray ();
} catch ( PHPExcel_Exception $ex ) {
$this -> _debugLog -> writeDebugLog ( 'JAMA Matrix Exception: ' , $ex -> getMessage ());
$result = '#VALUE!' ;
}
$this -> _debugLog -> writeDebugLog ( 'Evaluation Result is ' , $this -> _showTypeDetails ( $result ));
2015-05-13 16:00:22 +00:00
$stack -> push ( 'Value' , $result );
2015-05-12 23:40:55 +00:00
} else {
2015-05-13 16:00:22 +00:00
$this -> _executeNumericBinaryOperation ( $cellID , $multiplier , $arg , '*' , 'arrayTimesEquals' , $stack );
2015-05-12 23:40:55 +00:00
}
} elseif ( preg_match ( '/^' . self :: CALCULATION_REGEXP_CELLREF . '$/i' , $token , $matches )) {
2015-05-13 16:00:22 +00:00
$cellRef = null ;
2015-05-12 23:40:55 +00:00
// echo 'Element '.$token.' is a Cell reference<br />';
if ( isset ( $matches [ 8 ])) {
// echo 'Reference is a Range of cells<br />';
2015-05-13 16:00:22 +00:00
if ( $pCell === null ) {
2015-05-12 23:40:55 +00:00
// We can't access the range, so return a REF error
$cellValue = PHPExcel_Calculation_Functions :: REF ();
} else {
$cellRef = $matches [ 6 ] . $matches [ 7 ] . ':' . $matches [ 9 ] . $matches [ 10 ];
if ( $matches [ 2 ] > '' ) {
2015-05-13 16:00:22 +00:00
$matches [ 2 ] = trim ( $matches [ 2 ], " \" ' " );
if (( strpos ( $matches [ 2 ], '[' ) !== false ) || ( strpos ( $matches [ 2 ], ']' ) !== false )) {
2015-05-12 23:40:55 +00:00
// It's a Reference to an external workbook (not currently supported)
return $this -> _raiseFormulaError ( 'Unable to access External Workbook' );
}
2015-05-13 16:00:22 +00:00
$matches [ 2 ] = trim ( $matches [ 2 ], " \" ' " );
2015-05-12 23:40:55 +00:00
// echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'<br />';
$this -> _debugLog -> writeDebugLog ( 'Evaluating Cell Range ' , $cellRef , ' in worksheet ' , $matches [ 2 ]);
2015-05-13 16:00:22 +00:00
if ( $pCellParent !== null ) {
$cellValue = $this -> extractCellRange ( $cellRef , $this -> _workbook -> getSheetByName ( $matches [ 2 ]), false );
2015-05-12 23:40:55 +00:00
} else {
return $this -> _raiseFormulaError ( 'Unable to access Cell Reference' );
}
$this -> _debugLog -> writeDebugLog ( 'Evaluation Result for cells ' , $cellRef , ' in worksheet ' , $matches [ 2 ], ' is ' , $this -> _showTypeDetails ( $cellValue ));
// $cellRef = $matches[2].'!'.$cellRef;
} else {
// echo '$cellRef='.$cellRef.' in current worksheet<br />';
$this -> _debugLog -> writeDebugLog ( 'Evaluating Cell Range ' , $cellRef , ' in current worksheet' );
2015-05-13 16:00:22 +00:00
if ( $pCellParent !== null ) {
$cellValue = $this -> extractCellRange ( $cellRef , $pCellWorksheet , false );
2015-05-12 23:40:55 +00:00
} else {
return $this -> _raiseFormulaError ( 'Unable to access Cell Reference' );
}
$this -> _debugLog -> writeDebugLog ( 'Evaluation Result for cells ' , $cellRef , ' is ' , $this -> _showTypeDetails ( $cellValue ));
}
}
} else {
// echo 'Reference is a single Cell<br />';
2015-05-13 16:00:22 +00:00
if ( $pCell === null ) {
2015-05-12 23:40:55 +00:00
// We can't access the cell, so return a REF error
$cellValue = PHPExcel_Calculation_Functions :: REF ();
} else {
$cellRef = $matches [ 6 ] . $matches [ 7 ];
if ( $matches [ 2 ] > '' ) {
2015-05-13 16:00:22 +00:00
$matches [ 2 ] = trim ( $matches [ 2 ], " \" ' " );
if (( strpos ( $matches [ 2 ], '[' ) !== false ) || ( strpos ( $matches [ 2 ], ']' ) !== false )) {
2015-05-12 23:40:55 +00:00
// It's a Reference to an external workbook (not currently supported)
return $this -> _raiseFormulaError ( 'Unable to access External Workbook' );
}
// echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'<br />';
$this -> _debugLog -> writeDebugLog ( 'Evaluating Cell ' , $cellRef , ' in worksheet ' , $matches [ 2 ]);
2015-05-13 16:00:22 +00:00
if ( $pCellParent !== null ) {
2015-05-12 23:40:55 +00:00
$cellSheet = $this -> _workbook -> getSheetByName ( $matches [ 2 ]);
if ( $cellSheet && $cellSheet -> cellExists ( $cellRef )) {
2015-05-13 16:00:22 +00:00
$cellValue = $this -> extractCellRange ( $cellRef , $this -> _workbook -> getSheetByName ( $matches [ 2 ]), false );
2015-05-12 23:40:55 +00:00
$pCell -> attach ( $pCellParent );
} else {
2015-05-13 16:00:22 +00:00
$cellValue = null ;
2015-05-12 23:40:55 +00:00
}
} else {
return $this -> _raiseFormulaError ( 'Unable to access Cell Reference' );
}
$this -> _debugLog -> writeDebugLog ( 'Evaluation Result for cell ' , $cellRef , ' in worksheet ' , $matches [ 2 ], ' is ' , $this -> _showTypeDetails ( $cellValue ));
// $cellRef = $matches[2].'!'.$cellRef;
} else {
// echo '$cellRef='.$cellRef.' in current worksheet<br />';
$this -> _debugLog -> writeDebugLog ( 'Evaluating Cell ' , $cellRef , ' in current worksheet' );
if ( $pCellParent -> isDataSet ( $cellRef )) {
2015-05-13 16:00:22 +00:00
$cellValue = $this -> extractCellRange ( $cellRef , $pCellWorksheet , false );
2015-05-12 23:40:55 +00:00
$pCell -> attach ( $pCellParent );
} else {
2015-05-13 16:00:22 +00:00
$cellValue = null ;
2015-05-12 23:40:55 +00:00
}
$this -> _debugLog -> writeDebugLog ( 'Evaluation Result for cell ' , $cellRef , ' is ' , $this -> _showTypeDetails ( $cellValue ));
}
}
}
2015-05-13 16:00:22 +00:00
$stack -> push ( 'Value' , $cellValue , $cellRef );
2015-05-12 23:40:55 +00:00
// if the token is a function, pop arguments off the stack, hand them to the function, and push the result back on
} elseif ( preg_match ( '/^' . self :: CALCULATION_REGEXP_FUNCTION . '$/i' , $token , $matches )) {
// echo 'Token is a function<br />';
$functionName = $matches [ 1 ];
$argCount = $stack -> pop ();
$argCount = $argCount [ 'value' ];
if ( $functionName != 'MKMATRIX' ) {
$this -> _debugLog -> writeDebugLog ( 'Evaluating Function ' , self :: _localeFunc ( $functionName ), '() with ' , (( $argCount == 0 ) ? 'no' : $argCount ), ' argument' , (( $argCount == 1 ) ? '' : 's' ));
}
if (( isset ( self :: $_PHPExcelFunctions [ $functionName ])) || ( isset ( self :: $_controlFunctions [ $functionName ]))) { // function
if ( isset ( self :: $_PHPExcelFunctions [ $functionName ])) {
$functionCall = self :: $_PHPExcelFunctions [ $functionName ][ 'functionCall' ];
$passByReference = isset ( self :: $_PHPExcelFunctions [ $functionName ][ 'passByReference' ]);
$passCellReference = isset ( self :: $_PHPExcelFunctions [ $functionName ][ 'passCellReference' ]);
} elseif ( isset ( self :: $_controlFunctions [ $functionName ])) {
$functionCall = self :: $_controlFunctions [ $functionName ][ 'functionCall' ];
$passByReference = isset ( self :: $_controlFunctions [ $functionName ][ 'passByReference' ]);
$passCellReference = isset ( self :: $_controlFunctions [ $functionName ][ 'passCellReference' ]);
}
// get the arguments for this function
// echo 'Function '.$functionName.' expects '.$argCount.' arguments<br />';
$args = $argArrayVals = array ();
for ( $i = 0 ; $i < $argCount ; ++ $i ) {
$arg = $stack -> pop ();
$a = $argCount - $i - 1 ;
if (( $passByReference ) &&
( isset ( self :: $_PHPExcelFunctions [ $functionName ][ 'passByReference' ][ $a ])) &&
( self :: $_PHPExcelFunctions [ $functionName ][ 'passByReference' ][ $a ])) {
2015-05-13 16:00:22 +00:00
if ( $arg [ 'reference' ] === null ) {
2015-05-12 23:40:55 +00:00
$args [] = $cellID ;
2015-05-13 16:00:22 +00:00
if ( $functionName != 'MKMATRIX' ) {
$argArrayVals [] = $this -> _showValue ( $cellID );
}
2015-05-12 23:40:55 +00:00
} else {
$args [] = $arg [ 'reference' ];
2015-05-13 16:00:22 +00:00
if ( $functionName != 'MKMATRIX' ) {
$argArrayVals [] = $this -> _showValue ( $arg [ 'reference' ]);
}
2015-05-12 23:40:55 +00:00
}
} else {
$args [] = self :: _unwrapResult ( $arg [ 'value' ]);
2015-05-13 16:00:22 +00:00
if ( $functionName != 'MKMATRIX' ) {
$argArrayVals [] = $this -> _showValue ( $arg [ 'value' ]);
}
2015-05-12 23:40:55 +00:00
}
}
// Reverse the order of the arguments
krsort ( $args );
if (( $passByReference ) && ( $argCount == 0 )) {
$args [] = $cellID ;
$argArrayVals [] = $this -> _showValue ( $cellID );
}
// echo 'Arguments are: ';
// print_r($args);
// echo '<br />';
if ( $functionName != 'MKMATRIX' ) {
if ( $this -> _debugLog -> getWriteDebugLog ()) {
krsort ( $argArrayVals );
2015-05-13 16:00:22 +00:00
$this -> _debugLog -> writeDebugLog ( 'Evaluating ' , self :: _localeFunc ( $functionName ), '( ' , implode ( self :: $_localeArgumentSeparator . ' ' , PHPExcel_Calculation_Functions :: flattenArray ( $argArrayVals )), ' )' );
2015-05-12 23:40:55 +00:00
}
}
// Process each argument in turn, building the return value as an array
// if (($argCount == 1) && (is_array($args[1])) && ($functionName != 'MKMATRIX')) {
// $operand1 = $args[1];
// $this->_debugLog->writeDebugLog('Argument is a matrix: ', $this->_showValue($operand1));
// $result = array();
// $row = 0;
// foreach($operand1 as $args) {
// if (is_array($args)) {
// foreach($args as $arg) {
// $this->_debugLog->writeDebugLog('Evaluating ', self::_localeFunc($functionName), '( ', $this->_showValue($arg), ' )');
2015-05-13 16:00:22 +00:00
// $r = call_user_func_array($functionCall, $arg);
2015-05-12 23:40:55 +00:00
// $this->_debugLog->writeDebugLog('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($r));
// $result[$row][] = $r;
// }
// ++$row;
// } else {
// $this->_debugLog->writeDebugLog('Evaluating ', self::_localeFunc($functionName), '( ', $this->_showValue($args), ' )');
2015-05-13 16:00:22 +00:00
// $r = call_user_func_array($functionCall, $args);
2015-05-12 23:40:55 +00:00
// $this->_debugLog->writeDebugLog('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($r));
// $result[] = $r;
// }
// }
// } else {
// Process the argument with the appropriate function call
2015-05-13 16:00:22 +00:00
if ( $passCellReference ) {
$args [] = $pCell ;
}
if ( strpos ( $functionCall , '::' ) !== false ) {
$result = call_user_func_array ( explode ( '::' , $functionCall ), $args );
} else {
foreach ( $args as & $arg ) {
$arg = PHPExcel_Calculation_Functions :: flattenSingleValue ( $arg );
2015-05-12 23:40:55 +00:00
}
2015-05-13 16:00:22 +00:00
unset ( $arg );
$result = call_user_func_array ( $functionCall , $args );
}
2015-05-12 23:40:55 +00:00
if ( $functionName != 'MKMATRIX' ) {
$this -> _debugLog -> writeDebugLog ( 'Evaluation Result for ' , self :: _localeFunc ( $functionName ), '() function call is ' , $this -> _showTypeDetails ( $result ));
}
2015-05-13 16:00:22 +00:00
$stack -> push ( 'Value' , self :: _wrapResult ( $result ));
2015-05-12 23:40:55 +00:00
}
} else {
// if the token is a number, boolean, string or an Excel error, push it onto the stack
if ( isset ( self :: $_ExcelConstants [ strtoupper ( $token )])) {
$excelConstant = strtoupper ( $token );
// echo 'Token is a PHPExcel constant: '.$excelConstant.'<br />';
2015-05-13 16:00:22 +00:00
$stack -> push ( 'Constant Value' , self :: $_ExcelConstants [ $excelConstant ]);
2015-05-12 23:40:55 +00:00
$this -> _debugLog -> writeDebugLog ( 'Evaluating Constant ' , $excelConstant , ' as ' , $this -> _showTypeDetails ( self :: $_ExcelConstants [ $excelConstant ]));
2015-05-13 16:00:22 +00:00
} elseif (( is_numeric ( $token )) || ( $token === null ) || ( is_bool ( $token )) || ( $token == '' ) || ( $token { 0 } == '"' ) || ( $token { 0 } == '#' )) {
2015-05-12 23:40:55 +00:00
// echo 'Token is a number, boolean, string, null or an Excel error<br />';
2015-05-13 16:00:22 +00:00
$stack -> push ( 'Value' , $token );
2015-05-12 23:40:55 +00:00
// if the token is a named range, push the named range name onto the stack
} elseif ( preg_match ( '/^' . self :: CALCULATION_REGEXP_NAMEDRANGE . '$/i' , $token , $matches )) {
// echo 'Token is a named range<br />';
$namedRange = $matches [ 6 ];
// echo 'Named Range is '.$namedRange.'<br />';
$this -> _debugLog -> writeDebugLog ( 'Evaluating Named Range ' , $namedRange );
2015-05-13 16:00:22 +00:00
$cellValue = $this -> extractNamedRange ( $namedRange , (( null !== $pCell ) ? $pCellWorksheet : null ), false );
2015-05-12 23:40:55 +00:00
$pCell -> attach ( $pCellParent );
$this -> _debugLog -> writeDebugLog ( 'Evaluation Result for named range ' , $namedRange , ' is ' , $this -> _showTypeDetails ( $cellValue ));
2015-05-13 16:00:22 +00:00
$stack -> push ( 'Named Range' , $cellValue , $namedRange );
2015-05-12 23:40:55 +00:00
} else {
return $this -> _raiseFormulaError ( " undefined variable ' $token ' " );
}
}
}
// when we're out of tokens, the stack should have a single element, the final result
2015-05-13 16:00:22 +00:00
if ( $stack -> count () != 1 ) {
return $this -> _raiseFormulaError ( " internal error " );
}
2015-05-12 23:40:55 +00:00
$output = $stack -> pop ();
$output = $output [ 'value' ];
// if ((is_array($output)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) {
// return array_shift(PHPExcel_Calculation_Functions::flattenArray($output));
// }
return $output ;
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
2015-05-13 16:00:22 +00:00
private function _validateBinaryOperand ( $cellID , & $operand , & $stack )
{
2015-05-12 23:40:55 +00:00
if ( is_array ( $operand )) {
if (( count ( $operand , COUNT_RECURSIVE ) - count ( $operand )) == 1 ) {
do {
$operand = array_pop ( $operand );
} while ( is_array ( $operand ));
}
}
// Numbers, matrices and booleans can pass straight through, as they're already valid
if ( is_string ( $operand )) {
// We only need special validations for the operand if it is a string
// Start by stripping off the quotation marks we use to identify true excel string values internally
2015-05-13 16:00:22 +00:00
if ( $operand > '' && $operand { 0 } == '"' ) {
$operand = self :: _unwrapResult ( $operand );
}
2015-05-12 23:40:55 +00:00
// If the string is a numeric value, we treat it as a numeric, so no further testing
if ( ! is_numeric ( $operand )) {
// If not a numeric, test to see if the value is an Excel error, and so can't be used in normal binary operations
if ( $operand > '' && $operand { 0 } == '#' ) {
$stack -> push ( 'Value' , $operand );
$this -> _debugLog -> writeDebugLog ( 'Evaluation Result is ' , $this -> _showTypeDetails ( $operand ));
2015-05-13 16:00:22 +00:00
return false ;
2015-05-12 23:40:55 +00:00
} elseif ( ! PHPExcel_Shared_String :: convertToNumberIfFraction ( $operand )) {
// If not a numeric or a fraction, then it's a text string, and so can't be used in mathematical binary operations
$stack -> push ( 'Value' , '#VALUE!' );
$this -> _debugLog -> writeDebugLog ( 'Evaluation Result is a ' , $this -> _showTypeDetails ( '#VALUE!' ));
2015-05-13 16:00:22 +00:00
return false ;
2015-05-12 23:40:55 +00:00
}
}
}
// return a true if the value of the operand is one that we can use in normal binary operations
2015-05-13 16:00:22 +00:00
return true ;
}
2015-05-12 23:40:55 +00:00
2015-05-13 16:00:22 +00:00
private function _executeBinaryComparisonOperation ( $cellID , $operand1 , $operand2 , $operation , & $stack , $recursingArrays = false )
{
2015-05-12 23:40:55 +00:00
// If we're dealing with matrix operations, we want a matrix result
if (( is_array ( $operand1 )) || ( is_array ( $operand2 ))) {
$result = array ();
if (( is_array ( $operand1 )) && ( ! is_array ( $operand2 ))) {
2015-05-13 16:00:22 +00:00
foreach ( $operand1 as $x => $operandData ) {
2015-05-12 23:40:55 +00:00
$this -> _debugLog -> writeDebugLog ( 'Evaluating Comparison ' , $this -> _showValue ( $operandData ), ' ' , $operation , ' ' , $this -> _showValue ( $operand2 ));
2015-05-13 16:00:22 +00:00
$this -> _executeBinaryComparisonOperation ( $cellID , $operandData , $operand2 , $operation , $stack );
2015-05-12 23:40:55 +00:00
$r = $stack -> pop ();
$result [ $x ] = $r [ 'value' ];
}
} elseif (( ! is_array ( $operand1 )) && ( is_array ( $operand2 ))) {
2015-05-13 16:00:22 +00:00
foreach ( $operand2 as $x => $operandData ) {
2015-05-12 23:40:55 +00:00
$this -> _debugLog -> writeDebugLog ( 'Evaluating Comparison ' , $this -> _showValue ( $operand1 ), ' ' , $operation , ' ' , $this -> _showValue ( $operandData ));
2015-05-13 16:00:22 +00:00
$this -> _executeBinaryComparisonOperation ( $cellID , $operand1 , $operandData , $operation , $stack );
2015-05-12 23:40:55 +00:00
$r = $stack -> pop ();
$result [ $x ] = $r [ 'value' ];
}
} else {
2015-05-13 16:00:22 +00:00
if ( ! $recursingArrays ) {
self :: _checkMatrixOperands ( $operand1 , $operand2 , 2 );
}
foreach ( $operand1 as $x => $operandData ) {
2015-05-12 23:40:55 +00:00
$this -> _debugLog -> writeDebugLog ( 'Evaluating Comparison ' , $this -> _showValue ( $operandData ), ' ' , $operation , ' ' , $this -> _showValue ( $operand2 [ $x ]));
2015-05-13 16:00:22 +00:00
$this -> _executeBinaryComparisonOperation ( $cellID , $operandData , $operand2 [ $x ], $operation , $stack , true );
2015-05-12 23:40:55 +00:00
$r = $stack -> pop ();
$result [ $x ] = $r [ 'value' ];
}
}
// Log the result details
$this -> _debugLog -> writeDebugLog ( 'Comparison Evaluation Result is ' , $this -> _showTypeDetails ( $result ));
// And push the result onto the stack
2015-05-13 16:00:22 +00:00
$stack -> push ( 'Array' , $result );
return true ;
2015-05-12 23:40:55 +00:00
}
// Simple validate the two operands if they are string values
2015-05-13 16:00:22 +00:00
if ( is_string ( $operand1 ) && $operand1 > '' && $operand1 { 0 } == '"' ) {
$operand1 = self :: _unwrapResult ( $operand1 );
}
if ( is_string ( $operand2 ) && $operand2 > '' && $operand2 { 0 } == '"' ) {
$operand2 = self :: _unwrapResult ( $operand2 );
}
2015-05-12 23:40:55 +00:00
// Use case insensitive comparaison if not OpenOffice mode
2015-05-13 16:00:22 +00:00
if ( PHPExcel_Calculation_Functions :: getCompatibilityMode () != PHPExcel_Calculation_Functions :: COMPATIBILITY_OPENOFFICE ) {
2015-05-12 23:40:55 +00:00
if ( is_string ( $operand1 )) {
$operand1 = strtoupper ( $operand1 );
}
if ( is_string ( $operand2 )) {
$operand2 = strtoupper ( $operand2 );
}
}
$useLowercaseFirstComparison = is_string ( $operand1 ) && is_string ( $operand2 ) && PHPExcel_Calculation_Functions :: getCompatibilityMode () == PHPExcel_Calculation_Functions :: COMPATIBILITY_OPENOFFICE ;
// execute the necessary operation
switch ( $operation ) {
// Greater than
case '>' :
if ( $useLowercaseFirstComparison ) {
$result = $this -> strcmpLowercaseFirst ( $operand1 , $operand2 ) > 0 ;
} else {
$result = ( $operand1 > $operand2 );
}
break ;
// Less than
case '<' :
if ( $useLowercaseFirstComparison ) {
$result = $this -> strcmpLowercaseFirst ( $operand1 , $operand2 ) < 0 ;
} else {
$result = ( $operand1 < $operand2 );
}
break ;
// Equality
case '=' :
2015-01-17 22:51:48 +00:00
if ( is_numeric ( $operand1 ) && is_numeric ( $operand2 )) {
$result = ( abs ( $operand1 - $operand2 ) < $this -> delta );
} else {
$result = strcmp ( $operand1 , $operand2 ) == 0 ;
}
2015-05-12 23:40:55 +00:00
break ;
// Greater than or equal
case '>=' :
2015-01-17 22:51:48 +00:00
if ( is_numeric ( $operand1 ) && is_numeric ( $operand2 )) {
$result = (( abs ( $operand1 - $operand2 ) < $this -> delta ) || ( $operand1 > $operand2 ));
2015-05-12 23:40:55 +00:00
} elseif ( $useLowercaseFirstComparison ) {
$result = $this -> strcmpLowercaseFirst ( $operand1 , $operand2 ) >= 0 ;
} else {
$result = strcmp ( $operand1 , $operand2 ) >= 0 ;
}
break ;
// Less than or equal
case '<=' :
2015-01-17 22:51:48 +00:00
if ( is_numeric ( $operand1 ) && is_numeric ( $operand2 )) {
$result = (( abs ( $operand1 - $operand2 ) < $this -> delta ) || ( $operand1 < $operand2 ));
} elseif ( $useLowercaseFirstComparison ) {
2015-05-12 23:40:55 +00:00
$result = $this -> strcmpLowercaseFirst ( $operand1 , $operand2 ) <= 0 ;
} else {
$result = strcmp ( $operand1 , $operand2 ) <= 0 ;
}
break ;
// Inequality
case '<>' :
2015-01-17 22:51:48 +00:00
if ( is_numeric ( $operand1 ) && is_numeric ( $operand2 )) {
$result = ( abs ( $operand1 - $operand2 ) > 1E-14 );
} else {
$result = strcmp ( $operand1 , $operand2 ) != 0 ;
}
2015-05-12 23:40:55 +00:00
break ;
}
// Log the result details
$this -> _debugLog -> writeDebugLog ( 'Evaluation Result is ' , $this -> _showTypeDetails ( $result ));
// And push the result onto the stack
2015-05-13 16:00:22 +00:00
$stack -> push ( 'Value' , $result );
2015-05-12 23:40:55 +00:00
return true ;
}
/**
* Compare two strings in the same way as strcmp () except that lowercase come before uppercase letters
* @ param string $str1 First string value for the comparison
* @ param string $str2 Second string value for the comparison
* @ return integer
*/
private function strcmpLowercaseFirst ( $str1 , $str2 )
{
2015-01-18 12:31:18 +00:00
$inversedStr1 = PHPExcel_Shared_String :: StrCaseReverse ( $str1 );
$inversedStr2 = PHPExcel_Shared_String :: StrCaseReverse ( $str2 );
2013-11-20 09:55:05 +00:00
2015-05-12 23:40:55 +00:00
return strcmp ( $inversedStr1 , $inversedStr2 );
}
2010-08-26 19:14:53 +00:00
2015-05-13 16:00:22 +00:00
private function _executeNumericBinaryOperation ( $cellID , $operand1 , $operand2 , $operation , $matrixFunction , & $stack )
{
2015-05-12 23:40:55 +00:00
// Validate the two operands
2015-05-13 16:00:22 +00:00
if ( ! $this -> _validateBinaryOperand ( $cellID , $operand1 , $stack )) {
return false ;
}
if ( ! $this -> _validateBinaryOperand ( $cellID , $operand2 , $stack )) {
return false ;
}
2015-05-12 23:40:55 +00:00
// If either of the operands is a matrix, we need to treat them both as matrices
// (converting the other operand to a matrix if need be); then perform the required
// matrix operation
if (( is_array ( $operand1 )) || ( is_array ( $operand2 ))) {
// Ensure that both operands are arrays/matrices of the same size
self :: _checkMatrixOperands ( $operand1 , $operand2 , 2 );
try {
// Convert operand 1 from a PHP array to a matrix
$matrix = new PHPExcel_Shared_JAMA_Matrix ( $operand1 );
// Perform the required operation against the operand 1 matrix, passing in operand 2
$matrixResult = $matrix -> $matrixFunction ( $operand2 );
$result = $matrixResult -> getArray ();
} catch ( PHPExcel_Exception $ex ) {
$this -> _debugLog -> writeDebugLog ( 'JAMA Matrix Exception: ' , $ex -> getMessage ());
$result = '#VALUE!' ;
}
} else {
if (( PHPExcel_Calculation_Functions :: getCompatibilityMode () != PHPExcel_Calculation_Functions :: COMPATIBILITY_OPENOFFICE ) &&
2015-05-13 16:00:22 +00:00
(( is_string ( $operand1 ) && ! is_numeric ( $operand1 ) && strlen ( $operand1 ) > 0 ) ||
2015-05-12 23:40:55 +00:00
( is_string ( $operand2 ) && ! is_numeric ( $operand2 ) && strlen ( $operand2 ) > 0 ))) {
$result = PHPExcel_Calculation_Functions :: VALUE ();
} else {
// If we're dealing with non-matrix operations, execute the necessary operation
switch ( $operation ) {
// Addition
case '+' :
$result = $operand1 + $operand2 ;
break ;
// Subtraction
case '-' :
$result = $operand1 - $operand2 ;
break ;
// Multiplication
case '*' :
$result = $operand1 * $operand2 ;
break ;
// Division
case '/' :
if ( $operand2 == 0 ) {
// Trap for Divide by Zero error
2015-05-13 16:00:22 +00:00
$stack -> push ( 'Value' , '#DIV/0!' );
2015-05-12 23:40:55 +00:00
$this -> _debugLog -> writeDebugLog ( 'Evaluation Result is ' , $this -> _showTypeDetails ( '#DIV/0!' ));
2015-05-13 16:00:22 +00:00
return false ;
2015-05-12 23:40:55 +00:00
} else {
$result = $operand1 / $operand2 ;
}
break ;
// Power
case '^' :
$result = pow ( $operand1 , $operand2 );
break ;
}
}
}
// Log the result details
$this -> _debugLog -> writeDebugLog ( 'Evaluation Result is ' , $this -> _showTypeDetails ( $result ));
// And push the result onto the stack
2015-05-13 16:00:22 +00:00
$stack -> push ( 'Value' , $result );
return true ;
}
2015-05-12 23:40:55 +00:00
// trigger an error, but nicely, if need be
2015-05-13 16:00:22 +00:00
protected function _raiseFormulaError ( $errorMessage )
{
2015-05-12 23:40:55 +00:00
$this -> formulaError = $errorMessage ;
$this -> _cyclicReferenceStack -> clear ();
2015-05-13 16:00:22 +00:00
if ( ! $this -> suppressFormulaErrors ) {
throw new PHPExcel_Calculation_Exception ( $errorMessage );
}
2015-05-12 23:40:55 +00:00
trigger_error ( $errorMessage , E_USER_ERROR );
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Extract range values
*
* @ param string & $pRange String based range representation
* @ param PHPExcel_Worksheet $pSheet Worksheet
* @ param boolean $resetLog Flag indicating whether calculation log should be reset or not
* @ return mixed Array of values in range if range contains more than one element . Otherwise , a single value is returned .
* @ throws PHPExcel_Calculation_Exception
*/
2015-05-13 16:00:22 +00:00
public function extractCellRange ( & $pRange = 'A1' , PHPExcel_Worksheet $pSheet = null , $resetLog = true )
{
2015-05-12 23:40:55 +00:00
// Return value
$returnValue = array ();
2015-05-13 16:00:22 +00:00
// echo 'extractCellRange('.$pRange.')', PHP_EOL;
if ( $pSheet !== null ) {
2015-05-12 23:40:55 +00:00
$pSheetName = $pSheet -> getTitle ();
// echo 'Passed sheet name is '.$pSheetName.PHP_EOL;
// echo 'Range reference is '.$pRange.PHP_EOL;
2015-05-13 16:00:22 +00:00
if ( strpos ( $pRange , '!' ) !== false ) {
// echo '$pRange reference includes sheet reference', PHP_EOL;
list ( $pSheetName , $pRange ) = PHPExcel_Worksheet :: extractSheetTitle ( $pRange , true );
// echo 'New sheet name is '.$pSheetName, PHP_EOL;
// echo 'Adjusted Range reference is '.$pRange, PHP_EOL;
2015-05-12 23:40:55 +00:00
$pSheet = $this -> _workbook -> getSheetByName ( $pSheetName );
}
// Extract range
$aReferences = PHPExcel_Cell :: extractAllCellReferencesInRange ( $pRange );
$pRange = $pSheetName . '!' . $pRange ;
if ( ! isset ( $aReferences [ 1 ])) {
// Single cell in range
2015-05-13 16:00:22 +00:00
sscanf ( $aReferences [ 0 ], '%[A-Z]%d' , $currentCol , $currentRow );
$cellValue = null ;
2015-05-12 23:40:55 +00:00
if ( $pSheet -> cellExists ( $aReferences [ 0 ])) {
$returnValue [ $currentRow ][ $currentCol ] = $pSheet -> getCell ( $aReferences [ 0 ]) -> getCalculatedValue ( $resetLog );
} else {
2015-05-13 16:00:22 +00:00
$returnValue [ $currentRow ][ $currentCol ] = null ;
2015-05-12 23:40:55 +00:00
}
} else {
// Extract cell data for all cells in the range
foreach ( $aReferences as $reference ) {
// Extract range
2015-05-13 16:00:22 +00:00
sscanf ( $reference , '%[A-Z]%d' , $currentCol , $currentRow );
$cellValue = null ;
2015-05-12 23:40:55 +00:00
if ( $pSheet -> cellExists ( $reference )) {
$returnValue [ $currentRow ][ $currentCol ] = $pSheet -> getCell ( $reference ) -> getCalculatedValue ( $resetLog );
} else {
2015-05-13 16:00:22 +00:00
$returnValue [ $currentRow ][ $currentCol ] = null ;
2015-05-12 23:40:55 +00:00
}
}
}
}
return $returnValue ;
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Extract range values
*
* @ param string & $pRange String based range representation
* @ param PHPExcel_Worksheet $pSheet Worksheet
* @ return mixed Array of values in range if range contains more than one element . Otherwise , a single value is returned .
* @ param boolean $resetLog Flag indicating whether calculation log should be reset or not
* @ throws PHPExcel_Calculation_Exception
*/
2015-05-13 16:00:22 +00:00
public function extractNamedRange ( & $pRange = 'A1' , PHPExcel_Worksheet $pSheet = null , $resetLog = true )
{
2015-05-12 23:40:55 +00:00
// Return value
$returnValue = array ();
// echo 'extractNamedRange('.$pRange.')<br />';
2015-05-13 16:00:22 +00:00
if ( $pSheet !== null ) {
2015-05-12 23:40:55 +00:00
$pSheetName = $pSheet -> getTitle ();
// echo 'Current sheet name is '.$pSheetName.'<br />';
// echo 'Range reference is '.$pRange.'<br />';
2015-05-13 16:00:22 +00:00
if ( strpos ( $pRange , '!' ) !== false ) {
// echo '$pRange reference includes sheet reference', PHP_EOL;
list ( $pSheetName , $pRange ) = PHPExcel_Worksheet :: extractSheetTitle ( $pRange , true );
// echo 'New sheet name is '.$pSheetName, PHP_EOL;
// echo 'Adjusted Range reference is '.$pRange, PHP_EOL;
2015-05-12 23:40:55 +00:00
$pSheet = $this -> _workbook -> getSheetByName ( $pSheetName );
}
// Named range?
$namedRange = PHPExcel_NamedRange :: resolveRange ( $pRange , $pSheet );
2015-05-13 16:00:22 +00:00
if ( $namedRange !== null ) {
2015-05-12 23:40:55 +00:00
$pSheet = $namedRange -> getWorksheet ();
// echo 'Named Range '.$pRange.' (';
$pRange = $namedRange -> getRange ();
$splitRange = PHPExcel_Cell :: splitRange ( $pRange );
// Convert row and column references
if ( ctype_alpha ( $splitRange [ 0 ][ 0 ])) {
$pRange = $splitRange [ 0 ][ 0 ] . '1:' . $splitRange [ 0 ][ 1 ] . $namedRange -> getWorksheet () -> getHighestRow ();
2015-05-13 16:00:22 +00:00
} elseif ( ctype_digit ( $splitRange [ 0 ][ 0 ])) {
2015-05-12 23:40:55 +00:00
$pRange = 'A' . $splitRange [ 0 ][ 0 ] . ':' . $namedRange -> getWorksheet () -> getHighestColumn () . $splitRange [ 0 ][ 1 ];
}
// echo $pRange.') is in sheet '.$namedRange->getWorksheet()->getTitle().'<br />';
// if ($pSheet->getTitle() != $namedRange->getWorksheet()->getTitle()) {
// if (!$namedRange->getLocalOnly()) {
// $pSheet = $namedRange->getWorksheet();
// } else {
// return $returnValue;
// }
// }
} else {
return PHPExcel_Calculation_Functions :: REF ();
}
// Extract range
$aReferences = PHPExcel_Cell :: extractAllCellReferencesInRange ( $pRange );
// var_dump($aReferences);
if ( ! isset ( $aReferences [ 1 ])) {
// Single cell (or single column or row) in range
2015-05-13 16:00:22 +00:00
list ( $currentCol , $currentRow ) = PHPExcel_Cell :: coordinateFromString ( $aReferences [ 0 ]);
$cellValue = null ;
2015-05-12 23:40:55 +00:00
if ( $pSheet -> cellExists ( $aReferences [ 0 ])) {
$returnValue [ $currentRow ][ $currentCol ] = $pSheet -> getCell ( $aReferences [ 0 ]) -> getCalculatedValue ( $resetLog );
} else {
2015-05-13 16:00:22 +00:00
$returnValue [ $currentRow ][ $currentCol ] = null ;
2015-05-12 23:40:55 +00:00
}
} else {
// Extract cell data for all cells in the range
foreach ( $aReferences as $reference ) {
// Extract range
2015-05-13 16:00:22 +00:00
list ( $currentCol , $currentRow ) = PHPExcel_Cell :: coordinateFromString ( $reference );
2015-05-12 23:40:55 +00:00
// echo 'NAMED RANGE: $currentCol='.$currentCol.' $currentRow='.$currentRow.'<br />';
2015-05-13 16:00:22 +00:00
$cellValue = null ;
2015-05-12 23:40:55 +00:00
if ( $pSheet -> cellExists ( $reference )) {
$returnValue [ $currentRow ][ $currentCol ] = $pSheet -> getCell ( $reference ) -> getCalculatedValue ( $resetLog );
} else {
2015-05-13 16:00:22 +00:00
$returnValue [ $currentRow ][ $currentCol ] = null ;
2015-05-12 23:40:55 +00:00
}
}
}
// print_r($returnValue);
// echo '<br />';
}
return $returnValue ;
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Is a specific function implemented ?
*
* @ param string $pFunction Function Name
* @ return boolean
*/
2015-05-13 16:00:22 +00:00
public function isImplemented ( $pFunction = '' )
{
$pFunction = strtoupper ( $pFunction );
2015-05-12 23:40:55 +00:00
if ( isset ( self :: $_PHPExcelFunctions [ $pFunction ])) {
return ( self :: $_PHPExcelFunctions [ $pFunction ][ 'functionCall' ] != 'PHPExcel_Calculation_Functions::DUMMY' );
} else {
2015-05-13 16:00:22 +00:00
return false ;
2015-05-12 23:40:55 +00:00
}
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Get a list of all implemented functions as an array of function objects
*
* @ return array of PHPExcel_Calculation_Function
*/
2015-05-13 16:00:22 +00:00
public function listFunctions ()
{
2015-05-12 23:40:55 +00:00
$returnValue = array ();
2015-05-13 16:00:22 +00:00
foreach ( self :: $_PHPExcelFunctions as $functionName => $function ) {
2015-05-12 23:40:55 +00:00
if ( $function [ 'functionCall' ] != 'PHPExcel_Calculation_Functions::DUMMY' ) {
2015-05-13 16:00:22 +00:00
$returnValue [ $functionName ] = new PHPExcel_Calculation_Function (
$function [ 'category' ],
$functionName ,
$function [ 'functionCall' ]
);
2015-05-12 23:40:55 +00:00
}
}
return $returnValue ;
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Get a list of all Excel function names
*
* @ return array
*/
2015-05-13 16:00:22 +00:00
public function listAllFunctionNames ()
{
2015-05-12 23:40:55 +00:00
return array_keys ( self :: $_PHPExcelFunctions );
2015-05-13 16:00:22 +00:00
}
2015-05-12 23:40:55 +00:00
/**
* Get a list of implemented Excel function names
*
* @ return array
*/
2015-05-13 16:00:22 +00:00
public function listFunctionNames ()
{
2015-05-12 23:40:55 +00:00
$returnValue = array ();
2015-05-13 16:00:22 +00:00
foreach ( self :: $_PHPExcelFunctions as $functionName => $function ) {
2015-05-12 23:40:55 +00:00
if ( $function [ 'functionCall' ] != 'PHPExcel_Calculation_Functions::DUMMY' ) {
$returnValue [] = $functionName ;
}
}
return $returnValue ;
2015-05-13 16:00:22 +00:00
}
}