ILIAS  eassessment Revision 61809
 All Data Structures Namespaces Files Functions Variables Groups Pages
PHPExcel_Calculation Class Reference
+ Collaboration diagram for PHPExcel_Calculation:

Public Member Functions

 __destruct ()
 __clone ()
 __clone implementation.
 getCalculationCacheEnabled ()
 Is calculation caching enabled?
 setCalculationCacheEnabled ($pValue=true)
 Enable/disable calculation cache.
 enableCalculationCache ()
 Enable calculation cache.
 disableCalculationCache ()
 Disable calculation cache.
 clearCalculationCache ()
 Clear calculation cache.
 getCalculationCacheExpirationTime ()
 Get calculation cache expiration time.
 setCalculationCacheExpirationTime ($pValue=15)
 Set calculation cache expiration time.
 getLocale ()
 Get the currently defined locale code.
 setLocale ($locale='en_us')
 Set the locale code.
 _translateFormulaToLocale ($formula)
 _translateFormulaToEnglish ($formula)
 calculate (PHPExcel_Cell $pCell=null)
 Calculate cell value (using formula from a cell ID) Retained for backward compatibility.
 calculateCellValue (PHPExcel_Cell $pCell=null, $resetLog=true)
 Calculate the value of a cell formula.
 parseFormula ($formula)
 Validate and parse a formula string.
 calculateFormula ($formula, $cellID=null, PHPExcel_Cell $pCell=null)
 Calculate the value of a formula.
 _calculateFormulaValue ($formula, $cellID=null, PHPExcel_Cell $pCell=null)
 Parse a cell formula and calculate its value.
 extractCellRange (&$pRange= 'A1', PHPExcel_Worksheet $pSheet=null, $resetLog=true)
 Extract range values.
 extractNamedRange (&$pRange= 'A1', PHPExcel_Worksheet $pSheet=null, $resetLog=true)
 Extract range values.
 isImplemented ($pFunction= '')
 Is a specific function implemented?
 listFunctions ()
 Get a list of all implemented functions as an array of function objects.
 listAllFunctionNames ()
 Get a list of all Excel function names.
 listFunctionNames ()
 Get a list of implemented Excel function names.

Static Public Member Functions

static getInstance ()
 Get an instance of this class.
static flushInstance ()
 Flush the calculation cache for any existing instance of this class but only if a PHPExcel_Calculation instance exists.
static getTRUE ()
 Return the locale-specific translation of TRUE.
static getFALSE ()
 Return the locale-specific translation of FALSE.
static setArrayReturnType ($returnType)
 Set the Array Return Type (Array or Value of first element in the array)
static getArrayReturnType ()
 Return the Array Return Type (Array or Value of first element in the array)
static _translateSeparator ($fromSeparator, $toSeparator, $formula, &$inBraces)
static _localeFunc ($function)
static _wrapResult ($value)
 Wrap string values in quotes.
static _unwrapResult ($value)
 Remove quotes used as a wrapper to identify string values.
static _getMatrixDimensions (&$matrix)
 Read the dimensions of a matrix, and re-index it with straight numeric keys starting from row 0, column 0.

Data Fields

const CALCULATION_REGEXP_NUMBER = '[-+]?\d*\.?\d+(e[-+]?\d+)?'
 Constants.
const CALCULATION_REGEXP_STRING = '"(?:[^"]|"")*"'
const CALCULATION_REGEXP_OPENBRACE = '\('
const CALCULATION_REGEXP_FUNCTION = '@?([A-Z][A-Z0-9\.]*)[\s]*\('
const CALCULATION_REGEXP_CELLREF = CALCULATION_REGEXP_CELLREF
const CALCULATION_REGEXP_NAMEDRANGE = CALCULATION_REGEXP_NAMEDRANGE
const CALCULATION_REGEXP_ERROR = '\#[A-Z][A-Z0_\/]*[!\?]?'
const RETURN_ARRAY_AS_ERROR = 'error'
 constants
const RETURN_ARRAY_AS_VALUE = 'value'
const RETURN_ARRAY_AS_ARRAY = 'array'
 $suppressFormulaErrors = false
 $formulaError = null
 $writeDebugLog = false
 $echoDebugLog = false
 $debugLog = array()
 $cyclicFormulaCount = 0

Static Public Attributes

static $_localeBoolean

Protected Member Functions

 _raiseFormulaError ($errorMessage)

Private Member Functions

 __construct ()
 _showValue ($value)
 Format details of an operand for display in the log (based on operand type)
 _showTypeDetails ($value)
 Format type and details of an operand for display in the log (based on operand type)
 _parseFormula ($formula, PHPExcel_Cell $pCell=null)
 _processTokenStack ($tokens, $cellID=null, PHPExcel_Cell $pCell=null)
 _validateBinaryOperand ($cellID, &$operand, &$stack)
 _executeBinaryComparisonOperation ($cellID, $operand1, $operand2, $operation, &$stack, $recursingArrays=false)
 _executeNumericBinaryOperation ($cellID, $operand1, $operand2, $operation, $matrixFunction, &$stack)
 _writeDebug ($message)

Static Private Member Functions

static _translateFormula ($from, $to, $formula, $fromSeparator, $toSeparator)
static _checkMatrixOperands (&$operand1, &$operand2, $resize=1)
 Ensure that paired matrix operands are both matrices and of the same size.
static _resizeMatricesShrink (&$matrix1, &$matrix2, $matrix1Rows, $matrix1Columns, $matrix2Rows, $matrix2Columns)
 Ensure that paired matrix operands are both matrices of the same size.
static _resizeMatricesExtend (&$matrix1, &$matrix2, $matrix1Rows, $matrix1Columns, $matrix2Rows, $matrix2Columns)
 Ensure that paired matrix operands are both matrices of the same size.
static _convertMatrixReferences ($formula)
static _mkMatrix ()

Private Attributes

 $debugLogStack = array()
 $_cyclicFormulaCount = 0
 $_cyclicFormulaCell = ''
 $_savedPrecision = 12

Static Private Attributes

static $returnArrayAsType = self::RETURN_ARRAY_AS_VALUE
static $_instance
static $_calculationCache = array ()
static $_calculationCacheEnabled = true
static $_calculationCacheExpirationTime = 15
static $_operators
static $_binaryOperators
static $_localeLanguage = 'en_us'
static $_validLocaleLanguages
static $_localeArgumentSeparator = ','
static $_localeFunctions = array()
static $_ExcelConstants
static $_PHPExcelFunctions
static $_controlFunctions
static $functionReplaceFromExcel = null
static $functionReplaceToLocale = null
static $functionReplaceFromLocale = null
static $functionReplaceToExcel = null

Detailed Description

Definition at line 62 of file Calculation.php.

Constructor & Destructor Documentation

PHPExcel_Calculation::__construct ( )
private

Definition at line 1683 of file Calculation.php.

References $filename.

{
$localeFileDirectory = PHPEXCEL_ROOT.'PHPExcel/locale/';
foreach (glob($localeFileDirectory.'/*',GLOB_ONLYDIR) as $filename) {
$filename = substr($filename,strlen($localeFileDirectory)+1);
if ($filename != 'en') {
self::$_validLocaleLanguages[] = $filename;
}
}
$setPrecision = (PHP_INT_SIZE == 4) ? 12 : 16;
$this->_savedPrecision = ini_get('precision');
if ($this->_savedPrecision < $setPrecision) {
ini_set('precision',$setPrecision);
}
} // function __construct()
PHPExcel_Calculation::__destruct ( )

Definition at line 1700 of file Calculation.php.

{
ini_set('precision',$this->_savedPrecision);
}

Member Function Documentation

PHPExcel_Calculation::__clone ( )
final

__clone implementation.

Cloning should not be allowed in a Singleton!

public

Exceptions
Exception

Definition at line 1739 of file Calculation.php.

{
throw new Exception ('Cloning a Singleton is not allowed!');
} // function __clone()
PHPExcel_Calculation::_calculateFormulaValue (   $formula,
  $cellID = null,
PHPExcel_Cell  $pCell = null 
)

Parse a cell formula and calculate its value.

Parameters
string$formulaThe formula to parse and calculate
string$cellIDThe ID (e.g. A3) of the cell that we are calculating
PHPExcel_Cell$pCellCell to calculate
Returns
mixed
Exceptions
Exception

Definition at line 2257 of file Calculation.php.

References $_cyclicFormulaCount, _parseFormula(), _processTokenStack(), _raiseFormulaError(), _wrapResult(), _writeDebug(), and PHPExcel_Calculation_Functions\flattenArray().

Referenced by calculateCellValue(), and calculateFormula().

{
// echo '<b>'.$cellID.'</b><br />';
$cellValue = '';
// Basic validation that this is indeed a formula
// We simply return the "cell value" (formula) if not
$formula = trim($formula);
if ($formula{0} != '=') return self::_wrapResult($formula);
$formula = ltrim(substr($formula,1));
if (!isset($formula{0})) return self::_wrapResult($formula);
$wsTitle = "\x00Wrk";
if (!is_null($pCell)) {
$pCellParent = $pCell->getParent();
if (!is_null($pCellParent)) {
$wsTitle = $pCellParent->getTitle();
}
}
// Is calculation cacheing enabled?
if (!is_null($cellID)) {
if (self::$_calculationCacheEnabled) {
// Is the value present in calculation cache?
// echo 'Testing cache value<br />';
if (isset(self::$_calculationCache[$wsTitle][$cellID])) {
// echo 'Value is in cache<br />';
$this->_writeDebug('Testing cache value for cell '.$cellID);
// Is cache still valid?
if ((microtime(true) - self::$_calculationCache[$wsTitle][$cellID]['time']) < self::$_calculationCacheExpirationTime) {
// echo 'Cache time is still valid<br />';
$this->_writeDebug('Retrieving value for '.$cellID.' from cache');
// Return the cached result
$returnValue = self::$_calculationCache[$wsTitle][$cellID]['data'];
// echo 'Retrieving data value of '.$returnValue.' for '.$cellID.' from cache<br />';
if (is_array($returnValue)) {
$returnValue = PHPExcel_Calculation_Functions::flattenArray($returnValue);
return array_shift($returnValue);
}
return $returnValue;
} else {
// echo 'Cache has expired<br />';
$this->_writeDebug('Cache value for '.$cellID.' has expired');
// Clear the cache if it's no longer valid
unset(self::$_calculationCache[$wsTitle][$cellID]);
}
}
}
}
if ((in_array($wsTitle.'!'.$cellID,$this->debugLogStack)) && ($wsTitle != "\x00Wrk")) {
if ($this->cyclicFormulaCount <= 0) {
return $this->_raiseFormulaError('Cyclic Reference in Formula');
} elseif (($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) &&
($this->_cyclicFormulaCell == $wsTitle.'!'.$cellID)) {
return $cellValue;
} elseif ($this->_cyclicFormulaCell == $wsTitle.'!'.$cellID) {
if ($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) {
return $cellValue;
}
} elseif ($this->_cyclicFormulaCell == '') {
$this->_cyclicFormulaCell = $wsTitle.'!'.$cellID;
if ($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) {
return $cellValue;
}
}
}
$this->debugLogStack[] = $wsTitle.'!'.$cellID;
// Parse the formula onto the token stack and calculate the value
$cellValue = $this->_processTokenStack($this->_parseFormula($formula, $pCell), $cellID, $pCell);
array_pop($this->debugLogStack);
// Save to calculation cache
if (!is_null($cellID)) {
if (self::$_calculationCacheEnabled) {
self::$_calculationCache[$wsTitle][$cellID]['time'] = microtime(true);
self::$_calculationCache[$wsTitle][$cellID]['data'] = $cellValue;
}
}
// Return the calculated value
return $cellValue;
} // function _calculateFormulaValue()

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static PHPExcel_Calculation::_checkMatrixOperands ( $operand1,
$operand2,
  $resize = 1 
)
staticprivate

Ensure that paired matrix operands are both matrices and of the same size.

Parameters
mixed&$operand1First matrix operand
mixed&$operand2Second matrix operand
integer$resizeFlag 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

Definition at line 2353 of file Calculation.php.

References _getMatrixDimensions(), _resizeMatricesExtend(), and _resizeMatricesShrink().

Referenced by _executeBinaryComparisonOperation(), _executeNumericBinaryOperation(), and _processTokenStack().

{
// 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)) {
list($matrixRows,$matrixColumns) = self::_getMatrixDimensions($operand2);
$operand1 = array_fill(0,$matrixRows,array_fill(0,$matrixColumns,$operand1));
$resize = 0;
} elseif (!is_array($operand2)) {
list($matrixRows,$matrixColumns) = self::_getMatrixDimensions($operand1);
$operand2 = array_fill(0,$matrixRows,array_fill(0,$matrixColumns,$operand2));
$resize = 0;
}
list($matrix1Rows,$matrix1Columns) = self::_getMatrixDimensions($operand1);
list($matrix2Rows,$matrix2Columns) = self::_getMatrixDimensions($operand2);
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
self::_resizeMatricesExtend($operand1,$operand2,$matrix1Rows,$matrix1Columns,$matrix2Rows,$matrix2Columns);
} elseif ($resize == 1) {
// Given two matrices of (potentially) unequal size, convert the larger in each dimension to match the smaller
self::_resizeMatricesShrink($operand1,$operand2,$matrix1Rows,$matrix1Columns,$matrix2Rows,$matrix2Columns);
}
return array( $matrix1Rows,$matrix1Columns,$matrix2Rows,$matrix2Columns);
} // function _checkMatrixOperands()

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static PHPExcel_Calculation::_convertMatrixReferences (   $formula)
staticprivate

Definition at line 2557 of file Calculation.php.

References _raiseFormulaError().

{
static $matrixReplaceFrom = array('{',';','}');
static $matrixReplaceTo = array('MKMATRIX(MKMATRIX(','),MKMATRIX(','))');
// Convert any Excel matrix references to the MKMATRIX() function
if (strpos($formula,'{') !== false) {
// If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators
if (strpos($formula,'"') !== false) {
// So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded
// the formula
$temp = explode('"',$formula);
// Open and Closed counts used for trapping mismatched braces in the formula
$openCount = $closeCount = 0;
$i = false;
foreach($temp as &$value) {
// Only count/replace in alternating array entries
if ($i = !$i) {
$openCount += substr_count($value,'{');
$closeCount += substr_count($value,'}');
$value = str_replace($matrixReplaceFrom,$matrixReplaceTo,$value);
}
}
unset($value);
// Then rebuild the formula string
$formula = implode('"',$temp);
} else {
// If there's no quoted strings, then we do a simple count/replace
$openCount = substr_count($formula,'{');
$closeCount = substr_count($formula,'}');
$formula = str_replace($matrixReplaceFrom,$matrixReplaceTo,$formula);
}
// 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;
} // function _convertMatrixReferences()

+ Here is the call graph for this function:

PHPExcel_Calculation::_executeBinaryComparisonOperation (   $cellID,
  $operand1,
  $operand2,
  $operation,
$stack,
  $recursingArrays = false 
)
private

Definition at line 3397 of file Calculation.php.

References $x, _checkMatrixOperands(), _showTypeDetails(), _showValue(), _unwrapResult(), and _writeDebug().

Referenced by _processTokenStack().

{
// 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))) {
foreach($operand1 as $x => $operandData) {
$this->_writeDebug('Evaluating '.$this->_showValue($operandData).' '.$operation.' '.$this->_showValue($operand2));
$this->_executeBinaryComparisonOperation($cellID,$operandData,$operand2,$operation,$stack);
$r = $stack->pop();
$result[$x] = $r['value'];
}
} elseif ((!is_array($operand1)) && (is_array($operand2))) {
foreach($operand2 as $x => $operandData) {
$this->_writeDebug('Evaluating '.$this->_showValue($operand1).' '.$operation.' '.$this->_showValue($operandData));
$this->_executeBinaryComparisonOperation($cellID,$operand1,$operandData,$operation,$stack);
$r = $stack->pop();
$result[$x] = $r['value'];
}
} else {
if (!$recursingArrays) { self::_checkMatrixOperands($operand1,$operand2,2); }
foreach($operand1 as $x => $operandData) {
$this->_writeDebug('Evaluating '.$this->_showValue($operandData).' '.$operation.' '.$this->_showValue($operand2[$x]));
$this->_executeBinaryComparisonOperation($cellID,$operandData,$operand2[$x],$operation,$stack,true);
$r = $stack->pop();
$result[$x] = $r['value'];
}
}
// Log the result details
$this->_writeDebug('Evaluation Result is '.$this->_showTypeDetails($result));
// And push the result onto the stack
$stack->push('Array',$result);
return true;
}
// Simple validate the two operands if they are string values
if (is_string($operand1) && $operand1 > '' && $operand1{0} == '"') { $operand1 = self::_unwrapResult($operand1); }
if (is_string($operand2) && $operand2 > '' && $operand2{0} == '"') { $operand2 = self::_unwrapResult($operand2); }
// execute the necessary operation
switch ($operation) {
// Greater than
case '>':
$result = ($operand1 > $operand2);
break;
// Less than
case '<':
$result = ($operand1 < $operand2);
break;
// Equality
case '=':
$result = ($operand1 == $operand2);
break;
// Greater than or equal
case '>=':
$result = ($operand1 >= $operand2);
break;
// Less than or equal
case '<=':
$result = ($operand1 <= $operand2);
break;
// Inequality
case '<>':
$result = ($operand1 != $operand2);
break;
}
// Log the result details
$this->_writeDebug('Evaluation Result is '.$this->_showTypeDetails($result));
// And push the result onto the stack
$stack->push('Value',$result);
return true;
} // function _executeBinaryComparisonOperation()

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

PHPExcel_Calculation::_executeNumericBinaryOperation (   $cellID,
  $operand1,
  $operand2,
  $operation,
  $matrixFunction,
$stack 
)
private

Definition at line 3471 of file Calculation.php.

References _checkMatrixOperands(), _showTypeDetails(), _validateBinaryOperand(), _writeDebug(), PHPExcel_Calculation_Functions\COMPATIBILITY_OPENOFFICE, PHPExcel_Calculation_Functions\getCompatibilityMode(), and PHPExcel_Calculation_Functions\VALUE().

Referenced by _processTokenStack().

{
// Validate the two operands
if (!$this->_validateBinaryOperand($cellID,$operand1,$stack)) return false;
if (!$this->_validateBinaryOperand($cellID,$operand2,$stack)) return false;
$executeMatrixOperation = false;
// 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
$executeMatrixOperation = true;
$mSize = array();
list($mSize[],$mSize[],$mSize[],$mSize[]) = self::_checkMatrixOperands($operand1,$operand2,2);
// But if they're both single cell matrices, then we can treat them as simple values
if (array_sum($mSize) == 4) {
$executeMatrixOperation = false;
$operand1 = $operand1[0][0];
$operand2 = $operand2[0][0];
}
}
if ($executeMatrixOperation) {
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 (Exception $ex) {
$this->_writeDebug('JAMA Matrix Exception: '.$ex->getMessage());
$result = '#VALUE!';
}
} else {
((is_string($operand1) && !is_numeric($operand1)) || (is_string($operand2) && !is_numeric($operand2)))) {
} 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
$stack->push('Value','#DIV/0!');
$this->_writeDebug('Evaluation Result is '.$this->_showTypeDetails('#DIV/0!'));
return false;
} else {
$result = $operand1/$operand2;
}
break;
// Power
case '^':
$result = pow($operand1,$operand2);
break;
}
}
}
// Log the result details
$this->_writeDebug('Evaluation Result is '.$this->_showTypeDetails($result));
// And push the result onto the stack
$stack->push('Value',$result);
return true;
} // function _executeNumericBinaryOperation()

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static PHPExcel_Calculation::_getMatrixDimensions ( $matrix)
static

Read the dimensions of a matrix, and re-index it with straight numeric keys starting from row 0, column 0.

Parameters
mixed&$matrixmatrix operand
Returns
array An array comprising the number of rows, and number of columns

Definition at line 2389 of file Calculation.php.

Referenced by _checkMatrixOperands(), PHPExcel_Calculation_LookupRef\COLUMNS(), and PHPExcel_Calculation_LookupRef\ROWS().

{
$matrixRows = count($matrix);
$matrixColumns = 0;
foreach($matrix as $rowKey => $rowValue) {
$matrixColumns = max(count($rowValue),$matrixColumns);
if (!is_array($rowValue)) {
$matrix[$rowKey] = array($rowValue);
} else {
$matrix[$rowKey] = array_values($rowValue);
}
}
$matrix = array_values($matrix);
return array($matrixRows,$matrixColumns);
} // function _getMatrixDimensions()

+ Here is the caller graph for this function:

static PHPExcel_Calculation::_localeFunc (   $function)
static

Definition at line 2054 of file Calculation.php.

Referenced by PHPExcel_Token_Stack\push().

{
if (self::$_localeLanguage !== 'en_us') {
$functionName = trim($function,'(');
if (isset(self::$_localeFunctions[$functionName])) {
$brace = ($functionName != $function);
$function = self::$_localeFunctions[$functionName];
if ($brace) { $function .= '('; }
}
}
return $function;
}

+ Here is the caller graph for this function:

static PHPExcel_Calculation::_mkMatrix ( )
staticprivate

Definition at line 2608 of file Calculation.php.

{
return func_get_args();
} // function _mkMatrix()
PHPExcel_Calculation::_parseFormula (   $formula,
PHPExcel_Cell  $pCell = null 
)
private

Definition at line 2614 of file Calculation.php.

References $d, _raiseFormulaError(), and _wrapResult().

Referenced by _calculateFormulaValue(), and parseFormula().

{
if (($formula = self::_convertMatrixReferences(trim($formula))) === false) {
return false;
}
// 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
$pCellParent = (!is_null($pCell)) ? $pCell->getParent() : null;
// 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
$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
$comparisonOperators = array('>' => true, '<' => true, '=' => true, '>=' => true, '<=' => true, '<>' => true);
// 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
$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
);
$regexpMatchString = '/^('.self::CALCULATION_REGEXP_FUNCTION.
'|'.self::CALCULATION_REGEXP_NUMBER.
'|'.self::CALCULATION_REGEXP_STRING.
'|'.self::CALCULATION_REGEXP_OPENBRACE.
'|'.self::CALCULATION_REGEXP_CELLREF.
'|'.self::CALCULATION_REGEXP_NAMEDRANGE.
'|'.self::CALCULATION_REGEXP_ERROR.
')/si';
// Start with initialisation
$index = 0;
$stack = new PHPExcel_Token_Stack;
$output = array();
$expectingOperator = false; // We use this test in syntax-checking the expression to determine when a
// - is a negation or + is a positive operator rather than an operation
$expectingOperand = false; // We use this test in syntax-checking the expression to determine whether an operand
// should be null in a function call
// The guts of the lexical parser
// Loop through the formula extracting each operator and operand in turn
while(true) {
// echo 'Assessing Expression <b>'.substr($formula, $index).'</b><br />';
$opCharacter = $formula{$index}; // Get the first character of the value at the current index position
// echo 'Initial character of expression block is '.$opCharacter.'<br />';
if ((isset($comparisonOperators[$opCharacter])) && (strlen($formula) > $index) && (isset($comparisonOperators[$formula{$index+1}]))) {
$opCharacter .= $formula{++$index};
// echo 'Initial character of expression block is comparison operator '.$opCharacter.'<br />';
}
// 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);
// echo '$isOperandOrFunction is '.(($isOperandOrFunction) ? 'True' : 'False').'<br />';
// var_dump($match);
if ($opCharacter == '-' && !$expectingOperator) { // Is it a negation instead of a minus?
// echo 'Element is a Negation operator<br />';
$stack->push('Unary Operator','~'); // Put a negation on the stack
++$index; // and drop the negation symbol
} elseif ($opCharacter == '%' && $expectingOperator) {
// echo 'Element is a Percentage operator<br />';
$stack->push('Unary Operator','%'); // Put a percentage on the stack
++$index;
} elseif ($opCharacter == '+' && !$expectingOperator) { // Positive (unary plus rather than binary operator plus) can be discarded?
// echo 'Element is a Positive number, not Plus operator<br />';
++$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
} elseif ((isset(self::$_operators[$opCharacter]) or $isOperandOrFunction) && $expectingOperator) { // Are we putting an operator on the stack?
// echo 'Element with value '.$opCharacter.' is an Operator<br />';
while($stack->count() > 0 &&
($o2 = $stack->last()) &&
isset(self::$_operators[$o2['value']]) &&
@($operatorAssociativity[$opCharacter] ? $operatorPrecedence[$opCharacter] < $operatorPrecedence[$o2['value']] : $operatorPrecedence[$opCharacter] <= $operatorPrecedence[$o2['value']])) {
$output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output
}
$stack->push('Binary Operator',$opCharacter); // Finally put our current operator onto the stack
++$index;
$expectingOperator = false;
} elseif ($opCharacter == ')' && $expectingOperator) { // Are we expecting to close a parenthesis?
// echo 'Element is a Closing bracket<br />';
$expectingOperand = false;
while (($o2 = $stack->pop()) && $o2['value'] != '(') { // Pop off the stack back to the last (
if (is_null($o2)) return $this->_raiseFormulaError('Formula Error: Unexpected closing brace ")"');
else $output[] = $o2;
}
$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
// echo 'Closed Function is '.$functionName.'<br />';
$d = $stack->pop();
$argumentCount = $d['value']; // See how many arguments there were (argument count is the next value stored on the stack)
// if ($argumentCount == 0) {
// echo 'With no arguments<br />';
// } elseif ($argumentCount == 1) {
// echo 'With 1 argument<br />';
// } else {
// echo 'With '.$argumentCount.' arguments<br />';
// }
$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])) {
// echo 'Built-in function '.$functionName.'<br />';
$expectedArgumentCount = self::$_controlFunctions[$functionName]['argumentCount'];
$functionCall = self::$_controlFunctions[$functionName]['functionCall'];
} elseif (isset(self::$_PHPExcelFunctions[$functionName])) {
// echo 'PHPExcel function '.$functionName.'<br />';
$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
$argumentCountError = false;
if (is_numeric($expectedArgumentCount)) {
if ($expectedArgumentCount < 0) {
// echo '$expectedArgumentCount is between 0 and '.abs($expectedArgumentCount).'<br />';
if ($argumentCount > abs($expectedArgumentCount)) {
$argumentCountError = true;
$expectedArgumentCountString = 'no more than '.abs($expectedArgumentCount);
}
} else {
// echo '$expectedArgumentCount is numeric '.$expectedArgumentCount.'<br />';
if ($argumentCount != $expectedArgumentCount) {
$argumentCountError = true;
$expectedArgumentCountString = $expectedArgumentCount;
}
}
} elseif ($expectedArgumentCount != '*') {
$isOperandOrFunction = preg_match('/(\d*)([-+,])(\d*)/',$expectedArgumentCount,$argMatch);
// print_r($argMatch);
// echo '<br />';
switch ($argMatch[2]) {
case '+' :
if ($argumentCount < $argMatch[1]) {
$argumentCountError = true;
$expectedArgumentCountString = $argMatch[1].' or more ';
}
break;
case '-' :
if (($argumentCount < $argMatch[1]) || ($argumentCount > $argMatch[3])) {
$argumentCountError = true;
$expectedArgumentCountString = 'between '.$argMatch[1].' and '.$argMatch[3];
}
break;
case ',' :
if (($argumentCount != $argMatch[1]) && ($argumentCount != $argMatch[3])) {
$argumentCountError = true;
$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?
// echo 'Element is a Function argument separator<br />';
while (($o2 = $stack->pop()) && $o2['value'] != '(') { // Pop off the stack back to the last (
if (is_null($o2)) return $this->_raiseFormulaError("Formula Error: Unexpected ,");
else $output[] = $o2; // pop the argument expression stuff and push onto the output
}
// 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)) {
$output[] = array('type' => 'NULL Value', 'value' => self::$_ExcelConstants['NULL'], 'reference' => null);
}
// make sure there was a function
$d = $stack->last(2);
if (!preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $d['value'], $matches))
return $this->_raiseFormulaError("Formula Error: Unexpected ,");
$d = $stack->pop();
$stack->push($d['type'],++$d['value'],$d['reference']); // increment the argument count
$stack->push('Brace', '('); // put the ( back on, we'll need to pop back to it again
$expectingOperator = false;
$expectingOperand = true;
++$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?
$expectingOperator = true;
$expectingOperand = false;
$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)) {
$val = preg_replace('/\s/','',$val);
// 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*\))/i', substr($formula, $index+$length), $amatch);
if ($ax) {
$stack->push('Operand Count for Function '.self::_localeFunc(strtoupper($val)).')', 0);
$expectingOperator = true;
} else {
$stack->push('Operand Count for Function '.self::_localeFunc(strtoupper($val)).')', 1);
$expectingOperator = false;
}
$stack->push('Brace', '(');
} else { // it's a var w/ implicit multiplication
$output[] = array('type' => 'Value', 'value' => $matches[1], 'reference' => null);
}
} 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 = '';
if (strpos('!',$startRowColRef) !== false) {
list($rangeWS1,$startRowColRef) = explode('!',$startRowColRef);
}
if ($rangeWS1 != '') $rangeWS1 .= '!';
$rangeWS2 = $rangeWS1;
if (strpos('!',$val) !== false) {
list($rangeWS2,$val) = explode('!',$val);
}
if ($rangeWS2 != '') $rangeWS2 .= '!';
if ((is_integer($startRowColRef)) && (ctype_digit($val)) &&
($startRowColRef <= 1048576) && ($val <= 1048576)) {
// Row range
$endRowColRef = (!is_null($pCellParent)) ? $pCellParent->getHighestColumn() : 'XFD'; // Max 16,384 columns for Excel2007
$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
$endRowColRef = (!is_null($pCellParent)) ? $pCellParent->getHighestRow() : 1048576; // Max 1,048,576 rows for Excel2007
$output[count($output)-1]['value'] = $rangeWS1.strtoupper($startRowColRef).'1';
$val = $rangeWS2.$val.$endRowColRef;
}
}
$localeConstant = false;
if ($opCharacter == '"') {
// echo 'Element is a String<br />';
// UnEscape any quotes within the string
$val = self::_wrapResult(str_replace('""','"',self::_unwrapResult($val)));
} elseif (is_numeric($val)) {
// echo 'Element is a Number<br />';
if ((strpos($val,'.') !== false) || (stripos($val,'e') !== false) || ($val > PHP_INT_MAX) || ($val < -PHP_INT_MAX)) {
// 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];
} elseif (($localeConstant = array_search(trim(strtoupper($val)), self::$_localeBoolean)) !== false) {
// echo 'Element '.$localeConstant.' is an Excel Constant<br />';
$val = self::$_ExcelConstants[$localeConstant];
}
$details = array('type' => 'Value', 'value' => $val, 'reference' => null);
if ($localeConstant) { $details['localeValue'] = $localeConstant; }
$output[] = $details;
}
$index += $length;
} elseif ($opCharacter == '$') { // absolute row or column range
++$index;
} elseif ($opCharacter == ')') { // miscellaneous error checking
if ($expectingOperand) {
$output[] = array('type' => 'Null Value', 'value' => self::$_ExcelConstants['NULL'], 'reference' => null);
$expectingOperand = false;
$expectingOperator = true;
} 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 />';
while($stack->count() > 0 &&
($o2 = $stack->last()) &&
isset(self::$_operators[$o2['value']]) &&
@($operatorAssociativity[$opCharacter] ? $operatorPrecedence[$opCharacter] < $operatorPrecedence[$o2['value']] : $operatorPrecedence[$opCharacter] <= $operatorPrecedence[$o2['value']])) {
$output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output
}
$stack->push('Binary Operator','|'); // Put an Intersect Operator on the stack
$expectingOperator = false;
}
}
}
while (!is_null($op = $stack->pop())) { // pop everything off the stack and push onto output
if ($opCharacter['value'] == '(') return $this->_raiseFormulaError("Formula Error: Expecting ')'"); // if there are any opening braces on the stack, then braces were unbalanced
$output[] = $op;
}
return $output;
} // function _parseFormula()

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

PHPExcel_Calculation::_processTokenStack (   $tokens,
  $cellID = null,
PHPExcel_Cell  $pCell = null 
)
private

Definition at line 2984 of file Calculation.php.

References $arg, $data, $oRow, $row, _checkMatrixOperands(), _executeBinaryComparisonOperation(), _executeNumericBinaryOperation(), _raiseFormulaError(), _showTypeDetails(), _showValue(), _unwrapResult(), _writeDebug(), PHPExcel_Cell\columnIndexFromString(), PHPExcel_Cell\coordinateFromString(), extractCellRange(), extractNamedRange(), PHPExcel_Calculation_Functions\flattenArray(), PHPExcel_Calculation_Functions\flattenSingleValue(), PHPExcel_Calculation_Functions\REF(), and PHPExcel_Cell\stringFromColumnIndex().

Referenced by _calculateFormulaValue().

{
if ($tokens == false) return false;
// 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
$pCellParent = (!is_null($pCell)) ? $pCell->getParent() : null;
$stack = new PHPExcel_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
if (is_null($operand2Data = $stack->pop())) return $this->_raiseFormulaError('Internal error - Operand value missing from stack');
if (is_null($operand1Data = $stack->pop())) return $this->_raiseFormulaError('Internal error - Operand value missing from stack');
// Log what we're doing
$operand1 = $operand1Data['value'];
$operand2 = $operand2Data['value'];
if ($token == ':') {
$this->_writeDebug('Evaluating Range '.$this->_showValue($operand1Data['reference']).$token.$this->_showValue($operand2Data['reference']));
} else {
$this->_writeDebug('Evaluating '.$this->_showValue($operand1).' '.$token.' '.$this->_showValue($operand2));
}
// Process the operation in the appropriate manner
switch ($token) {
// Comparison (Boolean) Operators
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);
break;
// Binary Operators
case ':' : // Range
$sheet1 = $sheet2 = '';
if (strpos($operand1Data['reference'],'!') !== false) {
list($sheet1,$operand1Data['reference']) = explode('!',$operand1Data['reference']);
} else {
$sheet1 = (!is_null($pCellParent)) ? $pCellParent->getTitle() : '';
}
if (strpos($operand2Data['reference'],'!') !== false) {
list($sheet2,$operand2Data['reference']) = explode('!',$operand2Data['reference']);
} else {
$sheet2 = $sheet1;
}
if ($sheet1 == $sheet2) {
if (is_null($operand1Data['reference'])) {
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();
}
}
if (is_null($operand2Data['reference'])) {
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();
}
}
$oData = array_merge(explode(':',$operand1Data['reference']),explode(':',$operand2Data['reference']));
$oCol = $oRow = array();
foreach($oData as $oDatum) {
$oCol[] = PHPExcel_Cell::columnIndexFromString($oCR[0]) - 1;
$oRow[] = $oCR[1];
}
if (!is_null($pCellParent)) {
$cellValue = $this->extractCellRange($cellRef, $pCellParent->getParent()->getSheetByName($sheet1), false);
} else {
return $this->_raiseFormulaError('Unable to access Cell Reference');
}
$stack->push('Cell Reference',$cellValue,$cellRef);
} else {
$stack->push('Error',PHPExcel_Calculation_Functions::REF(),null);
}
break;
case '+' : // Addition
$this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'plusEquals',$stack);
break;
case '-' : // Subtraction
$this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'minusEquals',$stack);
break;
case '*' : // Multiplication
$this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'arrayTimesEquals',$stack);
break;
case '/' : // Division
$this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'arrayRightDivide',$stack);
break;
case '^' : // Exponential
$this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'power',$stack);
break;
case '&' : // Concatenation
// 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
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->concat($operand2);
$result = $matrixResult->getArray();
} catch (Exception $ex) {
$this->_writeDebug('JAMA Matrix Exception: '.$ex->getMessage());
$result = '#VALUE!';
}
} else {
$result = '"'.str_replace('""','"',self::_unwrapResult($operand1,'"').self::_unwrapResult($operand2,'"')).'"';
}
$this->_writeDebug('Evaluation Result is '.$this->_showTypeDetails($result));
$stack->push('Value',$result);
break;
case '|' : // Intersect
$rowIntersect = array_intersect_key($operand1,$operand2);
$cellIntersect = $oCol = $oRow = array();
foreach(array_keys($rowIntersect) as $row) {
$oRow[] = $row;
foreach($rowIntersect[$row] as $col => $data) {
$cellIntersect[$row] = array_intersect_key($operand1[$row],$operand2[$row]);
}
}
$this->_writeDebug('Evaluation Result is '.$this->_showTypeDetails($cellIntersect));
$stack->push('Value',$cellIntersect,$cellRef);
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 />';
if (is_null($arg = $stack->pop())) return $this->_raiseFormulaError('Internal error - Operand value missing from stack');
$arg = $arg['value'];
if ($token === '~') {
// echo 'Token is a negation operator<br />';
$this->_writeDebug('Evaluating Negation of '.$this->_showValue($arg));
$multiplier = -1;
} else {
// echo 'Token is a percentile operator<br />';
$this->_writeDebug('Evaluating Percentile of '.$this->_showValue($arg));
$multiplier = 0.01;
}
if (is_array($arg)) {
try {
$matrixResult = $matrix1->arrayTimesEquals($multiplier);
$result = $matrixResult->getArray();
} catch (Exception $ex) {
$this->_writeDebug('JAMA Matrix Exception: '.$ex->getMessage());
$result = '#VALUE!';
}
$this->_writeDebug('Evaluation Result is '.$this->_showTypeDetails($result));
$stack->push('Value',$result);
} else {
$this->_executeNumericBinaryOperation($cellID,$multiplier,$arg,'*','arrayTimesEquals',$stack);
}
} elseif (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $token, $matches)) {
$cellRef = null;
// echo 'Element '.$token.' is a Cell reference<br />';
if (isset($matches[8])) {
// echo 'Reference is a Range of cells<br />';
if (is_null($pCell)) {
// We can't access the range, so return a REF error
} else {
$cellRef = $matches[6].$matches[7].':'.$matches[9].$matches[10];
if ($matches[2] > '') {
$matches[2] = trim($matches[2],"\"'");
// echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'<br />';
$this->_writeDebug('Evaluating Cell Range '.$cellRef.' in worksheet '.$matches[2]);
if (!is_null($pCellParent)) {
$cellValue = $this->extractCellRange($cellRef, $pCellParent->getParent()->getSheetByName($matches[2]), false);
} else {
return $this->_raiseFormulaError('Unable to access Cell Reference');
}
$this->_writeDebug('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->_writeDebug('Evaluating Cell Range '.$cellRef.' in current worksheet');
if (!is_null($pCellParent)) {
$cellValue = $this->extractCellRange($cellRef, $pCellParent, false);
} else {
return $this->_raiseFormulaError('Unable to access Cell Reference');
}
$this->_writeDebug('Evaluation Result for cells '.$cellRef.' is '.$this->_showTypeDetails($cellValue));
}
}
} else {
// echo 'Reference is a single Cell<br />';
if (is_null($pCell)) {
// We can't access the cell, so return a REF error
} else {
$cellRef = $matches[6].$matches[7];
if ($matches[2] > '') {
$matches[2] = trim($matches[2],"\"'");
// echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'<br />';
$this->_writeDebug('Evaluating Cell '.$cellRef.' in worksheet '.$matches[2]);
if (!is_null($pCellParent)) {
if ($pCellParent->getParent()->getSheetByName($matches[2])->cellExists($cellRef)) {
$cellValue = $this->extractCellRange($cellRef, $pCellParent->getParent()->getSheetByName($matches[2]), false);
$pCell->attach($pCellParent);
} else {
$cellValue = null;
}
} else {
return $this->_raiseFormulaError('Unable to access Cell Reference');
}
$this->_writeDebug('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->_writeDebug('Evaluating Cell '.$cellRef.' in current worksheet');
if ($pCellParent->cellExists($cellRef)) {
$cellValue = $this->extractCellRange($cellRef, $pCellParent, false);
$pCell->attach($pCellParent);
} else {
$cellValue = null;
}
$this->_writeDebug('Evaluation Result for cell '.$cellRef.' is '.$this->_showTypeDetails($cellValue));
}
}
}
$stack->push('Value',$cellValue,$cellRef);
// 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->_writeDebug('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])) {
if (is_null($arg['reference'])) {
$args[] = $cellID;
if ($functionName != 'MKMATRIX') { $argArrayVals[] = $this->_showValue($cellID); }
} else {
$args[] = $arg['reference'];
if ($functionName != 'MKMATRIX') { $argArrayVals[] = $this->_showValue($arg['reference']); }
}
} else {
$args[] = self::_unwrapResult($arg['value']);
if ($functionName != 'MKMATRIX') { $argArrayVals[] = $this->_showValue($arg['value']); }
}
}
// 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->writeDebugLog) {
krsort($argArrayVals);
$this->_writeDebug('Evaluating '. self::_localeFunc($functionName).'( '.implode(self::$_localeArgumentSeparator.' ',PHPExcel_Calculation_Functions::flattenArray($argArrayVals)).' )');
}
}
// 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->_writeDebug('Argument is a matrix: '.$this->_showValue($operand1));
// $result = array();
// $row = 0;
// foreach($operand1 as $args) {
// if (is_array($args)) {
// foreach($args as $arg) {
// $this->_writeDebug('Evaluating '.self::_localeFunc($functionName).'( '.$this->_showValue($arg).' )');
// $r = call_user_func_array($functionCall,$arg);
// $this->_writeDebug('Evaluation Result for '.self::_localeFunc($functionName).'() function call is '.$this->_showTypeDetails($r));
// $result[$row][] = $r;
// }
// ++$row;
// } else {
// $this->_writeDebug('Evaluating '.self::_localeFunc($functionName).'( '.$this->_showValue($args).' )');
// $r = call_user_func_array($functionCall,$args);
// $this->_writeDebug('Evaluation Result for '.self::_localeFunc($functionName).'() function call is '.$this->_showTypeDetails($r));
// $result[] = $r;
// }
// }
// } else {
// Process the argument with the appropriate function call
if ($passCellReference) {
$args[] = $pCell;
}
if (strpos($functionCall,'::') !== false) {
$result = call_user_func_array(explode('::',$functionCall),$args);
} else {
foreach($args as &$arg) {
}
unset($arg);
$result = call_user_func_array($functionCall,$args);
}
// }
if ($functionName != 'MKMATRIX') {
$this->_writeDebug('Evaluation Result for '.self::_localeFunc($functionName).'() function call is '.$this->_showTypeDetails($result));
}
$stack->push('Value',self::_wrapResult($result));
}
} 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 />';
$stack->push('Constant Value',self::$_ExcelConstants[$excelConstant]);
$this->_writeDebug('Evaluating Constant '.$excelConstant.' as '.$this->_showTypeDetails(self::$_ExcelConstants[$excelConstant]));
} elseif ((is_numeric($token)) || (is_null($token)) || (is_bool($token)) || ($token == '') || ($token{0} == '"') || ($token{0} == '#')) {
// echo 'Token is a number, boolean, string, null or an Excel error<br />';
$stack->push('Value',$token);
// 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->_writeDebug('Evaluating Named Range '.$namedRange);
$cellValue = $this->extractNamedRange($namedRange, ((null !== $pCell) ? $pCellParent : null), false);
$pCell->attach($pCellParent);
$this->_writeDebug('Evaluation Result for named range '.$namedRange.' is '.$this->_showTypeDetails($cellValue));
$stack->push('Named Range',$cellValue,$namedRange);
} else {
return $this->_raiseFormulaError("undefined variable '$token'");
}
}
}
// when we're out of tokens, the stack should have a single element, the final result
if ($stack->count() != 1) return $this->_raiseFormulaError("internal error");
$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;
} // function _processTokenStack()

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

PHPExcel_Calculation::_raiseFormulaError (   $errorMessage)
protected

Definition at line 3563 of file Calculation.php.

Referenced by _calculateFormulaValue(), _convertMatrixReferences(), _parseFormula(), and _processTokenStack().

{
$this->formulaError = $errorMessage;
if (!$this->suppressFormulaErrors) throw new Exception($errorMessage);
trigger_error($errorMessage, E_USER_ERROR);
} // function _raiseFormulaError()

+ Here is the caller graph for this function:

static PHPExcel_Calculation::_resizeMatricesExtend ( $matrix1,
$matrix2,
  $matrix1Rows,
  $matrix1Columns,
  $matrix2Rows,
  $matrix2Columns 
)
staticprivate

Ensure that paired matrix operands are both matrices of the same size.

Parameters
mixed&$matrix1First matrix operand
mixed&$matrix2Second matrix operand

Definition at line 2450 of file Calculation.php.

References $x.

Referenced by _checkMatrixOperands().

{
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;
}
}
}
} // function _resizeMatricesExtend()

+ Here is the caller graph for this function:

static PHPExcel_Calculation::_resizeMatricesShrink ( $matrix1,
$matrix2,
  $matrix1Rows,
  $matrix1Columns,
  $matrix2Rows,
  $matrix2Columns 
)
staticprivate

Ensure that paired matrix operands are both matrices of the same size.

Parameters
mixed&$matrix1First matrix operand
mixed&$matrix2Second matrix operand

Definition at line 2411 of file Calculation.php.

Referenced by _checkMatrixOperands().

{
if (($matrix2Columns < $matrix1Columns) || ($matrix2Rows < $matrix1Rows)) {
if ($matrix2Columns < $matrix1Columns) {
for ($i = 0; $i < $matrix1Rows; ++$i) {
for ($j = $matrix2Columns; $j < $matrix1Columns; ++$j) {
unset($matrix1[$i][$j]);
}
}
}
if ($matrix2Rows < $matrix1Rows) {
for ($i = $matrix2Rows; $i < $matrix1Rows; ++$i) {
unset($matrix1[$i]);
}
}
}
if (($matrix1Columns < $matrix2Columns) || ($matrix1Rows < $matrix2Rows)) {
if ($matrix1Columns < $matrix2Columns) {
for ($i = 0; $i < $matrix2Rows; ++$i) {
for ($j = $matrix1Columns; $j < $matrix2Columns; ++$j) {
unset($matrix2[$i][$j]);
}
}
}
if ($matrix1Rows < $matrix2Rows) {
for ($i = $matrix1Rows; $i < $matrix2Rows; ++$i) {
unset($matrix2[$i]);
}
}
}
} // function _resizeMatricesShrink()

+ Here is the caller graph for this function:

PHPExcel_Calculation::_showTypeDetails (   $value)
private

Format type and details of an operand for display in the log (based on operand type)

Parameters
mixed$valueFirst matrix operand
Returns
mixed

Definition at line 2526 of file Calculation.php.

References _showValue(), and PHPExcel_Calculation_Functions\flattenArray().

Referenced by _executeBinaryComparisonOperation(), _executeNumericBinaryOperation(), _processTokenStack(), and _validateBinaryOperand().

{
if ($this->writeDebugLog) {
if (count($testArray) == 1) {
$value = array_pop($testArray);
}
if (is_null($value)) {
return 'a null value';
} elseif (is_float($value)) {
$typeString = 'a floating point number';
} elseif(is_int($value)) {
$typeString = 'an integer number';
} elseif(is_bool($value)) {
$typeString = 'a boolean';
} elseif(is_array($value)) {
$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);
}
} // function _showTypeDetails()

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

PHPExcel_Calculation::_showValue (   $value)
private

Format details of an operand for display in the log (based on operand type)

Parameters
mixed$valueFirst matrix operand
Returns
mixed

Definition at line 2493 of file Calculation.php.

References $row, and PHPExcel_Calculation_Functions\flattenArray().

Referenced by _executeBinaryComparisonOperation(), _processTokenStack(), and _showTypeDetails().

{
if ($this->writeDebugLog) {
if (count($testArray) == 1) {
$value = array_pop($testArray);
}
if (is_array($value)) {
$returnMatrix = array();
$pad = $rpad = ', ';
foreach($value as $row) {
if (is_array($row)) {
$returnMatrix[] = implode($pad,$row);
$rpad = '; ';
} else {
$returnMatrix[] = $row;
}
}
return '{ '.implode($rpad,$returnMatrix).' }';
} elseif(is_bool($value)) {
return ($value) ? self::$_localeBoolean['TRUE'] : self::$_localeBoolean['FALSE'];
}
}
return $value;
} // function _showValue()

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static PHPExcel_Calculation::_translateFormula (   $from,
  $to,
  $formula,
  $fromSeparator,
  $toSeparator 
)
staticprivate

Definition at line 1967 of file Calculation.php.

References _translateSeparator().

Referenced by _translateFormulaToEnglish(), and _translateFormulaToLocale().

{
// Convert any Excel function names to the required language
if (self::$_localeLanguage !== 'en_us') {
$inBraces = false;
// If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators
if (strpos($formula,'"') !== false) {
// So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded
// the formula
$temp = explode('"',$formula);
$i = false;
foreach($temp as &$value) {
// Only count/replace in alternating array entries
if ($i = !$i) {
$value = preg_replace($from,$to,$value);
$value = self::_translateSeparator($fromSeparator,$toSeparator,$value,$inBraces);
}
}
unset($value);
// Then rebuild the formula string
$formula = implode('"',$temp);
} else {
// If there's no quoted strings, then we do a simple count/replace
$formula = preg_replace($from,$to,$formula);
$formula = self::_translateSeparator($fromSeparator,$toSeparator,$formula,$inBraces);
}
}
return $formula;
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

PHPExcel_Calculation::_translateFormulaToEnglish (   $formula)

Definition at line 2029 of file Calculation.php.

References _translateFormula().

{
if (is_null(self::$functionReplaceFromLocale)) {
self::$functionReplaceFromLocale = array();
foreach(array_values(self::$_localeFunctions) as $localeFunctionName) {
self::$functionReplaceFromLocale[] = '/(@?[^\w\.])'.preg_quote($localeFunctionName).'([\s]*\()/Ui';
}
foreach(array_values(self::$_localeBoolean) as $excelBoolean) {
self::$functionReplaceFromLocale[] = '/(@?[^\w\.])'.preg_quote($excelBoolean).'([^\w\.])/Ui';
}
}
if (is_null(self::$functionReplaceToExcel)) {
self::$functionReplaceToExcel = array();
foreach(array_keys(self::$_localeFunctions) as $excelFunctionName) {
self::$functionReplaceToExcel[] = '$1'.trim($excelFunctionName).'$2';
}
foreach(array_keys(self::$_localeBoolean) as $excelBoolean) {
self::$functionReplaceToExcel[] = '$1'.trim($excelBoolean).'$2';
}
}
return self::_translateFormula(self::$functionReplaceFromLocale,self::$functionReplaceToExcel,$formula,self::$_localeArgumentSeparator,',');
} // function _translateFormulaToEnglish()

+ Here is the call graph for this function:

PHPExcel_Calculation::_translateFormulaToLocale (   $formula)

Definition at line 2000 of file Calculation.php.

References _translateFormula().

{
if (is_null(self::$functionReplaceFromExcel)) {
self::$functionReplaceFromExcel = array();
foreach(array_keys(self::$_localeFunctions) as $excelFunctionName) {
self::$functionReplaceFromExcel[] = '/(@?[^\w\.])'.preg_quote($excelFunctionName).'([\s]*\()/Ui';
}
foreach(array_keys(self::$_localeBoolean) as $excelBoolean) {
self::$functionReplaceFromExcel[] = '/(@?[^\w\.])'.preg_quote($excelBoolean).'([^\w\.])/Ui';
}
}
if (is_null(self::$functionReplaceToLocale)) {
self::$functionReplaceToLocale = array();
foreach(array_values(self::$_localeFunctions) as $localeFunctionName) {
self::$functionReplaceToLocale[] = '$1'.trim($localeFunctionName).'$2';
}
foreach(array_values(self::$_localeBoolean) as $localeBoolean) {
self::$functionReplaceToLocale[] = '$1'.trim($localeBoolean).'$2';
}
}
return self::_translateFormula(self::$functionReplaceFromExcel,self::$functionReplaceToLocale,$formula,',',self::$_localeArgumentSeparator);
} // function _translateFormulaToLocale()

+ Here is the call graph for this function:

static PHPExcel_Calculation::_translateSeparator (   $fromSeparator,
  $toSeparator,
  $formula,
$inBraces 
)
static

Definition at line 1949 of file Calculation.php.

Referenced by _translateFormula(), and PHPExcel_Reader_OOCalc\loadIntoExisting().

{
$strlen = mb_strlen($formula);
for ($i = 0; $i < $strlen; ++$i) {
$chr = mb_substr($formula,$i,1);
switch ($chr) {
case '{' : $inBraces = true;
break;
case '}' : $inBraces = false;
break;
case $fromSeparator :
if (!$inBraces) {
$formula = mb_substr($formula,0,$i).$toSeparator.mb_substr($formula,$i+1);
}
}
}
return $formula;
}

+ Here is the caller graph for this function:

static PHPExcel_Calculation::_unwrapResult (   $value)
static

Remove quotes used as a wrapper to identify string values.

Parameters
mixed$value
Returns
mixed

Definition at line 2099 of file Calculation.php.

References PHPExcel_Calculation_Functions\NaN().

Referenced by _executeBinaryComparisonOperation(), _processTokenStack(), _validateBinaryOperand(), calculateCellValue(), calculateFormula(), and PHPExcel_Reader_SYLK\loadIntoExisting().

{
if (is_string($value)) {
if ((isset($value{0})) && ($value{0} == '"') && (substr($value,-1) == '"')) {
return substr($value,1,-1);
}
// Convert numeric errors to NaN error
} else if((is_float($value)) && ((is_nan($value)) || (is_infinite($value)))) {
}
return $value;
} // function _unwrapResult()

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

PHPExcel_Calculation::_validateBinaryOperand (   $cellID,
$operand,
$stack 
)
private

Definition at line 3370 of file Calculation.php.

References _showTypeDetails(), _unwrapResult(), _writeDebug(), and PHPExcel_Shared_String\convertToNumberIfFraction().

Referenced by _executeNumericBinaryOperation().

{
// 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
if ($operand > '' && $operand{0} == '"') { $operand = self::_unwrapResult($operand); }
// 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->_writeDebug('Evaluation Result is '.$this->_showTypeDetails($operand));
return false;
// 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->_writeDebug('Evaluation Result is a '.$this->_showTypeDetails('#VALUE!'));
return false;
}
}
}
// return a true if the value of the operand is one that we can use in normal binary operations
return true;
} // function _validateBinaryOperand()

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static PHPExcel_Calculation::_wrapResult (   $value)
static

Wrap string values in quotes.

Parameters
mixed$value
Returns
mixed

Definition at line 2075 of file Calculation.php.

References PHPExcel_Calculation_Functions\NaN().

Referenced by PHPExcel_Calculation_Database\__filter(), _calculateFormulaValue(), PHPExcel_Calculation_Functions\_ifCondition(), _parseFormula(), PHPExcel_Calculation_Statistical\AVERAGEIF(), PHPExcel_Calculation_Statistical\COUNTIF(), PHPExcel_Calculation_Statistical\MAXIF(), PHPExcel_Calculation_Statistical\MINIF(), and PHPExcel_Calculation_MathTrig\SUMIF().

{
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
} else if((is_float($value)) && ((is_nan($value)) || (is_infinite($value)))) {
}
return $value;
} // function _wrapResult()

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

PHPExcel_Calculation::_writeDebug (   $message)
private

Definition at line 3551 of file Calculation.php.

Referenced by _calculateFormulaValue(), _executeBinaryComparisonOperation(), _executeNumericBinaryOperation(), _processTokenStack(), and _validateBinaryOperand().

{
// Only write the debug log if logging is enabled
if ($this->writeDebugLog) {
if ($this->echoDebugLog) {
echo implode(' -> ',$this->debugLogStack).' -> '.$message,'<br />';
}
$this->debugLog[] = implode(' -> ',$this->debugLogStack).' -> '.$message;
}
} // function _writeDebug()

+ Here is the caller graph for this function:

PHPExcel_Calculation::calculate ( PHPExcel_Cell  $pCell = null)

Calculate cell value (using formula from a cell ID) Retained for backward compatibility.

public

Parameters
PHPExcel_Cell$pCellCell to calculate
Returns
mixed
Exceptions
Exception

Definition at line 2123 of file Calculation.php.

References calculateCellValue().

{
try {
return $this->calculateCellValue($pCell);
} catch (Exception $e) {
throw(new Exception($e->getMessage()));
}
} // function calculate()

+ Here is the call graph for this function:

PHPExcel_Calculation::calculateCellValue ( PHPExcel_Cell  $pCell = null,
  $resetLog = true 
)

Calculate the value of a cell formula.

public

Parameters
PHPExcel_Cell$pCellCell to calculate
Boolean$resetLogFlag indicating whether the debug log should be reset or not
Returns
mixed
Exceptions
Exception

Definition at line 2141 of file Calculation.php.

References $returnArrayAsType, _calculateFormulaValue(), _unwrapResult(), PHPExcel_Calculation_Functions\flattenArray(), PHPExcel_Calculation_Functions\NaN(), RETURN_ARRAY_AS_ARRAY, and PHPExcel_Calculation_Functions\VALUE().

Referenced by calculate().

{
if ($resetLog) {
// Initialise the logging settings if requested
$this->formulaError = null;
$this->debugLog = $this->debugLogStack = array();
$this->_cyclicFormulaCount = 1;
self::$returnArrayAsType = self::RETURN_ARRAY_AS_ARRAY;
}
// Read the formula from the cell
if (is_null($pCell)) {
return null;
}
if ($resetLog) {
self::$returnArrayAsType = $returnArrayAsType;
}
// Execute the calculation for the cell formula
try {
$result = self::_unwrapResult($this->_calculateFormulaValue($pCell->getValue(), $pCell->getCoordinate(), $pCell));
} catch (Exception $e) {
throw(new Exception($e->getMessage()));
}
if ((is_array($result)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) {
if (self::$returnArrayAsType == self::RETURN_ARRAY_AS_ERROR) {
}
// 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);
if (!is_numeric($r)) { return PHPExcel_Calculation_Functions::VALUE(); }
if (is_array($result[$r])) {
$c = array_keys($result[$r]);
$c = array_shift($c);
if (!is_numeric($c)) {
}
}
}
$result = array_shift($testResult);
}
if (is_null($result)) {
return 0;
} elseif((is_float($result)) && ((is_nan($result)) || (is_infinite($result)))) {
}
return $result;
} // function calculateCellValue(

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

PHPExcel_Calculation::calculateFormula (   $formula,
  $cellID = null,
PHPExcel_Cell  $pCell = null 
)

Calculate the value of a formula.

Parameters
string$formulaFormula to parse
Returns
mixed
Exceptions
Exception

Definition at line 2225 of file Calculation.php.

References _calculateFormulaValue(), _unwrapResult(), and getCalculationCacheEnabled().

{
// Initialise the logging settings
$this->formulaError = null;
$this->debugLog = $this->debugLogStack = array();
// Disable calculation cacheing because it only applies to cell calculations, not straight formulae
// But don't actually flush any cache
$resetCache = $this->getCalculationCacheEnabled();
self::$_calculationCacheEnabled = false;
// Execute the calculation
try {
$result = self::_unwrapResult($this->_calculateFormulaValue($formula, $cellID, $pCell));
} catch (Exception $e) {
throw(new Exception($e->getMessage()));
}
// Reset calculation cacheing to its previous state
self::$_calculationCacheEnabled = $resetCache;
return $result;
} // function calculateFormula()

+ Here is the call graph for this function:

PHPExcel_Calculation::clearCalculationCache ( )

Clear calculation cache.

Definition at line 1835 of file Calculation.php.

Referenced by setCalculationCacheEnabled().

{
self::$_calculationCache = array();
} // function clearCalculationCache()

+ Here is the caller graph for this function:

PHPExcel_Calculation::disableCalculationCache ( )

Disable calculation cache.

Definition at line 1827 of file Calculation.php.

References setCalculationCacheEnabled().

{
} // function disableCalculationCache()

+ Here is the call graph for this function:

PHPExcel_Calculation::enableCalculationCache ( )

Enable calculation cache.

Definition at line 1819 of file Calculation.php.

References setCalculationCacheEnabled().

{
} // function enableCalculationCache()

+ Here is the call graph for this function:

PHPExcel_Calculation::extractCellRange ( $pRange = 'A1',
PHPExcel_Worksheet  $pSheet = null,
  $resetLog = true 
)

Extract range values.

Parameters
string&$pRangeString based range representation
PHPExcel_Worksheet$pSheetWorksheet
Returns
mixed Array of values in range if range contains more than one element. Otherwise, a single value is returned.
Exceptions
Exception

Definition at line 3578 of file Calculation.php.

References PHPExcel_Cell\extractAllCellReferencesInRange(), and PHPExcel_Worksheet\extractSheetTitle().

Referenced by _processTokenStack().

{
// Return value
$returnValue = array ();
// echo 'extractCellRange('.$pRange.')<br />';
if (!is_null($pSheet)) {
// echo 'Passed sheet name is '.$pSheet->getTitle().'<br />';
// echo 'Range reference is '.$pRange.'<br />';
if (strpos ($pRange, '!') !== false) {
// echo '$pRange reference includes sheet reference<br />';
$worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pRange, true);
$pSheet = $pSheet->getParent()->getSheetByName($worksheetReference[0]);
// echo 'New sheet name is '.$pSheet->getTitle().'<br />';
$pRange = $worksheetReference[1];
// echo 'Adjusted Range reference is '.$pRange.'<br />';
}
// Extract range
$pRange = $pSheet->getTitle().'!'.$pRange;
if (!isset($aReferences[1])) {
// Single cell in range
list($currentCol,$currentRow) = sscanf($aReferences[0],'%[A-Z]%d');
if ($pSheet->cellExists($aReferences[0])) {
$returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog);
} else {
$returnValue[$currentRow][$currentCol] = null;
}
} else {
// Extract cell data for all cells in the range
foreach ($aReferences as $reference) {
// Extract range
list($currentCol,$currentRow) = sscanf($reference,'%[A-Z]%d');
if ($pSheet->cellExists($reference)) {
$returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog);
} else {
$returnValue[$currentRow][$currentCol] = null;
}
}
}
}
// Return
return $returnValue;
} // function extractCellRange()

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

PHPExcel_Calculation::extractNamedRange ( $pRange = 'A1',
PHPExcel_Worksheet  $pSheet = null,
  $resetLog = true 
)

Extract range values.

Parameters
string&$pRangeString based range representation
PHPExcel_Worksheet$pSheetWorksheet
Returns
mixed Array of values in range if range contains more than one element. Otherwise, a single value is returned.
Exceptions
Exception

Definition at line 3634 of file Calculation.php.

References PHPExcel_Cell\coordinateFromString(), PHPExcel_Cell\extractAllCellReferencesInRange(), PHPExcel_Worksheet\extractSheetTitle(), PHPExcel_Calculation_Functions\REF(), PHPExcel_NamedRange\resolveRange(), and PHPExcel_Cell\splitRange().

Referenced by _processTokenStack().

{
// Return value
$returnValue = array ();
// echo 'extractNamedRange('.$pRange.')<br />';
if (!is_null($pSheet)) {
// echo 'Current sheet name is '.$pSheet->getTitle().'<br />';
// echo 'Range reference is '.$pRange.'<br />';
if (strpos ($pRange, '!') !== false) {
// echo '$pRange reference includes sheet reference<br />';
$worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pRange, true);
$pSheet = $pSheet->getParent()->getSheetByName($worksheetReference[0]);
// echo 'New sheet name is '.$pSheet->getTitle().'<br />';
$pRange = $worksheetReference[1];
// echo 'Adjusted Range reference is '.$pRange.'<br />';
}
// Named range?
$namedRange = PHPExcel_NamedRange::resolveRange($pRange, $pSheet);
if (!is_null($namedRange)) {
$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();
} elseif(ctype_digit($splitRange[0][0])) {
$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 {
}
// Extract range
// var_dump($aReferences);
if (!isset($aReferences[1])) {
// Single cell (or single column or row) in range
list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($aReferences[0]);
if ($pSheet->cellExists($aReferences[0])) {
$returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog);
} else {
$returnValue[$currentRow][$currentCol] = null;
}
} else {
// Extract cell data for all cells in the range
foreach ($aReferences as $reference) {
// Extract range
list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($reference);
// echo 'NAMED RANGE: $currentCol='.$currentCol.' $currentRow='.$currentRow.'<br />';
if ($pSheet->cellExists($reference)) {
$returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog);
} else {
$returnValue[$currentRow][$currentCol] = null;
}
}
}
// print_r($returnValue);
// echo '<br />';
}
// Return
return $returnValue;
} // function extractNamedRange()

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static PHPExcel_Calculation::flushInstance ( )
static

Flush the calculation cache for any existing instance of this class but only if a PHPExcel_Calculation instance exists.

public

Returns
null

Definition at line 1726 of file Calculation.php.

{
if (isset(self::$_instance) && !is_null(self::$_instance)) {
self::$_instance->clearCalculationCache();
}
} // function flushInstance()
static PHPExcel_Calculation::getArrayReturnType ( )
static

Return the Array Return Type (Array or Value of first element in the array)

public

Returns
string $returnType Array return type

Definition at line 1788 of file Calculation.php.

References $returnArrayAsType.

Referenced by PHPExcel_Writer_CSV\save(), PHPExcel_Writer_HTML\save(), and PHPExcel_Writer_PDF\save().

{
} // function getExcelCalendar()

+ Here is the caller graph for this function:

PHPExcel_Calculation::getCalculationCacheEnabled ( )

Is calculation caching enabled?

public

Returns
boolean

Definition at line 1799 of file Calculation.php.

References $_calculationCacheEnabled.

Referenced by calculateFormula().

{
} // function getCalculationCacheEnabled()

+ Here is the caller graph for this function:

PHPExcel_Calculation::getCalculationCacheExpirationTime ( )

Get calculation cache expiration time.

Returns
float

Definition at line 1845 of file Calculation.php.

References $_calculationCacheExpirationTime.

{
} // getCalculationCacheExpirationTime()
static PHPExcel_Calculation::getFALSE ( )
static

Return the locale-specific translation of FALSE.

public

Returns
string locale-specific translation of FALSE

Definition at line 1760 of file Calculation.php.

Referenced by PHPExcel_Cell_AdvancedValueBinder\bindValue(), PHPExcel_Calculation_Logical\LOGICAL_AND(), PHPExcel_Calculation_Logical\LOGICAL_OR(), and PHPExcel_Calculation_Logical\NOT().

{
return self::$_localeBoolean['FALSE'];
}

+ Here is the caller graph for this function:

PHPExcel_Calculation::getLocale ( )

Get the currently defined locale code.

Returns
string

Definition at line 1867 of file Calculation.php.

References $_localeLanguage.

{
} // function getLocale()
static PHPExcel_Calculation::getTRUE ( )
static

Return the locale-specific translation of TRUE.

public

Returns
string locale-specific translation of TRUE

Definition at line 1750 of file Calculation.php.

Referenced by PHPExcel_Cell_AdvancedValueBinder\bindValue(), PHPExcel_Calculation_Logical\LOGICAL_AND(), PHPExcel_Calculation_Logical\LOGICAL_OR(), and PHPExcel_Calculation_Logical\NOT().

{
return self::$_localeBoolean['TRUE'];
}

+ Here is the caller graph for this function:

PHPExcel_Calculation::isImplemented (   $pFunction = '')

Is a specific function implemented?

Parameters
string$pFunctionFunction Name
Returns
boolean

Definition at line 3716 of file Calculation.php.

{
$pFunction = strtoupper ($pFunction);
if (isset(self::$_PHPExcelFunctions[$pFunction])) {
return (self::$_PHPExcelFunctions[$pFunction]['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY');
} else {
return false;
}
} // function isImplemented()
PHPExcel_Calculation::listAllFunctionNames ( )

Get a list of all Excel function names.

Returns
array

Definition at line 3754 of file Calculation.php.

{
return array_keys(self::$_PHPExcelFunctions);
} // function listAllFunctionNames()
PHPExcel_Calculation::listFunctionNames ( )

Get a list of implemented Excel function names.

Returns
array

Definition at line 3763 of file Calculation.php.

{
// Return value
$returnValue = array();
// Loop functions
foreach(self::$_PHPExcelFunctions as $functionName => $function) {
if ($function['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY') {
$returnValue[] = $functionName;
}
}
// Return
return $returnValue;
} // function listFunctionNames()
PHPExcel_Calculation::listFunctions ( )

Get a list of all implemented functions as an array of function objects.

Returns
array of PHPExcel_Calculation_Function

Definition at line 3731 of file Calculation.php.

{
// Return value
$returnValue = array();
// Loop functions
foreach(self::$_PHPExcelFunctions as $functionName => $function) {
if ($function['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY') {
$returnValue[$functionName] = new PHPExcel_Calculation_Function($function['category'],
$functionName,
$function['functionCall']
);
}
}
// Return
return $returnValue;
} // function listFunctions()
PHPExcel_Calculation::parseFormula (   $formula)

Validate and parse a formula string.

Parameters
string$formulaFormula to parse
Returns
array
Exceptions
Exception

Definition at line 2205 of file Calculation.php.

References _parseFormula().

{
// Basic validation that this is indeed a formula
// We return an empty array if not
$formula = trim($formula);
if ((!isset($formula{0})) || ($formula{0} != '=')) return array();
$formula = ltrim(substr($formula,1));
if (!isset($formula{0})) return array();
// Parse the formula and return the token stack
return $this->_parseFormula($formula);
} // function parseFormula()

+ Here is the call graph for this function:

static PHPExcel_Calculation::setArrayReturnType (   $returnType)
static

Set the Array Return Type (Array or Value of first element in the array)

public

Parameters
string$returnTypeArray return type
Returns
boolean Success or failure

Definition at line 1771 of file Calculation.php.

Referenced by PHPExcel_Writer_CSV\save(), PHPExcel_Writer_HTML\save(), and PHPExcel_Writer_PDF\save().

{
if (($returnType == self::RETURN_ARRAY_AS_VALUE) ||
($returnType == self::RETURN_ARRAY_AS_ERROR) ||
($returnType == self::RETURN_ARRAY_AS_ARRAY)) {
self::$returnArrayAsType = $returnType;
return true;
}
return false;
} // function setExcelCalendar()

+ Here is the caller graph for this function:

PHPExcel_Calculation::setCalculationCacheEnabled (   $pValue = true)

Enable/disable calculation cache.

public

Parameters
boolean$pValue

Definition at line 1810 of file Calculation.php.

References clearCalculationCache().

Referenced by disableCalculationCache(), and enableCalculationCache().

{
self::$_calculationCacheEnabled = $pValue;
} // function setCalculationCacheEnabled()

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

PHPExcel_Calculation::setCalculationCacheExpirationTime (   $pValue = 15)

Set calculation cache expiration time.

Parameters
float$pValue

Definition at line 1855 of file Calculation.php.

{
self::$_calculationCacheExpirationTime = $pValue;
} // function setCalculationCacheExpirationTime()
PHPExcel_Calculation::setLocale (   $locale = 'en_us')

Set the locale code.

Returns
boolean

Definition at line 1877 of file Calculation.php.

{
// Identify our locale and language
$language = $locale = strtolower($locale);
if (strpos($locale,'_') !== false) {
list($language) = explode('_',$locale);
}
// Test whether we have any language data for this language (any locale)
if (in_array($language,self::$_validLocaleLanguages)) {
// 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
$functionNamesFile = PHPEXCEL_ROOT . 'PHPExcel/locale/'.str_replace('_','/',$locale).'/functions';
if (!file_exists($functionNamesFile)) {
// If there isn't a locale specific function file, look for a language specific function file
$functionNamesFile = PHPEXCEL_ROOT . 'PHPExcel/locale/'.$language.'/functions';
if (!file_exists($functionNamesFile)) {
return false;
}
}
// Retrieve the list of locale or language specific function names
$localeFunctions = file($functionNamesFile,FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($localeFunctions as $localeFunction) {
list($localeFunction) = explode('##',$localeFunction); // Strip out comments
if (strpos($localeFunction,'=') !== false) {
list($fName,$lfName) = explode('=',$localeFunction);
$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
if (isset(self::$_localeFunctions['TRUE'])) { self::$_localeBoolean['TRUE'] = self::$_localeFunctions['TRUE']; }
if (isset(self::$_localeFunctions['FALSE'])) { self::$_localeBoolean['FALSE'] = self::$_localeFunctions['FALSE']; }
$configFile = PHPEXCEL_ROOT . 'PHPExcel/locale/'.str_replace('_','/',$locale).'/config';
if (!file_exists($configFile)) {
$configFile = PHPEXCEL_ROOT . 'PHPExcel/locale/'.$language.'/config';
}
if (file_exists($configFile)) {
$localeSettings = file($configFile,FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($localeSettings as $localeSetting) {
list($localeSetting) = explode('##',$localeSetting); // Strip out comments
if (strpos($localeSetting,'=') !== false) {
list($settingName,$settingValue) = explode('=',$localeSetting);
$settingName = strtoupper(trim($settingName));
switch ($settingName) {
case 'ARGUMENTSEPARATOR' :
self::$_localeArgumentSeparator = trim($settingValue);
break;
}
}
}
}
}
self::$functionReplaceFromExcel = self::$functionReplaceToExcel =
self::$functionReplaceFromLocale = self::$functionReplaceToLocale = null;
self::$_localeLanguage = $locale;
return true;
}
return false;
} // function setLocale()

Field Documentation

PHPExcel_Calculation::$_binaryOperators
staticprivate
Initial value:
array('+' => true, '-' => true, '*' => true, '/' => true,
'^' => true, '&' => true, '>' => true, '<' => true,
'=' => true, '>=' => true, '<=' => true, '<>' => true,
'|' => true, ':' => true
)

Definition at line 146 of file Calculation.php.

PHPExcel_Calculation::$_calculationCache = array ()
staticprivate

Definition at line 105 of file Calculation.php.

PHPExcel_Calculation::$_calculationCacheEnabled = true
staticprivate

Definition at line 114 of file Calculation.php.

Referenced by getCalculationCacheEnabled().

PHPExcel_Calculation::$_calculationCacheExpirationTime = 15
staticprivate

Definition at line 123 of file Calculation.php.

Referenced by getCalculationCacheExpirationTime().

PHPExcel_Calculation::$_controlFunctions
staticprivate
Initial value:
array(
'MKMATRIX' => array('argumentCount' => '*',
'functionCall' => 'self::_mkMatrix'
)
)

Definition at line 1674 of file Calculation.php.

PHPExcel_Calculation::$_cyclicFormulaCell = ''
private

Definition at line 214 of file Calculation.php.

PHPExcel_Calculation::$_cyclicFormulaCount = 0
private

Definition at line 213 of file Calculation.php.

Referenced by _calculateFormulaValue().

PHPExcel_Calculation::$_ExcelConstants
staticprivate
Initial value:
array('TRUE' => true,
'FALSE' => false,
'NULL' => null
)

Definition at line 233 of file Calculation.php.

PHPExcel_Calculation::$_instance
staticprivate

Definition at line 96 of file Calculation.php.

Referenced by getInstance().

PHPExcel_Calculation::$_localeArgumentSeparator = ','
staticprivate

Definition at line 224 of file Calculation.php.

PHPExcel_Calculation::$_localeBoolean
static
Initial value:
array( 'TRUE' => 'TRUE',
'FALSE' => 'FALSE',
'NULL' => 'NULL'
)

Definition at line 226 of file Calculation.php.

PHPExcel_Calculation::$_localeFunctions = array()
staticprivate

Definition at line 225 of file Calculation.php.

PHPExcel_Calculation::$_localeLanguage = 'en_us'
staticprivate

Definition at line 221 of file Calculation.php.

Referenced by getLocale().

PHPExcel_Calculation::$_operators
staticprivate
Initial value:
array('+' => true, '-' => true, '*' => true, '/' => true,
'^' => true, '&' => true, '%' => false, '~' => false,
'>' => true, '<' => true, '=' => true, '>=' => true,
'<=' => true, '<>' => true, '|' => true, ':' => true
)

Definition at line 133 of file Calculation.php.

PHPExcel_Calculation::$_PHPExcelFunctions
staticprivate

Definition at line 239 of file Calculation.php.

PHPExcel_Calculation::$_savedPrecision = 12
private

Definition at line 218 of file Calculation.php.

PHPExcel_Calculation::$_validLocaleLanguages
staticprivate
Initial value:
array( 'en'
)

Definition at line 222 of file Calculation.php.

PHPExcel_Calculation::$cyclicFormulaCount = 0

Definition at line 215 of file Calculation.php.

PHPExcel_Calculation::$debugLog = array()

Definition at line 212 of file Calculation.php.

PHPExcel_Calculation::$debugLogStack = array()
private

Definition at line 203 of file Calculation.php.

PHPExcel_Calculation::$echoDebugLog = false

Definition at line 193 of file Calculation.php.

PHPExcel_Calculation::$formulaError = null

Definition at line 170 of file Calculation.php.

PHPExcel_Calculation::$functionReplaceFromExcel = null
staticprivate

Definition at line 1997 of file Calculation.php.

PHPExcel_Calculation::$functionReplaceFromLocale = null
staticprivate

Definition at line 2026 of file Calculation.php.

PHPExcel_Calculation::$functionReplaceToExcel = null
staticprivate

Definition at line 2027 of file Calculation.php.

PHPExcel_Calculation::$functionReplaceToLocale = null
staticprivate

Definition at line 1998 of file Calculation.php.

PHPExcel_Calculation::$returnArrayAsType = self::RETURN_ARRAY_AS_VALUE
staticprivate

Definition at line 87 of file Calculation.php.

Referenced by calculateCellValue(), and getArrayReturnType().

PHPExcel_Calculation::$suppressFormulaErrors = false

Definition at line 161 of file Calculation.php.

PHPExcel_Calculation::$writeDebugLog = false

Definition at line 181 of file Calculation.php.

const PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF = CALCULATION_REGEXP_CELLREF
const PHPExcel_Calculation::CALCULATION_REGEXP_ERROR = '\#[A-Z][A-Z0_\/]*[!\?]?'

Definition at line 79 of file Calculation.php.

const PHPExcel_Calculation::CALCULATION_REGEXP_FUNCTION = '@?([A-Z][A-Z0-9\.]*)[\s]*\('

Definition at line 73 of file Calculation.php.

const PHPExcel_Calculation::CALCULATION_REGEXP_NAMEDRANGE = CALCULATION_REGEXP_NAMEDRANGE

Definition at line 77 of file Calculation.php.

Referenced by PHPExcel_Worksheet\cellExists(), and PHPExcel_Worksheet\getCell().

const PHPExcel_Calculation::CALCULATION_REGEXP_NUMBER = '[-+]?\d*\.?\d+(e[-+]?\d+)?'

Constants.

Regular Expressions

Definition at line 67 of file Calculation.php.

Referenced by PHPExcel_Cell_AdvancedValueBinder\bindValue().

const PHPExcel_Calculation::CALCULATION_REGEXP_OPENBRACE = '\('

Definition at line 71 of file Calculation.php.

const PHPExcel_Calculation::CALCULATION_REGEXP_STRING = '"(?:[^"]|"")*"'

Definition at line 69 of file Calculation.php.

const PHPExcel_Calculation::RETURN_ARRAY_AS_ARRAY = 'array'

Definition at line 85 of file Calculation.php.

Referenced by calculateCellValue().

const PHPExcel_Calculation::RETURN_ARRAY_AS_ERROR = 'error'

constants

Definition at line 83 of file Calculation.php.

const PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE = 'value'

The documentation for this class was generated from the following file: