ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
PHPExcel_Calculation Class Reference
+ Collaboration diagram for PHPExcel_Calculation:

Public Member Functions

 __destruct ()
 
 flushInstance ()
 Flush the calculation cache for any existing instance of this class but only if a PHPExcel_Calculation instance exists. More...
 
 getDebugLog ()
 Get the debuglog for this claculation engine instance. More...
 
 __clone ()
 __clone implementation. More...
 
 getCalculationCacheEnabled ()
 Is calculation caching enabled? More...
 
 setCalculationCacheEnabled ($pValue=TRUE)
 Enable/disable calculation cache. More...
 
 enableCalculationCache ()
 Enable calculation cache. More...
 
 disableCalculationCache ()
 Disable calculation cache. More...
 
 clearCalculationCache ()
 Clear calculation cache. More...
 
 clearCalculationCacheForWorksheet ($worksheetName)
 Clear calculation cache for a specified worksheet. More...
 
 renameCalculationCacheForWorksheet ($fromWorksheetName, $toWorksheetName)
 Rename calculation cache for a specified worksheet. More...
 
 getLocale ()
 Get the currently defined locale code. More...
 
 setLocale ($locale='en_us')
 Set the locale code. More...
 
 _translateFormulaToLocale ($formula)
 
 _translateFormulaToEnglish ($formula)
 
 calculate (PHPExcel_Cell $pCell=NULL)
 Calculate cell value (using formula from a cell ID) Retained for backward compatibility. More...
 
 calculateCellValue (PHPExcel_Cell $pCell=NULL, $resetLog=TRUE)
 Calculate the value of a cell formula. More...
 
 parseFormula ($formula)
 Validate and parse a formula string. More...
 
 calculateFormula ($formula, $cellID=NULL, PHPExcel_Cell $pCell=NULL)
 Calculate the value of a formula. More...
 
 getValueFromCache ($cellReference, &$cellValue)
 
 saveValueToCache ($cellReference, $cellValue)
 
 _calculateFormulaValue ($formula, $cellID=null, PHPExcel_Cell $pCell=null)
 Parse a cell formula and calculate its value. More...
 
 extractCellRange (&$pRange='A1', PHPExcel_Worksheet $pSheet=NULL, $resetLog=TRUE)
 Extract range values. More...
 
 extractNamedRange (&$pRange='A1', PHPExcel_Worksheet $pSheet=NULL, $resetLog=TRUE)
 Extract range values. More...
 
 isImplemented ($pFunction='')
 Is a specific function implemented? More...
 
 listFunctions ()
 Get a list of all implemented functions as an array of function objects. More...
 
 listAllFunctionNames ()
 Get a list of all Excel function names. More...
 
 listFunctionNames ()
 Get a list of implemented Excel function names. More...
 

Static Public Member Functions

static getInstance (PHPExcel $workbook=NULL)
 Get an instance of this class. More...
 
static unsetInstance (PHPExcel $workbook=NULL)
 Unset an instance of this class. More...
 
static getTRUE ()
 Return the locale-specific translation of TRUE. More...
 
static getFALSE ()
 Return the locale-specific translation of FALSE. More...
 
static setArrayReturnType ($returnType)
 Set the Array Return Type (Array or Value of first element in the array) More...
 
static getArrayReturnType ()
 Return the Array Return Type (Array or Value of first element in the array) More...
 
static _translateSeparator ($fromSeparator, $toSeparator, $formula, &$inBraces)
 
static _localeFunc ($function)
 
static _wrapResult ($value)
 Wrap string values in quotes. More...
 
static _unwrapResult ($value)
 Remove quotes used as a wrapper to identify string values. More...
 
static _getMatrixDimensions (&$matrix)
 Read the dimensions of a matrix, and re-index it with straight numeric keys starting from row 0, column 0. More...
 

Data Fields

const CALCULATION_REGEXP_NUMBER = '[-+]?\d*\.?\d+(e[-+]?\d+)?'
 Constants
More...
 
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 More...
 
const RETURN_ARRAY_AS_VALUE = 'value'
 
const RETURN_ARRAY_AS_ARRAY = 'array'
 
 $suppressFormulaErrors = FALSE
 
 $formulaError = NULL
 
 $cyclicFormulaCount = 1
 

Static Public Attributes

static $_localeBoolean
 

Protected Member Functions

 _raiseFormulaError ($errorMessage)
 

Private Member Functions

 __construct (PHPExcel $workbook=NULL)
 
 _showValue ($value)
 Format details of an operand for display in the log (based on operand type) More...
 
 _showTypeDetails ($value)
 Format type and details of an operand for display in the log (based on operand type) More...
 
 _convertMatrixReferences ($formula)
 
 _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)
 
 strcmpLowercaseFirst ($str1, $str2)
 Compare two strings in the same way as strcmp() except that lowercase come before uppercase letters. More...
 
 _executeNumericBinaryOperation ($cellID, $operand1, $operand2, $operation, $matrixFunction, &$stack)
 

Static Private Member Functions

static _loadLocales ()
 
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. More...
 
static _resizeMatricesShrink (&$matrix1, &$matrix2, $matrix1Rows, $matrix1Columns, $matrix2Rows, $matrix2Columns)
 Ensure that paired matrix operands are both matrices of the same size. More...
 
static _resizeMatricesExtend (&$matrix1, &$matrix2, $matrix1Rows, $matrix1Columns, $matrix2Rows, $matrix2Columns)
 Ensure that paired matrix operands are both matrices of the same size. More...
 
static _mkMatrix ()
 
static _dataTestReference (&$operandData)
 

Private Attributes

 $_workbook
 
 $_calculationCache = array ()
 
 $_calculationCacheEnabled = TRUE
 
 $debugLog
 
 $_cyclicReferenceStack
 
 $_cellStack = array()
 
 $_cyclicFormulaCount = 1
 
 $_cyclicFormulaCell = ''
 
 $_savedPrecision = 14
 

Static Private Attributes

static $returnArrayAsType = self::RETURN_ARRAY_AS_VALUE
 
static $_instance
 
static $_workbookSets
 
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
 
static $_operatorAssociativity
 
static $_comparisonOperators = array('>' => TRUE, '<' => TRUE, '=' => TRUE, '>=' => TRUE, '<=' => TRUE, '<>' => TRUE)
 
static $_operatorPrecedence
 

Detailed Description

Definition at line 62 of file Calculation.php.

Constructor & Destructor Documentation

◆ __construct()

PHPExcel_Calculation::__construct ( PHPExcel  $workbook = NULL)
private

Definition at line 1723 of file Calculation.php.

1723 {
1724 $setPrecision = (PHP_INT_SIZE == 4) ? 14 : 16;
1725 $this->_savedPrecision = ini_get('precision');
1726 if ($this->_savedPrecision < $setPrecision) {
1727 ini_set('precision',$setPrecision);
1728 }
1729 $this->delta = 1 * pow(10, -$setPrecision);
1730
1731 if ($workbook !== NULL) {
1732 self::$_workbookSets[$workbook->getID()] = $this;
1733 }
1734
1735 $this->_workbook = $workbook;
1736 $this->_cyclicReferenceStack = new PHPExcel_CalcEngine_CyclicReferenceStack();
1737 $this->_debugLog = new PHPExcel_CalcEngine_Logger($this->_cyclicReferenceStack);
1738 } // function __construct()
getID()
Return the unique ID value assigned to this spreadsheet workbook.
Definition: PHPExcel.php:1135

◆ __destruct()

PHPExcel_Calculation::__destruct ( )

Definition at line 1741 of file Calculation.php.

1741 {
1742 if ($this->_savedPrecision != ini_get('precision')) {
1743 ini_set('precision',$this->_savedPrecision);
1744 }
1745 }

Member Function Documentation

◆ __clone()

PHPExcel_Calculation::__clone ( )
final

__clone implementation.

Cloning should not be allowed in a Singleton!

@access public

Exceptions
PHPExcel_Calculation_Exception

Definition at line 1822 of file Calculation.php.

1822 {
1823 throw new PHPExcel_Calculation_Exception ('Cloning the calculation engine is not allowed!');
1824 } // function __clone()

◆ _calculateFormulaValue()

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
PHPExcel_Calculation_Exception

Definition at line 2375 of file Calculation.php.

2375 {
2376 $cellValue = null;
2377
2378 // Basic validation that this is indeed a formula
2379 // We simply return the cell value if not
2380 $formula = trim($formula);
2381 if ($formula{0} != '=') return self::_wrapResult($formula);
2382 $formula = ltrim(substr($formula, 1));
2383 if (!isset($formula{0})) return self::_wrapResult($formula);
2384
2385 $pCellParent = ($pCell !== NULL) ? $pCell->getWorksheet() : NULL;
2386 $wsTitle = ($pCellParent !== NULL) ? $pCellParent->getTitle() : "\x00Wrk";
2387 $wsCellReference = $wsTitle . '!' . $cellID;
2388
2389 if (($cellID !== NULL) && ($this->getValueFromCache($wsCellReference, $cellValue))) {
2390 return $cellValue;
2391 }
2392
2393 if (($wsTitle{0} !== "\x00") && ($this->_cyclicReferenceStack->onStack($wsCellReference))) {
2394 if ($this->cyclicFormulaCount <= 0) {
2395 $this->_cyclicFormulaCell = '';
2396 return $this->_raiseFormulaError('Cyclic Reference in Formula');
2397 } elseif ($this->_cyclicFormulaCell === $wsCellReference) {
2399 if ($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) {
2400 $this->_cyclicFormulaCell = '';
2401 return $cellValue;
2402 }
2403 } elseif ($this->_cyclicFormulaCell == '') {
2404 if ($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) {
2405 return $cellValue;
2406 }
2407 $this->_cyclicFormulaCell = $wsCellReference;
2408 }
2409 }
2410
2411 // Parse the formula onto the token stack and calculate the value
2412 $this->_cyclicReferenceStack->push($wsCellReference);
2413 $cellValue = $this->_processTokenStack($this->_parseFormula($formula, $pCell), $cellID, $pCell);
2414 $this->_cyclicReferenceStack->pop();
2415
2416 // Save to calculation cache
2417 if ($cellID !== NULL) {
2418 $this->saveValueToCache($wsCellReference, $cellValue);
2419 }
2420
2421 // Return the calculated value
2422 return $cellValue;
2423 } // function _calculateFormulaValue()
_raiseFormulaError($errorMessage)
_processTokenStack($tokens, $cellID=NULL, PHPExcel_Cell $pCell=NULL)
saveValueToCache($cellReference, $cellValue)
static _wrapResult($value)
Wrap string values in quotes.
_parseFormula($formula, PHPExcel_Cell $pCell=NULL)
getValueFromCache($cellReference, &$cellValue)
getWorksheet()
Get parent worksheet.
Definition: Cell.php:488

References $_cyclicFormulaCount, _parseFormula(), _processTokenStack(), _raiseFormulaError(), _wrapResult(), getValueFromCache(), and saveValueToCache().

Referenced by calculateCellValue(), and calculateFormula().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _checkMatrixOperands()

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 2438 of file Calculation.php.

2438 {
2439 // Examine each of the two operands, and turn them into an array if they aren't one already
2440 // Note that this function should only be called if one or both of the operand is already an array
2441 if (!is_array($operand1)) {
2442 list($matrixRows,$matrixColumns) = self::_getMatrixDimensions($operand2);
2443 $operand1 = array_fill(0,$matrixRows,array_fill(0,$matrixColumns,$operand1));
2444 $resize = 0;
2445 } elseif (!is_array($operand2)) {
2446 list($matrixRows,$matrixColumns) = self::_getMatrixDimensions($operand1);
2447 $operand2 = array_fill(0,$matrixRows,array_fill(0,$matrixColumns,$operand2));
2448 $resize = 0;
2449 }
2450
2451 list($matrix1Rows,$matrix1Columns) = self::_getMatrixDimensions($operand1);
2452 list($matrix2Rows,$matrix2Columns) = self::_getMatrixDimensions($operand2);
2453 if (($matrix1Rows == $matrix2Columns) && ($matrix2Rows == $matrix1Columns)) {
2454 $resize = 1;
2455 }
2456
2457 if ($resize == 2) {
2458 // Given two matrices of (potentially) unequal size, convert the smaller in each dimension to match the larger
2459 self::_resizeMatricesExtend($operand1,$operand2,$matrix1Rows,$matrix1Columns,$matrix2Rows,$matrix2Columns);
2460 } elseif ($resize == 1) {
2461 // Given two matrices of (potentially) unequal size, convert the larger in each dimension to match the smaller
2462 self::_resizeMatricesShrink($operand1,$operand2,$matrix1Rows,$matrix1Columns,$matrix2Rows,$matrix2Columns);
2463 }
2464 return array( $matrix1Rows,$matrix1Columns,$matrix2Rows,$matrix2Columns);
2465 } // function _checkMatrixOperands()
static _resizeMatricesExtend(&$matrix1, &$matrix2, $matrix1Rows, $matrix1Columns, $matrix2Rows, $matrix2Columns)
Ensure that paired matrix operands are both matrices 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 _getMatrixDimensions(&$matrix)
Read the dimensions of a matrix, and re-index it with straight numeric keys starting from row 0,...

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

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

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _convertMatrixReferences()

PHPExcel_Calculation::_convertMatrixReferences (   $formula)
private

Definition at line 2652 of file Calculation.php.

2652 {
2653 static $matrixReplaceFrom = array('{',';','}');
2654 static $matrixReplaceTo = array('MKMATRIX(MKMATRIX(','),MKMATRIX(','))');
2655
2656 // Convert any Excel matrix references to the MKMATRIX() function
2657 if (strpos($formula,'{') !== FALSE) {
2658 // If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators
2659 if (strpos($formula,'"') !== FALSE) {
2660 // So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded
2661 // the formula
2662 $temp = explode('"',$formula);
2663 // Open and Closed counts used for trapping mismatched braces in the formula
2664 $openCount = $closeCount = 0;
2665 $i = FALSE;
2666 foreach($temp as &$value) {
2667 // Only count/replace in alternating array entries
2668 if ($i = !$i) {
2669 $openCount += substr_count($value,'{');
2670 $closeCount += substr_count($value,'}');
2671 $value = str_replace($matrixReplaceFrom,$matrixReplaceTo,$value);
2672 }
2673 }
2674 unset($value);
2675 // Then rebuild the formula string
2676 $formula = implode('"',$temp);
2677 } else {
2678 // If there's no quoted strings, then we do a simple count/replace
2679 $openCount = substr_count($formula,'{');
2680 $closeCount = substr_count($formula,'}');
2681 $formula = str_replace($matrixReplaceFrom,$matrixReplaceTo,$formula);
2682 }
2683 // Trap for mismatched braces and trigger an appropriate error
2684 if ($openCount < $closeCount) {
2685 if ($openCount > 0) {
2686 return $this->_raiseFormulaError("Formula Error: Mismatched matrix braces '}'");
2687 } else {
2688 return $this->_raiseFormulaError("Formula Error: Unexpected '}' encountered");
2689 }
2690 } elseif ($openCount > $closeCount) {
2691 if ($closeCount > 0) {
2692 return $this->_raiseFormulaError("Formula Error: Mismatched matrix braces '{'");
2693 } else {
2694 return $this->_raiseFormulaError("Formula Error: Unexpected '{' encountered");
2695 }
2696 }
2697 }
2698
2699 return $formula;
2700 } // function _convertMatrixReferences()

References _raiseFormulaError().

Referenced by _parseFormula().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _dataTestReference()

static PHPExcel_Calculation::_dataTestReference ( $operandData)
staticprivate

Definition at line 3082 of file Calculation.php.

3083 {
3084 $operand = $operandData['value'];
3085 if (($operandData['reference'] === NULL) && (is_array($operand))) {
3086 $rKeys = array_keys($operand);
3087 $rowKey = array_shift($rKeys);
3088 $cKeys = array_keys(array_keys($operand[$rowKey]));
3089 $colKey = array_shift($cKeys);
3090 if (ctype_upper($colKey)) {
3091 $operandData['reference'] = $colKey.$rowKey;
3092 }
3093 }
3094 return $operand;
3095 }

Referenced by _processTokenStack().

+ Here is the caller graph for this function:

◆ _executeBinaryComparisonOperation()

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

Definition at line 3532 of file Calculation.php.

3532 {
3533 // If we're dealing with matrix operations, we want a matrix result
3534 if ((is_array($operand1)) || (is_array($operand2))) {
3535 $result = array();
3536 if ((is_array($operand1)) && (!is_array($operand2))) {
3537 foreach($operand1 as $x => $operandData) {
3538 $this->_debugLog->writeDebugLog('Evaluating Comparison ', $this->_showValue($operandData), ' ', $operation, ' ', $this->_showValue($operand2));
3539 $this->_executeBinaryComparisonOperation($cellID,$operandData,$operand2,$operation,$stack);
3540 $r = $stack->pop();
3541 $result[$x] = $r['value'];
3542 }
3543 } elseif ((!is_array($operand1)) && (is_array($operand2))) {
3544 foreach($operand2 as $x => $operandData) {
3545 $this->_debugLog->writeDebugLog('Evaluating Comparison ', $this->_showValue($operand1), ' ', $operation, ' ', $this->_showValue($operandData));
3546 $this->_executeBinaryComparisonOperation($cellID,$operand1,$operandData,$operation,$stack);
3547 $r = $stack->pop();
3548 $result[$x] = $r['value'];
3549 }
3550 } else {
3551 if (!$recursingArrays) { self::_checkMatrixOperands($operand1,$operand2,2); }
3552 foreach($operand1 as $x => $operandData) {
3553 $this->_debugLog->writeDebugLog('Evaluating Comparison ', $this->_showValue($operandData), ' ', $operation, ' ', $this->_showValue($operand2[$x]));
3554 $this->_executeBinaryComparisonOperation($cellID,$operandData,$operand2[$x],$operation,$stack,TRUE);
3555 $r = $stack->pop();
3556 $result[$x] = $r['value'];
3557 }
3558 }
3559 // Log the result details
3560 $this->_debugLog->writeDebugLog('Comparison Evaluation Result is ', $this->_showTypeDetails($result));
3561 // And push the result onto the stack
3562 $stack->push('Array',$result);
3563 return TRUE;
3564 }
3565
3566 // Simple validate the two operands if they are string values
3567 if (is_string($operand1) && $operand1 > '' && $operand1{0} == '"') { $operand1 = self::_unwrapResult($operand1); }
3568 if (is_string($operand2) && $operand2 > '' && $operand2{0} == '"') { $operand2 = self::_unwrapResult($operand2); }
3569
3570 // Use case insensitive comparaison if not OpenOffice mode
3572 {
3573 if (is_string($operand1)) {
3574 $operand1 = strtoupper($operand1);
3575 }
3576
3577 if (is_string($operand2)) {
3578 $operand2 = strtoupper($operand2);
3579 }
3580 }
3581
3582 $useLowercaseFirstComparison = is_string($operand1) && is_string($operand2) && PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE;
3583
3584 // execute the necessary operation
3585 switch ($operation) {
3586 // Greater than
3587 case '>':
3588 if ($useLowercaseFirstComparison) {
3589 $result = $this->strcmpLowercaseFirst($operand1, $operand2) > 0;
3590 } else {
3591 $result = ($operand1 > $operand2);
3592 }
3593 break;
3594 // Less than
3595 case '<':
3596 if ($useLowercaseFirstComparison) {
3597 $result = $this->strcmpLowercaseFirst($operand1, $operand2) < 0;
3598 } else {
3599 $result = ($operand1 < $operand2);
3600 }
3601 break;
3602 // Equality
3603 case '=':
3604 if (is_numeric($operand1) && is_numeric($operand2)) {
3605 $result = (abs($operand1 - $operand2) < $this->delta);
3606 } else {
3607 $result = strcmp($operand1, $operand2) == 0;
3608 }
3609 break;
3610 // Greater than or equal
3611 case '>=':
3612 if (is_numeric($operand1) && is_numeric($operand2)) {
3613 $result = ((abs($operand1 - $operand2) < $this->delta) || ($operand1 > $operand2));
3614 } elseif ($useLowercaseFirstComparison) {
3615 $result = $this->strcmpLowercaseFirst($operand1, $operand2) >= 0;
3616 } else {
3617 $result = strcmp($operand1, $operand2) >= 0;
3618 }
3619 break;
3620 // Less than or equal
3621 case '<=':
3622 if (is_numeric($operand1) && is_numeric($operand2)) {
3623 $result = ((abs($operand1 - $operand2) < $this->delta) || ($operand1 < $operand2));
3624 } elseif ($useLowercaseFirstComparison) {
3625 $result = $this->strcmpLowercaseFirst($operand1, $operand2) <= 0;
3626 } else {
3627 $result = strcmp($operand1, $operand2) <= 0;
3628 }
3629 break;
3630 // Inequality
3631 case '<>':
3632 if (is_numeric($operand1) && is_numeric($operand2)) {
3633 $result = (abs($operand1 - $operand2) > 1E-14);
3634 } else {
3635 $result = strcmp($operand1, $operand2) != 0;
3636 }
3637 break;
3638 }
3639
3640 // Log the result details
3641 $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result));
3642 // And push the result onto the stack
3643 $stack->push('Value',$result);
3644 return true;
3645 }
$result
static _checkMatrixOperands(&$operand1, &$operand2, $resize=1)
Ensure that paired matrix operands are both matrices and of the same size.
static _unwrapResult($value)
Remove quotes used as a wrapper to identify string values.
_executeBinaryComparisonOperation($cellID, $operand1, $operand2, $operation, &$stack, $recursingArrays=FALSE)
strcmpLowercaseFirst($str1, $str2)
Compare two strings in the same way as strcmp() except that lowercase come before uppercase letters.
_showTypeDetails($value)
Format type and details of an operand for display in the log (based on operand type)
_showValue($value)
Format details of an operand for display in the log (based on operand type)
$x
Definition: example_009.php:98
$r
Definition: example_031.php:79

References $r, $result, $x, _checkMatrixOperands(), _executeBinaryComparisonOperation(), _showTypeDetails(), _showValue(), _unwrapResult(), PHPExcel_Calculation_Functions\COMPATIBILITY_OPENOFFICE, PHPExcel_Calculation_Functions\getCompatibilityMode(), and strcmpLowercaseFirst().

Referenced by _executeBinaryComparisonOperation(), and _processTokenStack().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _executeNumericBinaryOperation()

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

Definition at line 3661 of file Calculation.php.

3661 {
3662 // Validate the two operands
3663 if (!$this->_validateBinaryOperand($cellID,$operand1,$stack)) return FALSE;
3664 if (!$this->_validateBinaryOperand($cellID,$operand2,$stack)) return FALSE;
3665
3666 // If either of the operands is a matrix, we need to treat them both as matrices
3667 // (converting the other operand to a matrix if need be); then perform the required
3668 // matrix operation
3669 if ((is_array($operand1)) || (is_array($operand2))) {
3670 // Ensure that both operands are arrays/matrices of the same size
3671 self::_checkMatrixOperands($operand1, $operand2, 2);
3672
3673 try {
3674 // Convert operand 1 from a PHP array to a matrix
3675 $matrix = new PHPExcel_Shared_JAMA_Matrix($operand1);
3676 // Perform the required operation against the operand 1 matrix, passing in operand 2
3677 $matrixResult = $matrix->$matrixFunction($operand2);
3678 $result = $matrixResult->getArray();
3679 } catch (PHPExcel_Exception $ex) {
3680 $this->_debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage());
3681 $result = '#VALUE!';
3682 }
3683 } else {
3685 ((is_string($operand1) && !is_numeric($operand1) && strlen($operand1)>0) ||
3686 (is_string($operand2) && !is_numeric($operand2) && strlen($operand2)>0))) {
3688 } else {
3689 // If we're dealing with non-matrix operations, execute the necessary operation
3690 switch ($operation) {
3691 // Addition
3692 case '+':
3693 $result = $operand1 + $operand2;
3694 break;
3695 // Subtraction
3696 case '-':
3697 $result = $operand1 - $operand2;
3698 break;
3699 // Multiplication
3700 case '*':
3701 $result = $operand1 * $operand2;
3702 break;
3703 // Division
3704 case '/':
3705 if ($operand2 == 0) {
3706 // Trap for Divide by Zero error
3707 $stack->push('Value','#DIV/0!');
3708 $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails('#DIV/0!'));
3709 return FALSE;
3710 } else {
3711 $result = $operand1 / $operand2;
3712 }
3713 break;
3714 // Power
3715 case '^':
3716 $result = pow($operand1, $operand2);
3717 break;
3718 }
3719 }
3720 }
3721
3722 // Log the result details
3723 $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result));
3724 // And push the result onto the stack
3725 $stack->push('Value',$result);
3726 return TRUE;
3727 } // function _executeNumericBinaryOperation()
_validateBinaryOperand($cellID, &$operand, &$stack)
PHPExcel root directory.
Definition: Matrix.php:27

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

Referenced by _processTokenStack().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _getMatrixDimensions()

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 2474 of file Calculation.php.

2474 {
2475 $matrixRows = count($matrix);
2476 $matrixColumns = 0;
2477 foreach($matrix as $rowKey => $rowValue) {
2478 $matrixColumns = max(count($rowValue),$matrixColumns);
2479 if (!is_array($rowValue)) {
2480 $matrix[$rowKey] = array($rowValue);
2481 } else {
2482 $matrix[$rowKey] = array_values($rowValue);
2483 }
2484 }
2485 $matrix = array_values($matrix);
2486 return array($matrixRows,$matrixColumns);
2487 } // function _getMatrixDimensions()

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

+ Here is the caller graph for this function:

◆ _loadLocales()

static PHPExcel_Calculation::_loadLocales ( )
staticprivate

Definition at line 1747 of file Calculation.php.

1747 {
1748 $localeFileDirectory = PHPEXCEL_ROOT.'PHPExcel/locale/';
1749 foreach (glob($localeFileDirectory.'/*',GLOB_ONLYDIR) as $filename) {
1750 $filename = substr($filename,strlen($localeFileDirectory)+1);
1751 if ($filename != 'en') {
1752 self::$_validLocaleLanguages[] = $filename;
1753 }
1754 }
1755 }

References $filename.

Referenced by setLocale().

+ Here is the caller graph for this function:

◆ _localeFunc()

static PHPExcel_Calculation::_localeFunc (   $function)
static

Definition at line 2142 of file Calculation.php.

2142 {
2143 if (self::$_localeLanguage !== 'en_us') {
2144 $functionName = trim($function,'(');
2145 if (isset(self::$_localeFunctions[$functionName])) {
2146 $brace = ($functionName != $function);
2147 $function = self::$_localeFunctions[$functionName];
2148 if ($brace) { $function .= '('; }
2149 }
2150 }
2151 return $function;
2152 }

Referenced by PHPExcel_Calculation_Token_Stack\push().

+ Here is the caller graph for this function:

◆ _mkMatrix()

static PHPExcel_Calculation::_mkMatrix ( )
staticprivate

Definition at line 2703 of file Calculation.php.

2703 {
2704 return func_get_args();
2705 } // function _mkMatrix()

◆ _parseFormula()

PHPExcel_Calculation::_parseFormula (   $formula,
PHPExcel_Cell  $pCell = NULL 
)
private

Definition at line 2740 of file Calculation.php.

2740 {
2741 if (($formula = $this->_convertMatrixReferences(trim($formula))) === FALSE) {
2742 return FALSE;
2743 }
2744
2745 // If we're using cell caching, then $pCell may well be flushed back to the cache (which detaches the parent worksheet),
2746 // so we store the parent worksheet so that we can re-attach it when necessary
2747 $pCellParent = ($pCell !== NULL) ? $pCell->getWorksheet() : NULL;
2748
2749 $regexpMatchString = '/^('.self::CALCULATION_REGEXP_FUNCTION.
2750 '|'.self::CALCULATION_REGEXP_CELLREF.
2751 '|'.self::CALCULATION_REGEXP_NUMBER.
2752 '|'.self::CALCULATION_REGEXP_STRING.
2753 '|'.self::CALCULATION_REGEXP_OPENBRACE.
2754 '|'.self::CALCULATION_REGEXP_NAMEDRANGE.
2755 '|'.self::CALCULATION_REGEXP_ERROR.
2756 ')/si';
2757
2758 // Start with initialisation
2759 $index = 0;
2761 $output = array();
2762 $expectingOperator = FALSE; // We use this test in syntax-checking the expression to determine when a
2763 // - is a negation or + is a positive operator rather than an operation
2764 $expectingOperand = FALSE; // We use this test in syntax-checking the expression to determine whether an operand
2765 // should be null in a function call
2766 // The guts of the lexical parser
2767 // Loop through the formula extracting each operator and operand in turn
2768 while(TRUE) {
2769//echo 'Assessing Expression '.substr($formula, $index),PHP_EOL;
2770 $opCharacter = $formula{$index}; // Get the first character of the value at the current index position
2771//echo 'Initial character of expression block is '.$opCharacter,PHP_EOL;
2772 if ((isset(self::$_comparisonOperators[$opCharacter])) && (strlen($formula) > $index) && (isset(self::$_comparisonOperators[$formula{$index+1}]))) {
2773 $opCharacter .= $formula{++$index};
2774//echo 'Initial character of expression block is comparison operator '.$opCharacter.PHP_EOL;
2775 }
2776
2777 // Find out if we're currently at the beginning of a number, variable, cell reference, function, parenthesis or operand
2778 $isOperandOrFunction = preg_match($regexpMatchString, substr($formula, $index), $match);
2779//echo '$isOperandOrFunction is '.(($isOperandOrFunction) ? 'True' : 'False').PHP_EOL;
2780//var_dump($match);
2781
2782 if ($opCharacter == '-' && !$expectingOperator) { // Is it a negation instead of a minus?
2783//echo 'Element is a Negation operator',PHP_EOL;
2784 $stack->push('Unary Operator','~'); // Put a negation on the stack
2785 ++$index; // and drop the negation symbol
2786 } elseif ($opCharacter == '%' && $expectingOperator) {
2787//echo 'Element is a Percentage operator',PHP_EOL;
2788 $stack->push('Unary Operator','%'); // Put a percentage on the stack
2789 ++$index;
2790 } elseif ($opCharacter == '+' && !$expectingOperator) { // Positive (unary plus rather than binary operator plus) can be discarded?
2791//echo 'Element is a Positive number, not Plus operator',PHP_EOL;
2792 ++$index; // Drop the redundant plus symbol
2793 } elseif ((($opCharacter == '~') || ($opCharacter == '|')) && (!$isOperandOrFunction)) { // We have to explicitly deny a tilde or pipe, because they are legal
2794 return $this->_raiseFormulaError("Formula Error: Illegal character '~'"); // on the stack but not in the input expression
2795
2796 } elseif ((isset(self::$_operators[$opCharacter]) or $isOperandOrFunction) && $expectingOperator) { // Are we putting an operator on the stack?
2797//echo 'Element with value '.$opCharacter.' is an Operator',PHP_EOL;
2798 while($stack->count() > 0 &&
2799 ($o2 = $stack->last()) &&
2800 isset(self::$_operators[$o2['value']]) &&
2801 @(self::$_operatorAssociativity[$opCharacter] ? self::$_operatorPrecedence[$opCharacter] < self::$_operatorPrecedence[$o2['value']] : self::$_operatorPrecedence[$opCharacter] <= self::$_operatorPrecedence[$o2['value']])) {
2802 $output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output
2803 }
2804 $stack->push('Binary Operator',$opCharacter); // Finally put our current operator onto the stack
2805 ++$index;
2806 $expectingOperator = FALSE;
2807
2808 } elseif ($opCharacter == ')' && $expectingOperator) { // Are we expecting to close a parenthesis?
2809//echo 'Element is a Closing bracket',PHP_EOL;
2810 $expectingOperand = FALSE;
2811 while (($o2 = $stack->pop()) && $o2['value'] != '(') { // Pop off the stack back to the last (
2812 if ($o2 === NULL) return $this->_raiseFormulaError('Formula Error: Unexpected closing brace ")"');
2813 else $output[] = $o2;
2814 }
2815 $d = $stack->last(2);
2816 if (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $d['value'], $matches)) { // Did this parenthesis just close a function?
2817 $functionName = $matches[1]; // Get the function name
2818//echo 'Closed Function is '.$functionName,PHP_EOL;
2819 $d = $stack->pop();
2820 $argumentCount = $d['value']; // See how many arguments there were (argument count is the next value stored on the stack)
2821//if ($argumentCount == 0) {
2822// echo 'With no arguments',PHP_EOL;
2823//} elseif ($argumentCount == 1) {
2824// echo 'With 1 argument',PHP_EOL;
2825//} else {
2826// echo 'With '.$argumentCount.' arguments',PHP_EOL;
2827//}
2828 $output[] = $d; // Dump the argument count on the output
2829 $output[] = $stack->pop(); // Pop the function and push onto the output
2830 if (isset(self::$_controlFunctions[$functionName])) {
2831//echo 'Built-in function '.$functionName,PHP_EOL;
2832 $expectedArgumentCount = self::$_controlFunctions[$functionName]['argumentCount'];
2833 $functionCall = self::$_controlFunctions[$functionName]['functionCall'];
2834 } elseif (isset(self::$_PHPExcelFunctions[$functionName])) {
2835//echo 'PHPExcel function '.$functionName,PHP_EOL;
2836 $expectedArgumentCount = self::$_PHPExcelFunctions[$functionName]['argumentCount'];
2837 $functionCall = self::$_PHPExcelFunctions[$functionName]['functionCall'];
2838 } else { // did we somehow push a non-function on the stack? this should never happen
2839 return $this->_raiseFormulaError("Formula Error: Internal error, non-function on stack");
2840 }
2841 // Check the argument count
2842 $argumentCountError = FALSE;
2843 if (is_numeric($expectedArgumentCount)) {
2844 if ($expectedArgumentCount < 0) {
2845//echo '$expectedArgumentCount is between 0 and '.abs($expectedArgumentCount),PHP_EOL;
2846 if ($argumentCount > abs($expectedArgumentCount)) {
2847 $argumentCountError = TRUE;
2848 $expectedArgumentCountString = 'no more than '.abs($expectedArgumentCount);
2849 }
2850 } else {
2851//echo '$expectedArgumentCount is numeric '.$expectedArgumentCount,PHP_EOL;
2852 if ($argumentCount != $expectedArgumentCount) {
2853 $argumentCountError = TRUE;
2854 $expectedArgumentCountString = $expectedArgumentCount;
2855 }
2856 }
2857 } elseif ($expectedArgumentCount != '*') {
2858 $isOperandOrFunction = preg_match('/(\d*)([-+,])(\d*)/',$expectedArgumentCount,$argMatch);
2859//print_r($argMatch);
2860//echo PHP_EOL;
2861 switch ($argMatch[2]) {
2862 case '+' :
2863 if ($argumentCount < $argMatch[1]) {
2864 $argumentCountError = TRUE;
2865 $expectedArgumentCountString = $argMatch[1].' or more ';
2866 }
2867 break;
2868 case '-' :
2869 if (($argumentCount < $argMatch[1]) || ($argumentCount > $argMatch[3])) {
2870 $argumentCountError = TRUE;
2871 $expectedArgumentCountString = 'between '.$argMatch[1].' and '.$argMatch[3];
2872 }
2873 break;
2874 case ',' :
2875 if (($argumentCount != $argMatch[1]) && ($argumentCount != $argMatch[3])) {
2876 $argumentCountError = TRUE;
2877 $expectedArgumentCountString = 'either '.$argMatch[1].' or '.$argMatch[3];
2878 }
2879 break;
2880 }
2881 }
2882 if ($argumentCountError) {
2883 return $this->_raiseFormulaError("Formula Error: Wrong number of arguments for $functionName() function: $argumentCount given, ".$expectedArgumentCountString." expected");
2884 }
2885 }
2886 ++$index;
2887
2888 } elseif ($opCharacter == ',') { // Is this the separator for function arguments?
2889//echo 'Element is a Function argument separator',PHP_EOL;
2890 while (($o2 = $stack->pop()) && $o2['value'] != '(') { // Pop off the stack back to the last (
2891 if ($o2 === NULL) return $this->_raiseFormulaError("Formula Error: Unexpected ,");
2892 else $output[] = $o2; // pop the argument expression stuff and push onto the output
2893 }
2894 // If we've a comma when we're expecting an operand, then what we actually have is a null operand;
2895 // so push a null onto the stack
2896 if (($expectingOperand) || (!$expectingOperator)) {
2897 $output[] = array('type' => 'NULL Value', 'value' => self::$_ExcelConstants['NULL'], 'reference' => NULL);
2898 }
2899 // make sure there was a function
2900 $d = $stack->last(2);
2901 if (!preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $d['value'], $matches))
2902 return $this->_raiseFormulaError("Formula Error: Unexpected ,");
2903 $d = $stack->pop();
2904 $stack->push($d['type'],++$d['value'],$d['reference']); // increment the argument count
2905 $stack->push('Brace', '('); // put the ( back on, we'll need to pop back to it again
2906 $expectingOperator = FALSE;
2907 $expectingOperand = TRUE;
2908 ++$index;
2909
2910 } elseif ($opCharacter == '(' && !$expectingOperator) {
2911// echo 'Element is an Opening Bracket<br />';
2912 $stack->push('Brace', '(');
2913 ++$index;
2914
2915 } elseif ($isOperandOrFunction && !$expectingOperator) { // do we now have a function/variable/number?
2916 $expectingOperator = TRUE;
2917 $expectingOperand = FALSE;
2918 $val = $match[1];
2919 $length = strlen($val);
2920// echo 'Element with value '.$val.' is an Operand, Variable, Constant, String, Number, Cell Reference or Function<br />';
2921
2922 if (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $val, $matches)) {
2923 $val = preg_replace('/\s/u','',$val);
2924// echo 'Element '.$val.' is a Function<br />';
2925 if (isset(self::$_PHPExcelFunctions[strtoupper($matches[1])]) || isset(self::$_controlFunctions[strtoupper($matches[1])])) { // it's a function
2926 $stack->push('Function', strtoupper($val));
2927 $ax = preg_match('/^\s*(\s*\‍))/ui', substr($formula, $index+$length), $amatch);
2928 if ($ax) {
2929 $stack->push('Operand Count for Function '.strtoupper($val).')', 0);
2930 $expectingOperator = TRUE;
2931 } else {
2932 $stack->push('Operand Count for Function '.strtoupper($val).')', 1);
2933 $expectingOperator = FALSE;
2934 }
2935 $stack->push('Brace', '(');
2936 } else { // it's a var w/ implicit multiplication
2937 $output[] = array('type' => 'Value', 'value' => $matches[1], 'reference' => NULL);
2938 }
2939 } elseif (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $val, $matches)) {
2940// echo 'Element '.$val.' is a Cell reference<br />';
2941 // Watch for this case-change when modifying to allow cell references in different worksheets...
2942 // Should only be applied to the actual cell column, not the worksheet name
2943
2944 // If the last entry on the stack was a : operator, then we have a cell range reference
2945 $testPrevOp = $stack->last(1);
2946 if ($testPrevOp['value'] == ':') {
2947 // If we have a worksheet reference, then we're playing with a 3D reference
2948 if ($matches[2] == '') {
2949 // Otherwise, we 'inherit' the worksheet reference from the start cell reference
2950 // The start of the cell range reference should be the last entry in $output
2951 $startCellRef = $output[count($output)-1]['value'];
2952 preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $startCellRef, $startMatches);
2953 if ($startMatches[2] > '') {
2954 $val = $startMatches[2].'!'.$val;
2955 }
2956 } else {
2957 return $this->_raiseFormulaError("3D Range references are not yet supported");
2958 }
2959 }
2960
2961 $output[] = array('type' => 'Cell Reference', 'value' => $val, 'reference' => $val);
2962// $expectingOperator = FALSE;
2963 } else { // it's a variable, constant, string, number or boolean
2964// echo 'Element is a Variable, Constant, String, Number or Boolean<br />';
2965 // If the last entry on the stack was a : operator, then we may have a row or column range reference
2966 $testPrevOp = $stack->last(1);
2967 if ($testPrevOp['value'] == ':') {
2968 $startRowColRef = $output[count($output)-1]['value'];
2969 $rangeWS1 = '';
2970 if (strpos('!',$startRowColRef) !== FALSE) {
2971 list($rangeWS1,$startRowColRef) = explode('!',$startRowColRef);
2972 }
2973 if ($rangeWS1 != '') $rangeWS1 .= '!';
2974 $rangeWS2 = $rangeWS1;
2975 if (strpos('!',$val) !== FALSE) {
2976 list($rangeWS2,$val) = explode('!',$val);
2977 }
2978 if ($rangeWS2 != '') $rangeWS2 .= '!';
2979 if ((is_integer($startRowColRef)) && (ctype_digit($val)) &&
2980 ($startRowColRef <= 1048576) && ($val <= 1048576)) {
2981 // Row range
2982 $endRowColRef = ($pCellParent !== NULL) ? $pCellParent->getHighestColumn() : 'XFD'; // Max 16,384 columns for Excel2007
2983 $output[count($output)-1]['value'] = $rangeWS1.'A'.$startRowColRef;
2984 $val = $rangeWS2.$endRowColRef.$val;
2985 } elseif ((ctype_alpha($startRowColRef)) && (ctype_alpha($val)) &&
2986 (strlen($startRowColRef) <= 3) && (strlen($val) <= 3)) {
2987 // Column range
2988 $endRowColRef = ($pCellParent !== NULL) ? $pCellParent->getHighestRow() : 1048576; // Max 1,048,576 rows for Excel2007
2989 $output[count($output)-1]['value'] = $rangeWS1.strtoupper($startRowColRef).'1';
2990 $val = $rangeWS2.$val.$endRowColRef;
2991 }
2992 }
2993
2994 $localeConstant = FALSE;
2995 if ($opCharacter == '"') {
2996// echo 'Element is a String<br />';
2997 // UnEscape any quotes within the string
2998 $val = self::_wrapResult(str_replace('""','"',self::_unwrapResult($val)));
2999 } elseif (is_numeric($val)) {
3000// echo 'Element is a Number<br />';
3001 if ((strpos($val,'.') !== FALSE) || (stripos($val,'e') !== FALSE) || ($val > PHP_INT_MAX) || ($val < -PHP_INT_MAX)) {
3002// echo 'Casting '.$val.' to float<br />';
3003 $val = (float) $val;
3004 } else {
3005// echo 'Casting '.$val.' to integer<br />';
3006 $val = (integer) $val;
3007 }
3008 } elseif (isset(self::$_ExcelConstants[trim(strtoupper($val))])) {
3009 $excelConstant = trim(strtoupper($val));
3010// echo 'Element '.$excelConstant.' is an Excel Constant<br />';
3011 $val = self::$_ExcelConstants[$excelConstant];
3012 } elseif (($localeConstant = array_search(trim(strtoupper($val)), self::$_localeBoolean)) !== FALSE) {
3013// echo 'Element '.$localeConstant.' is an Excel Constant<br />';
3014 $val = self::$_ExcelConstants[$localeConstant];
3015 }
3016 $details = array('type' => 'Value', 'value' => $val, 'reference' => NULL);
3017 if ($localeConstant) { $details['localeValue'] = $localeConstant; }
3018 $output[] = $details;
3019 }
3020 $index += $length;
3021
3022 } elseif ($opCharacter == '$') { // absolute row or column range
3023 ++$index;
3024 } elseif ($opCharacter == ')') { // miscellaneous error checking
3025 if ($expectingOperand) {
3026 $output[] = array('type' => 'NULL Value', 'value' => self::$_ExcelConstants['NULL'], 'reference' => NULL);
3027 $expectingOperand = FALSE;
3028 $expectingOperator = TRUE;
3029 } else {
3030 return $this->_raiseFormulaError("Formula Error: Unexpected ')'");
3031 }
3032 } elseif (isset(self::$_operators[$opCharacter]) && !$expectingOperator) {
3033 return $this->_raiseFormulaError("Formula Error: Unexpected operator '$opCharacter'");
3034 } else { // I don't even want to know what you did to get here
3035 return $this->_raiseFormulaError("Formula Error: An unexpected error occured");
3036 }
3037 // Test for end of formula string
3038 if ($index == strlen($formula)) {
3039 // Did we end with an operator?.
3040 // Only valid for the % unary operator
3041 if ((isset(self::$_operators[$opCharacter])) && ($opCharacter != '%')) {
3042 return $this->_raiseFormulaError("Formula Error: Operator '$opCharacter' has no operands");
3043 } else {
3044 break;
3045 }
3046 }
3047 // Ignore white space
3048 while (($formula{$index} == "\n") || ($formula{$index} == "\r")) {
3049 ++$index;
3050 }
3051 if ($formula{$index} == ' ') {
3052 while ($formula{$index} == ' ') {
3053 ++$index;
3054 }
3055 // If we're expecting an operator, but only have a space between the previous and next operands (and both are
3056 // Cell References) then we have an INTERSECTION operator
3057// echo 'Possible Intersect Operator<br />';
3058 if (($expectingOperator) && (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'.*/Ui', substr($formula, $index), $match)) &&
3059 ($output[count($output)-1]['type'] == 'Cell Reference')) {
3060// echo 'Element is an Intersect Operator<br />';
3061 while($stack->count() > 0 &&
3062 ($o2 = $stack->last()) &&
3063 isset(self::$_operators[$o2['value']]) &&
3064 @(self::$_operatorAssociativity[$opCharacter] ? self::$_operatorPrecedence[$opCharacter] < self::$_operatorPrecedence[$o2['value']] : self::$_operatorPrecedence[$opCharacter] <= self::$_operatorPrecedence[$o2['value']])) {
3065 $output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output
3066 }
3067 $stack->push('Binary Operator','|'); // Put an Intersect Operator on the stack
3068 $expectingOperator = FALSE;
3069 }
3070 }
3071 }
3072
3073 while (($op = $stack->pop()) !== NULL) { // pop everything off the stack and push onto output
3074 if ((is_array($op) && $op['value'] == '(') || ($op === '('))
3075 return $this->_raiseFormulaError("Formula Error: Expecting ')'"); // if there are any opening braces on the stack, then braces were unbalanced
3076 $output[] = $op;
3077 }
3078 return $output;
3079 } // function _parseFormula()
for($col=0; $col< 50; $col++) $d
_convertMatrixReferences($formula)
if(!is_dir( $entity_dir)) exit("Fatal Error ([A-Za-z0-9]+)\s+" &#(? foreach( $entity_files as $file) $output

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

Referenced by _calculateFormulaValue(), and parseFormula().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _processTokenStack()

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

Definition at line 3098 of file Calculation.php.

3098 {
3099 if ($tokens == FALSE) return FALSE;
3100
3101 // If we're using cell caching, then $pCell may well be flushed back to the cache (which detaches the parent cell collection),
3102 // so we store the parent cell collection so that we can re-attach it when necessary
3103 $pCellWorksheet = ($pCell !== NULL) ? $pCell->getWorksheet() : NULL;
3104 $pCellParent = ($pCell !== NULL) ? $pCell->getParent() : null;
3106
3107 // Loop through each token in turn
3108 foreach ($tokens as $tokenData) {
3109// print_r($tokenData);
3110// echo '<br />';
3111 $token = $tokenData['value'];
3112// echo '<b>Token is '.$token.'</b><br />';
3113 // 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
3114 if (isset(self::$_binaryOperators[$token])) {
3115// echo 'Token is a binary operator<br />';
3116 // We must have two operands, error if we don't
3117 if (($operand2Data = $stack->pop()) === NULL) return $this->_raiseFormulaError('Internal error - Operand value missing from stack');
3118 if (($operand1Data = $stack->pop()) === NULL) return $this->_raiseFormulaError('Internal error - Operand value missing from stack');
3119
3120 $operand1 = self::_dataTestReference($operand1Data);
3121 $operand2 = self::_dataTestReference($operand2Data);
3122
3123 // Log what we're doing
3124 if ($token == ':') {
3125 $this->_debugLog->writeDebugLog('Evaluating Range ', $this->_showValue($operand1Data['reference']), ' ', $token, ' ', $this->_showValue($operand2Data['reference']));
3126 } else {
3127 $this->_debugLog->writeDebugLog('Evaluating ', $this->_showValue($operand1), ' ', $token, ' ', $this->_showValue($operand2));
3128 }
3129
3130 // Process the operation in the appropriate manner
3131 switch ($token) {
3132 // Comparison (Boolean) Operators
3133 case '>' : // Greater than
3134 case '<' : // Less than
3135 case '>=' : // Greater than or Equal to
3136 case '<=' : // Less than or Equal to
3137 case '=' : // Equality
3138 case '<>' : // Inequality
3139 $this->_executeBinaryComparisonOperation($cellID,$operand1,$operand2,$token,$stack);
3140 break;
3141 // Binary Operators
3142 case ':' : // Range
3143 $sheet1 = $sheet2 = '';
3144 if (strpos($operand1Data['reference'],'!') !== FALSE) {
3145 list($sheet1,$operand1Data['reference']) = explode('!',$operand1Data['reference']);
3146 } else {
3147 $sheet1 = ($pCellParent !== NULL) ? $pCellWorksheet->getTitle() : '';
3148 }
3149 if (strpos($operand2Data['reference'],'!') !== FALSE) {
3150 list($sheet2,$operand2Data['reference']) = explode('!',$operand2Data['reference']);
3151 } else {
3152 $sheet2 = $sheet1;
3153 }
3154 if ($sheet1 == $sheet2) {
3155 if ($operand1Data['reference'] === NULL) {
3156 if ((trim($operand1Data['value']) != '') && (is_numeric($operand1Data['value']))) {
3157 $operand1Data['reference'] = $pCell->getColumn().$operand1Data['value'];
3158 } elseif (trim($operand1Data['reference']) == '') {
3159 $operand1Data['reference'] = $pCell->getCoordinate();
3160 } else {
3161 $operand1Data['reference'] = $operand1Data['value'].$pCell->getRow();
3162 }
3163 }
3164 if ($operand2Data['reference'] === NULL) {
3165 if ((trim($operand2Data['value']) != '') && (is_numeric($operand2Data['value']))) {
3166 $operand2Data['reference'] = $pCell->getColumn().$operand2Data['value'];
3167 } elseif (trim($operand2Data['reference']) == '') {
3168 $operand2Data['reference'] = $pCell->getCoordinate();
3169 } else {
3170 $operand2Data['reference'] = $operand2Data['value'].$pCell->getRow();
3171 }
3172 }
3173
3174 $oData = array_merge(explode(':',$operand1Data['reference']),explode(':',$operand2Data['reference']));
3175 $oCol = $oRow = array();
3176 foreach($oData as $oDatum) {
3178 $oCol[] = PHPExcel_Cell::columnIndexFromString($oCR[0]) - 1;
3179 $oRow[] = $oCR[1];
3180 }
3181 $cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)).min($oRow).':'.PHPExcel_Cell::stringFromColumnIndex(max($oCol)).max($oRow);
3182 if ($pCellParent !== NULL) {
3183 $cellValue = $this->extractCellRange($cellRef, $this->_workbook->getSheetByName($sheet1), FALSE);
3184 } else {
3185 return $this->_raiseFormulaError('Unable to access Cell Reference');
3186 }
3187 $stack->push('Cell Reference',$cellValue,$cellRef);
3188 } else {
3189 $stack->push('Error',PHPExcel_Calculation_Functions::REF(),NULL);
3190 }
3191
3192 break;
3193 case '+' : // Addition
3194 $this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'plusEquals',$stack);
3195 break;
3196 case '-' : // Subtraction
3197 $this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'minusEquals',$stack);
3198 break;
3199 case '*' : // Multiplication
3200 $this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'arrayTimesEquals',$stack);
3201 break;
3202 case '/' : // Division
3203 $this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'arrayRightDivide',$stack);
3204 break;
3205 case '^' : // Exponential
3206 $this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'power',$stack);
3207 break;
3208 case '&' : // Concatenation
3209 // If either of the operands is a matrix, we need to treat them both as matrices
3210 // (converting the other operand to a matrix if need be); then perform the required
3211 // matrix operation
3212 if (is_bool($operand1)) {
3213 $operand1 = ($operand1) ? self::$_localeBoolean['TRUE'] : self::$_localeBoolean['FALSE'];
3214 }
3215 if (is_bool($operand2)) {
3216 $operand2 = ($operand2) ? self::$_localeBoolean['TRUE'] : self::$_localeBoolean['FALSE'];
3217 }
3218 if ((is_array($operand1)) || (is_array($operand2))) {
3219 // Ensure that both operands are arrays/matrices
3220 self::_checkMatrixOperands($operand1,$operand2,2);
3221 try {
3222 // Convert operand 1 from a PHP array to a matrix
3223 $matrix = new PHPExcel_Shared_JAMA_Matrix($operand1);
3224 // Perform the required operation against the operand 1 matrix, passing in operand 2
3225 $matrixResult = $matrix->concat($operand2);
3226 $result = $matrixResult->getArray();
3227 } catch (PHPExcel_Exception $ex) {
3228 $this->_debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage());
3229 $result = '#VALUE!';
3230 }
3231 } else {
3232 $result = '"'.str_replace('""','"',self::_unwrapResult($operand1,'"').self::_unwrapResult($operand2,'"')).'"';
3233 }
3234 $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result));
3235 $stack->push('Value',$result);
3236 break;
3237 case '|' : // Intersect
3238 $rowIntersect = array_intersect_key($operand1,$operand2);
3239 $cellIntersect = $oCol = $oRow = array();
3240 foreach(array_keys($rowIntersect) as $row) {
3241 $oRow[] = $row;
3242 foreach($rowIntersect[$row] as $col => $data) {
3243 $oCol[] = PHPExcel_Cell::columnIndexFromString($col) - 1;
3244 $cellIntersect[$row] = array_intersect_key($operand1[$row],$operand2[$row]);
3245 }
3246 }
3247 $cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)).min($oRow).':'.PHPExcel_Cell::stringFromColumnIndex(max($oCol)).max($oRow);
3248 $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($cellIntersect));
3249 $stack->push('Value',$cellIntersect,$cellRef);
3250 break;
3251 }
3252
3253 // if the token is a unary operator, pop one value off the stack, do the operation, and push it back on
3254 } elseif (($token === '~') || ($token === '%')) {
3255// echo 'Token is a unary operator<br />';
3256 if (($arg = $stack->pop()) === NULL) return $this->_raiseFormulaError('Internal error - Operand value missing from stack');
3257 $arg = $arg['value'];
3258 if ($token === '~') {
3259// echo 'Token is a negation operator<br />';
3260 $this->_debugLog->writeDebugLog('Evaluating Negation of ', $this->_showValue($arg));
3261 $multiplier = -1;
3262 } else {
3263// echo 'Token is a percentile operator<br />';
3264 $this->_debugLog->writeDebugLog('Evaluating Percentile of ', $this->_showValue($arg));
3265 $multiplier = 0.01;
3266 }
3267 if (is_array($arg)) {
3268 self::_checkMatrixOperands($arg,$multiplier,2);
3269 try {
3270 $matrix1 = new PHPExcel_Shared_JAMA_Matrix($arg);
3271 $matrixResult = $matrix1->arrayTimesEquals($multiplier);
3272 $result = $matrixResult->getArray();
3273 } catch (PHPExcel_Exception $ex) {
3274 $this->_debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage());
3275 $result = '#VALUE!';
3276 }
3277 $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result));
3278 $stack->push('Value',$result);
3279 } else {
3280 $this->_executeNumericBinaryOperation($cellID,$multiplier,$arg,'*','arrayTimesEquals',$stack);
3281 }
3282
3283 } elseif (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $token, $matches)) {
3284 $cellRef = NULL;
3285// echo 'Element '.$token.' is a Cell reference<br />';
3286 if (isset($matches[8])) {
3287// echo 'Reference is a Range of cells<br />';
3288 if ($pCell === NULL) {
3289// We can't access the range, so return a REF error
3291 } else {
3292 $cellRef = $matches[6].$matches[7].':'.$matches[9].$matches[10];
3293 if ($matches[2] > '') {
3294 $matches[2] = trim($matches[2],"\"'");
3295 if ((strpos($matches[2],'[') !== FALSE) || (strpos($matches[2],']') !== FALSE)) {
3296 // It's a Reference to an external workbook (not currently supported)
3297 return $this->_raiseFormulaError('Unable to access External Workbook');
3298 }
3299 $matches[2] = trim($matches[2],"\"'");
3300// echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'<br />';
3301 $this->_debugLog->writeDebugLog('Evaluating Cell Range ', $cellRef, ' in worksheet ', $matches[2]);
3302 if ($pCellParent !== NULL) {
3303 $cellValue = $this->extractCellRange($cellRef, $this->_workbook->getSheetByName($matches[2]), FALSE);
3304 } else {
3305 return $this->_raiseFormulaError('Unable to access Cell Reference');
3306 }
3307 $this->_debugLog->writeDebugLog('Evaluation Result for cells ', $cellRef, ' in worksheet ', $matches[2], ' is ', $this->_showTypeDetails($cellValue));
3308// $cellRef = $matches[2].'!'.$cellRef;
3309 } else {
3310// echo '$cellRef='.$cellRef.' in current worksheet<br />';
3311 $this->_debugLog->writeDebugLog('Evaluating Cell Range ', $cellRef, ' in current worksheet');
3312 if ($pCellParent !== NULL) {
3313 $cellValue = $this->extractCellRange($cellRef, $pCellWorksheet, FALSE);
3314 } else {
3315 return $this->_raiseFormulaError('Unable to access Cell Reference');
3316 }
3317 $this->_debugLog->writeDebugLog('Evaluation Result for cells ', $cellRef, ' is ', $this->_showTypeDetails($cellValue));
3318 }
3319 }
3320 } else {
3321// echo 'Reference is a single Cell<br />';
3322 if ($pCell === NULL) {
3323// We can't access the cell, so return a REF error
3325 } else {
3326 $cellRef = $matches[6].$matches[7];
3327 if ($matches[2] > '') {
3328 $matches[2] = trim($matches[2],"\"'");
3329 if ((strpos($matches[2],'[') !== FALSE) || (strpos($matches[2],']') !== FALSE)) {
3330 // It's a Reference to an external workbook (not currently supported)
3331 return $this->_raiseFormulaError('Unable to access External Workbook');
3332 }
3333// echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'<br />';
3334 $this->_debugLog->writeDebugLog('Evaluating Cell ', $cellRef, ' in worksheet ', $matches[2]);
3335 if ($pCellParent !== NULL) {
3336 $cellSheet = $this->_workbook->getSheetByName($matches[2]);
3337 if ($cellSheet && $cellSheet->cellExists($cellRef)) {
3338 $cellValue = $this->extractCellRange($cellRef, $this->_workbook->getSheetByName($matches[2]), FALSE);
3339 $pCell->attach($pCellParent);
3340 } else {
3341 $cellValue = NULL;
3342 }
3343 } else {
3344 return $this->_raiseFormulaError('Unable to access Cell Reference');
3345 }
3346 $this->_debugLog->writeDebugLog('Evaluation Result for cell ', $cellRef, ' in worksheet ', $matches[2], ' is ', $this->_showTypeDetails($cellValue));
3347// $cellRef = $matches[2].'!'.$cellRef;
3348 } else {
3349// echo '$cellRef='.$cellRef.' in current worksheet<br />';
3350 $this->_debugLog->writeDebugLog('Evaluating Cell ', $cellRef, ' in current worksheet');
3351 if ($pCellParent->isDataSet($cellRef)) {
3352 $cellValue = $this->extractCellRange($cellRef, $pCellWorksheet, FALSE);
3353 $pCell->attach($pCellParent);
3354 } else {
3355 $cellValue = NULL;
3356 }
3357 $this->_debugLog->writeDebugLog('Evaluation Result for cell ', $cellRef, ' is ', $this->_showTypeDetails($cellValue));
3358 }
3359 }
3360 }
3361 $stack->push('Value',$cellValue,$cellRef);
3362
3363 // if the token is a function, pop arguments off the stack, hand them to the function, and push the result back on
3364 } elseif (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $token, $matches)) {
3365// echo 'Token is a function<br />';
3366 $functionName = $matches[1];
3367 $argCount = $stack->pop();
3368 $argCount = $argCount['value'];
3369 if ($functionName != 'MKMATRIX') {
3370 $this->_debugLog->writeDebugLog('Evaluating Function ', self::_localeFunc($functionName), '() with ', (($argCount == 0) ? 'no' : $argCount), ' argument', (($argCount == 1) ? '' : 's'));
3371 }
3372 if ((isset(self::$_PHPExcelFunctions[$functionName])) || (isset(self::$_controlFunctions[$functionName]))) { // function
3373 if (isset(self::$_PHPExcelFunctions[$functionName])) {
3374 $functionCall = self::$_PHPExcelFunctions[$functionName]['functionCall'];
3375 $passByReference = isset(self::$_PHPExcelFunctions[$functionName]['passByReference']);
3376 $passCellReference = isset(self::$_PHPExcelFunctions[$functionName]['passCellReference']);
3377 } elseif (isset(self::$_controlFunctions[$functionName])) {
3378 $functionCall = self::$_controlFunctions[$functionName]['functionCall'];
3379 $passByReference = isset(self::$_controlFunctions[$functionName]['passByReference']);
3380 $passCellReference = isset(self::$_controlFunctions[$functionName]['passCellReference']);
3381 }
3382 // get the arguments for this function
3383// echo 'Function '.$functionName.' expects '.$argCount.' arguments<br />';
3384 $args = $argArrayVals = array();
3385 for ($i = 0; $i < $argCount; ++$i) {
3386 $arg = $stack->pop();
3387 $a = $argCount - $i - 1;
3388 if (($passByReference) &&
3389 (isset(self::$_PHPExcelFunctions[$functionName]['passByReference'][$a])) &&
3390 (self::$_PHPExcelFunctions[$functionName]['passByReference'][$a])) {
3391 if ($arg['reference'] === NULL) {
3392 $args[] = $cellID;
3393 if ($functionName != 'MKMATRIX') { $argArrayVals[] = $this->_showValue($cellID); }
3394 } else {
3395 $args[] = $arg['reference'];
3396 if ($functionName != 'MKMATRIX') { $argArrayVals[] = $this->_showValue($arg['reference']); }
3397 }
3398 } else {
3399 $args[] = self::_unwrapResult($arg['value']);
3400 if ($functionName != 'MKMATRIX') { $argArrayVals[] = $this->_showValue($arg['value']); }
3401 }
3402 }
3403 // Reverse the order of the arguments
3404 krsort($args);
3405 if (($passByReference) && ($argCount == 0)) {
3406 $args[] = $cellID;
3407 $argArrayVals[] = $this->_showValue($cellID);
3408 }
3409// echo 'Arguments are: ';
3410// print_r($args);
3411// echo '<br />';
3412 if ($functionName != 'MKMATRIX') {
3413 if ($this->_debugLog->getWriteDebugLog()) {
3414 krsort($argArrayVals);
3415 $this->_debugLog->writeDebugLog('Evaluating ', self::_localeFunc($functionName), '( ', implode(self::$_localeArgumentSeparator.' ',PHPExcel_Calculation_Functions::flattenArray($argArrayVals)), ' )');
3416 }
3417 }
3418 // Process each argument in turn, building the return value as an array
3419// if (($argCount == 1) && (is_array($args[1])) && ($functionName != 'MKMATRIX')) {
3420// $operand1 = $args[1];
3421// $this->_debugLog->writeDebugLog('Argument is a matrix: ', $this->_showValue($operand1));
3422// $result = array();
3423// $row = 0;
3424// foreach($operand1 as $args) {
3425// if (is_array($args)) {
3426// foreach($args as $arg) {
3427// $this->_debugLog->writeDebugLog('Evaluating ', self::_localeFunc($functionName), '( ', $this->_showValue($arg), ' )');
3428// $r = call_user_func_array($functionCall,$arg);
3429// $this->_debugLog->writeDebugLog('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($r));
3430// $result[$row][] = $r;
3431// }
3432// ++$row;
3433// } else {
3434// $this->_debugLog->writeDebugLog('Evaluating ', self::_localeFunc($functionName), '( ', $this->_showValue($args), ' )');
3435// $r = call_user_func_array($functionCall,$args);
3436// $this->_debugLog->writeDebugLog('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($r));
3437// $result[] = $r;
3438// }
3439// }
3440// } else {
3441 // Process the argument with the appropriate function call
3442 if ($passCellReference) {
3443 $args[] = $pCell;
3444 }
3445 if (strpos($functionCall,'::') !== FALSE) {
3446 $result = call_user_func_array(explode('::',$functionCall),$args);
3447 } else {
3448 foreach($args as &$arg) {
3450 }
3451 unset($arg);
3452 $result = call_user_func_array($functionCall,$args);
3453 }
3454// }
3455 if ($functionName != 'MKMATRIX') {
3456 $this->_debugLog->writeDebugLog('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($result));
3457 }
3458 $stack->push('Value',self::_wrapResult($result));
3459 }
3460
3461 } else {
3462 // if the token is a number, boolean, string or an Excel error, push it onto the stack
3463 if (isset(self::$_ExcelConstants[strtoupper($token)])) {
3464 $excelConstant = strtoupper($token);
3465// echo 'Token is a PHPExcel constant: '.$excelConstant.'<br />';
3466 $stack->push('Constant Value',self::$_ExcelConstants[$excelConstant]);
3467 $this->_debugLog->writeDebugLog('Evaluating Constant ', $excelConstant, ' as ', $this->_showTypeDetails(self::$_ExcelConstants[$excelConstant]));
3468 } elseif ((is_numeric($token)) || ($token === NULL) || (is_bool($token)) || ($token == '') || ($token{0} == '"') || ($token{0} == '#')) {
3469// echo 'Token is a number, boolean, string, null or an Excel error<br />';
3470 $stack->push('Value',$token);
3471 // if the token is a named range, push the named range name onto the stack
3472 } elseif (preg_match('/^'.self::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $token, $matches)) {
3473// echo 'Token is a named range<br />';
3474 $namedRange = $matches[6];
3475// echo 'Named Range is '.$namedRange.'<br />';
3476 $this->_debugLog->writeDebugLog('Evaluating Named Range ', $namedRange);
3477 $cellValue = $this->extractNamedRange($namedRange, ((NULL !== $pCell) ? $pCellWorksheet : NULL), FALSE);
3478 $pCell->attach($pCellParent);
3479 $this->_debugLog->writeDebugLog('Evaluation Result for named range ', $namedRange, ' is ', $this->_showTypeDetails($cellValue));
3480 $stack->push('Named Range',$cellValue,$namedRange);
3481 } else {
3482 return $this->_raiseFormulaError("undefined variable '$token'");
3483 }
3484 }
3485 }
3486 // when we're out of tokens, the stack should have a single element, the final result
3487 if ($stack->count() != 1) return $this->_raiseFormulaError("internal error");
3488 $output = $stack->pop();
3489 $output = $output['value'];
3490
3491// if ((is_array($output)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) {
3492// return array_shift(PHPExcel_Calculation_Functions::flattenArray($output));
3493// }
3494 return $output;
3495 } // function _processTokenStack()
static flattenSingleValue($value='')
Convert an array to a single scalar value by extracting the first element.
Definition: Functions.php:662
static flattenArray($array)
Convert a multi-dimensional array to a simple 1-dimensional array.
Definition: Functions.php:598
static _dataTestReference(&$operandData)
extractNamedRange(&$pRange='A1', PHPExcel_Worksheet $pSheet=NULL, $resetLog=TRUE)
Extract range values.
extractCellRange(&$pRange='A1', PHPExcel_Worksheet $pSheet=NULL, $resetLog=TRUE)
Extract range values.
_executeNumericBinaryOperation($cellID, $operand1, $operand2, $operation, $matrixFunction, &$stack)
getParent()
Get parent worksheet.
Definition: Cell.php:479
static stringFromColumnIndex($pColumnIndex=0)
String from columnindex.
Definition: Cell.php:825
static coordinateFromString($pCoordinateString='A1')
Coordinate from string.
Definition: Cell.php:580
getColumn()
Get cell coordinate column.
Definition: Cell.php:151
attach(PHPExcel_CachedObjectStorage_CacheBase $parent)
Definition: Cell.php:115
getCoordinate()
Get cell coordinate.
Definition: Cell.php:171
static columnIndexFromString($pString='A')
Column index from string.
Definition: Cell.php:782

References $data, $output, $result, $row, _checkMatrixOperands(), _dataTestReference(), _executeBinaryComparisonOperation(), _executeNumericBinaryOperation(), _raiseFormulaError(), _showTypeDetails(), _showValue(), _unwrapResult(), 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().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _raiseFormulaError()

PHPExcel_Calculation::_raiseFormulaError (   $errorMessage)
protected

Definition at line 3731 of file Calculation.php.

3731 {
3732 $this->formulaError = $errorMessage;
3733 $this->_cyclicReferenceStack->clear();
3734 if (!$this->suppressFormulaErrors) throw new PHPExcel_Calculation_Exception($errorMessage);
3735 trigger_error($errorMessage, E_USER_ERROR);
3736 } // function _raiseFormulaError()

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

+ Here is the caller graph for this function:

◆ _resizeMatricesExtend()

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
integer$matrix1RowsRow size of first matrix operand
integer$matrix1ColumnsColumn size of first matrix operand
integer$matrix2RowsRow size of second matrix operand
integer$matrix2ColumnsColumn size of second matrix operand

Definition at line 2543 of file Calculation.php.

2543 {
2544 if (($matrix2Columns < $matrix1Columns) || ($matrix2Rows < $matrix1Rows)) {
2545 if ($matrix2Columns < $matrix1Columns) {
2546 for ($i = 0; $i < $matrix2Rows; ++$i) {
2547 $x = $matrix2[$i][$matrix2Columns-1];
2548 for ($j = $matrix2Columns; $j < $matrix1Columns; ++$j) {
2549 $matrix2[$i][$j] = $x;
2550 }
2551 }
2552 }
2553 if ($matrix2Rows < $matrix1Rows) {
2554 $x = $matrix2[$matrix2Rows-1];
2555 for ($i = 0; $i < $matrix1Rows; ++$i) {
2556 $matrix2[$i] = $x;
2557 }
2558 }
2559 }
2560
2561 if (($matrix1Columns < $matrix2Columns) || ($matrix1Rows < $matrix2Rows)) {
2562 if ($matrix1Columns < $matrix2Columns) {
2563 for ($i = 0; $i < $matrix1Rows; ++$i) {
2564 $x = $matrix1[$i][$matrix1Columns-1];
2565 for ($j = $matrix1Columns; $j < $matrix2Columns; ++$j) {
2566 $matrix1[$i][$j] = $x;
2567 }
2568 }
2569 }
2570 if ($matrix1Rows < $matrix2Rows) {
2571 $x = $matrix1[$matrix1Rows-1];
2572 for ($i = 0; $i < $matrix2Rows; ++$i) {
2573 $matrix1[$i] = $x;
2574 }
2575 }
2576 }
2577 } // function _resizeMatricesExtend()

References $x.

Referenced by _checkMatrixOperands().

+ Here is the caller graph for this function:

◆ _resizeMatricesShrink()

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
integer$matrix1RowsRow size of first matrix operand
integer$matrix1ColumnsColumn size of first matrix operand
integer$matrix2RowsRow size of second matrix operand
integer$matrix2ColumnsColumn size of second matrix operand

Definition at line 2500 of file Calculation.php.

2500 {
2501 if (($matrix2Columns < $matrix1Columns) || ($matrix2Rows < $matrix1Rows)) {
2502 if ($matrix2Rows < $matrix1Rows) {
2503 for ($i = $matrix2Rows; $i < $matrix1Rows; ++$i) {
2504 unset($matrix1[$i]);
2505 }
2506 }
2507 if ($matrix2Columns < $matrix1Columns) {
2508 for ($i = 0; $i < $matrix1Rows; ++$i) {
2509 for ($j = $matrix2Columns; $j < $matrix1Columns; ++$j) {
2510 unset($matrix1[$i][$j]);
2511 }
2512 }
2513 }
2514 }
2515
2516 if (($matrix1Columns < $matrix2Columns) || ($matrix1Rows < $matrix2Rows)) {
2517 if ($matrix1Rows < $matrix2Rows) {
2518 for ($i = $matrix1Rows; $i < $matrix2Rows; ++$i) {
2519 unset($matrix2[$i]);
2520 }
2521 }
2522 if ($matrix1Columns < $matrix2Columns) {
2523 for ($i = 0; $i < $matrix2Rows; ++$i) {
2524 for ($j = $matrix1Columns; $j < $matrix2Columns; ++$j) {
2525 unset($matrix2[$i][$j]);
2526 }
2527 }
2528 }
2529 }
2530 } // function _resizeMatricesShrink()

Referenced by _checkMatrixOperands().

+ Here is the caller graph for this function:

◆ _showTypeDetails()

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 2621 of file Calculation.php.

2621 {
2622 if ($this->_debugLog->getWriteDebugLog()) {
2624 if (count($testArray) == 1) {
2625 $value = array_pop($testArray);
2626 }
2627
2628 if ($value === NULL) {
2629 return 'a NULL value';
2630 } elseif (is_float($value)) {
2631 $typeString = 'a floating point number';
2632 } elseif(is_int($value)) {
2633 $typeString = 'an integer number';
2634 } elseif(is_bool($value)) {
2635 $typeString = 'a boolean';
2636 } elseif(is_array($value)) {
2637 $typeString = 'a matrix';
2638 } else {
2639 if ($value == '') {
2640 return 'an empty string';
2641 } elseif ($value{0} == '#') {
2642 return 'a '.$value.' error';
2643 } else {
2644 $typeString = 'a string';
2645 }
2646 }
2647 return $typeString.' with a value of '.$this->_showValue($value);
2648 }
2649 } // function _showTypeDetails()

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

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

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _showValue()

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 2586 of file Calculation.php.

2586 {
2587 if ($this->_debugLog->getWriteDebugLog()) {
2589 if (count($testArray) == 1) {
2590 $value = array_pop($testArray);
2591 }
2592
2593 if (is_array($value)) {
2594 $returnMatrix = array();
2595 $pad = $rpad = ', ';
2596 foreach($value as $row) {
2597 if (is_array($row)) {
2598 $returnMatrix[] = implode($pad,array_map(array($this,'_showValue'),$row));
2599 $rpad = '; ';
2600 } else {
2601 $returnMatrix[] = $this->_showValue($row);
2602 }
2603 }
2604 return '{ '.implode($rpad,$returnMatrix).' }';
2605 } elseif(is_string($value) && (trim($value,'"') == $value)) {
2606 return '"'.$value.'"';
2607 } elseif(is_bool($value)) {
2608 return ($value) ? self::$_localeBoolean['TRUE'] : self::$_localeBoolean['FALSE'];
2609 }
2610 }
2612 } // function _showValue()

References $row, _showValue(), PHPExcel_Calculation_Functions\flattenArray(), and PHPExcel_Calculation_Functions\flattenSingleValue().

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

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _translateFormula()

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

Definition at line 2055 of file Calculation.php.

2055 {
2056 // Convert any Excel function names to the required language
2057 if (self::$_localeLanguage !== 'en_us') {
2058 $inBraces = FALSE;
2059 // If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators
2060 if (strpos($formula,'"') !== FALSE) {
2061 // So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded
2062 // the formula
2063 $temp = explode('"',$formula);
2064 $i = FALSE;
2065 foreach($temp as &$value) {
2066 // Only count/replace in alternating array entries
2067 if ($i = !$i) {
2068 $value = preg_replace($from,$to,$value);
2069 $value = self::_translateSeparator($fromSeparator,$toSeparator,$value,$inBraces);
2070 }
2071 }
2072 unset($value);
2073 // Then rebuild the formula string
2074 $formula = implode('"',$temp);
2075 } else {
2076 // If there's no quoted strings, then we do a simple count/replace
2077 $formula = preg_replace($from,$to,$formula);
2078 $formula = self::_translateSeparator($fromSeparator,$toSeparator,$formula,$inBraces);
2079 }
2080 }
2081
2082 return $formula;
2083 }
static _translateSeparator($fromSeparator, $toSeparator, $formula, &$inBraces)

References _translateSeparator().

Referenced by _translateFormulaToEnglish(), and _translateFormulaToLocale().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _translateFormulaToEnglish()

PHPExcel_Calculation::_translateFormulaToEnglish (   $formula)

Definition at line 2117 of file Calculation.php.

2117 {
2118 if (self::$functionReplaceFromLocale === NULL) {
2119 self::$functionReplaceFromLocale = array();
2120 foreach(array_values(self::$_localeFunctions) as $localeFunctionName) {
2121 self::$functionReplaceFromLocale[] = '/(@?[^\w\.])'.preg_quote($localeFunctionName).'([\s]*\‍()/Ui';
2122 }
2123 foreach(array_values(self::$_localeBoolean) as $excelBoolean) {
2124 self::$functionReplaceFromLocale[] = '/(@?[^\w\.])'.preg_quote($excelBoolean).'([^\w\.])/Ui';
2125 }
2126 }
2127
2128 if (self::$functionReplaceToExcel === NULL) {
2129 self::$functionReplaceToExcel = array();
2130 foreach(array_keys(self::$_localeFunctions) as $excelFunctionName) {
2131 self::$functionReplaceToExcel[] = '$1'.trim($excelFunctionName).'$2';
2132 }
2133 foreach(array_keys(self::$_localeBoolean) as $excelBoolean) {
2134 self::$functionReplaceToExcel[] = '$1'.trim($excelBoolean).'$2';
2135 }
2136 }
2137
2138 return self::_translateFormula(self::$functionReplaceFromLocale,self::$functionReplaceToExcel,$formula,self::$_localeArgumentSeparator,',');
2139 } // function _translateFormulaToEnglish()
static _translateFormula($from, $to, $formula, $fromSeparator, $toSeparator)

References _translateFormula().

+ Here is the call graph for this function:

◆ _translateFormulaToLocale()

PHPExcel_Calculation::_translateFormulaToLocale (   $formula)

Definition at line 2088 of file Calculation.php.

2088 {
2089 if (self::$functionReplaceFromExcel === NULL) {
2090 self::$functionReplaceFromExcel = array();
2091 foreach(array_keys(self::$_localeFunctions) as $excelFunctionName) {
2092 self::$functionReplaceFromExcel[] = '/(@?[^\w\.])'.preg_quote($excelFunctionName).'([\s]*\‍()/Ui';
2093 }
2094 foreach(array_keys(self::$_localeBoolean) as $excelBoolean) {
2095 self::$functionReplaceFromExcel[] = '/(@?[^\w\.])'.preg_quote($excelBoolean).'([^\w\.])/Ui';
2096 }
2097
2098 }
2099
2100 if (self::$functionReplaceToLocale === NULL) {
2101 self::$functionReplaceToLocale = array();
2102 foreach(array_values(self::$_localeFunctions) as $localeFunctionName) {
2103 self::$functionReplaceToLocale[] = '$1'.trim($localeFunctionName).'$2';
2104 }
2105 foreach(array_values(self::$_localeBoolean) as $localeBoolean) {
2106 self::$functionReplaceToLocale[] = '$1'.trim($localeBoolean).'$2';
2107 }
2108 }
2109
2110 return self::_translateFormula(self::$functionReplaceFromExcel,self::$functionReplaceToLocale,$formula,',',self::$_localeArgumentSeparator);
2111 } // function _translateFormulaToLocale()

References _translateFormula().

+ Here is the call graph for this function:

◆ _translateSeparator()

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

Definition at line 2037 of file Calculation.php.

2037 {
2038 $strlen = mb_strlen($formula);
2039 for ($i = 0; $i < $strlen; ++$i) {
2040 $chr = mb_substr($formula,$i,1);
2041 switch ($chr) {
2042 case '{' : $inBraces = TRUE;
2043 break;
2044 case '}' : $inBraces = FALSE;
2045 break;
2046 case $fromSeparator :
2047 if (!$inBraces) {
2048 $formula = mb_substr($formula,0,$i).$toSeparator.mb_substr($formula,$i+1);
2049 }
2050 }
2051 }
2052 return $formula;
2053 }

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

+ Here is the caller graph for this function:

◆ _unwrapResult()

static PHPExcel_Calculation::_unwrapResult (   $value)
static

Remove quotes used as a wrapper to identify string values.

Parameters
mixed$value
Returns
mixed

Definition at line 2187 of file Calculation.php.

2187 {
2188 if (is_string($value)) {
2189 if ((isset($value{0})) && ($value{0} == '"') && (substr($value,-1) == '"')) {
2190 return substr($value,1,-1);
2191 }
2192 // Convert numeric errors to NaN error
2193 } else if((is_float($value)) && ((is_nan($value)) || (is_infinite($value)))) {
2195 }
2196 return $value;
2197 } // function _unwrapResult()

References PHPExcel_Calculation_Functions\NaN().

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

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _validateBinaryOperand()

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

Definition at line 3498 of file Calculation.php.

3498 {
3499 if (is_array($operand)) {
3500 if ((count($operand, COUNT_RECURSIVE) - count($operand)) == 1) {
3501 do {
3502 $operand = array_pop($operand);
3503 } while (is_array($operand));
3504 }
3505 }
3506 // Numbers, matrices and booleans can pass straight through, as they're already valid
3507 if (is_string($operand)) {
3508 // We only need special validations for the operand if it is a string
3509 // Start by stripping off the quotation marks we use to identify true excel string values internally
3510 if ($operand > '' && $operand{0} == '"') { $operand = self::_unwrapResult($operand); }
3511 // If the string is a numeric value, we treat it as a numeric, so no further testing
3512 if (!is_numeric($operand)) {
3513 // If not a numeric, test to see if the value is an Excel error, and so can't be used in normal binary operations
3514 if ($operand > '' && $operand{0} == '#') {
3515 $stack->push('Value', $operand);
3516 $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($operand));
3517 return FALSE;
3519 // If not a numeric or a fraction, then it's a text string, and so can't be used in mathematical binary operations
3520 $stack->push('Value', '#VALUE!');
3521 $this->_debugLog->writeDebugLog('Evaluation Result is a ', $this->_showTypeDetails('#VALUE!'));
3522 return FALSE;
3523 }
3524 }
3525 }
3526
3527 // return a true if the value of the operand is one that we can use in normal binary operations
3528 return TRUE;
3529 } // function _validateBinaryOperand()
static convertToNumberIfFraction(&$operand)
Identify whether a string contains a fractional numeric value, and convert it to a numeric if it is.
Definition: String.php:671

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

Referenced by _executeNumericBinaryOperation().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _wrapResult()

static PHPExcel_Calculation::_wrapResult (   $value)
static

Wrap string values in quotes.

Parameters
mixed$value
Returns
mixed

Definition at line 2163 of file Calculation.php.

2163 {
2164 if (is_string($value)) {
2165 // Error values cannot be "wrapped"
2166 if (preg_match('/^'.self::CALCULATION_REGEXP_ERROR.'$/i', $value, $match)) {
2167 // Return Excel errors "as is"
2168 return $value;
2169 }
2170 // Return strings wrapped in quotes
2171 return '"'.$value.'"';
2172 // Convert numeric errors to NaN error
2173 } else if((is_float($value)) && ((is_nan($value)) || (is_infinite($value)))) {
2175 }
2176
2177 return $value;
2178 } // function _wrapResult()

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().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ calculate()

PHPExcel_Calculation::calculate ( PHPExcel_Cell  $pCell = NULL)

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

@access public

Parameters
PHPExcel_Cell$pCellCell to calculate
Returns
mixed
Exceptions
PHPExcel_Calculation_Exception

Definition at line 2211 of file Calculation.php.

2211 {
2212 try {
2213 return $this->calculateCellValue($pCell);
2214 } catch (PHPExcel_Exception $e) {
2215 throw new PHPExcel_Calculation_Exception($e->getMessage());
2216 }
2217 } // function calculate()
calculateCellValue(PHPExcel_Cell $pCell=NULL, $resetLog=TRUE)
Calculate the value of a cell formula.

References calculateCellValue().

+ Here is the call graph for this function:

◆ calculateCellValue()

PHPExcel_Calculation::calculateCellValue ( PHPExcel_Cell  $pCell = NULL,
  $resetLog = TRUE 
)

Calculate the value of a cell formula.

@access public

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

Definition at line 2229 of file Calculation.php.

2229 {
2230 if ($pCell === NULL) {
2231 return NULL;
2232 }
2233
2235 if ($resetLog) {
2236 // Initialise the logging settings if requested
2237 $this->formulaError = null;
2238 $this->_debugLog->clearLog();
2239 $this->_cyclicReferenceStack->clear();
2240 $this->_cyclicFormulaCount = 1;
2241
2242 self::$returnArrayAsType = self::RETURN_ARRAY_AS_ARRAY;
2243 }
2244
2245 // Execute the calculation for the cell formula
2246 $this->_cellStack[] = array(
2247 'sheet' => $pCell->getWorksheet()->getTitle(),
2248 'cell' => $pCell->getCoordinate(),
2249 );
2250 try {
2251 $result = self::_unwrapResult($this->_calculateFormulaValue($pCell->getValue(), $pCell->getCoordinate(), $pCell));
2252 $cellAddress = array_pop($this->_cellStack);
2253 $this->_workbook->getSheetByName($cellAddress['sheet'])->getCell($cellAddress['cell']);
2254 } catch (PHPExcel_Exception $e) {
2255 $cellAddress = array_pop($this->_cellStack);
2256 $this->_workbook->getSheetByName($cellAddress['sheet'])->getCell($cellAddress['cell']);
2257 throw new PHPExcel_Calculation_Exception($e->getMessage());
2258 }
2259
2260 if ((is_array($result)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) {
2261 self::$returnArrayAsType = $returnArrayAsType;
2263 if (self::$returnArrayAsType == self::RETURN_ARRAY_AS_ERROR) {
2265 }
2266 // If there's only a single cell in the array, then we allow it
2267 if (count($testResult) != 1) {
2268 // If keys are numeric, then it's a matrix result rather than a cell range result, so we permit it
2269 $r = array_keys($result);
2270 $r = array_shift($r);
2271 if (!is_numeric($r)) { return PHPExcel_Calculation_Functions::VALUE(); }
2272 if (is_array($result[$r])) {
2273 $c = array_keys($result[$r]);
2274 $c = array_shift($c);
2275 if (!is_numeric($c)) {
2277 }
2278 }
2279 }
2280 $result = array_shift($testResult);
2281 }
2282 self::$returnArrayAsType = $returnArrayAsType;
2283
2284
2285 if ($result === NULL) {
2286 return 0;
2287 } elseif((is_float($result)) && ((is_nan($result)) || (is_infinite($result)))) {
2289 }
2290 return $result;
2291 } // function calculateCellValue(
_calculateFormulaValue($formula, $cellID=null, PHPExcel_Cell $pCell=null)
Parse a cell formula and calculate its value.
getValue()
Get cell value.
Definition: Cell.php:181

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

Referenced by calculate().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ calculateFormula()

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

Calculate the value of a formula.

Parameters
string$formulaFormula to parse
string$cellIDAddress of the cell to calculate
PHPExcel_Cell$pCellCell to calculate
Returns
mixed
Exceptions
PHPExcel_Calculation_Exception

Definition at line 2323 of file Calculation.php.

2323 {
2324 // Initialise the logging settings
2325 $this->formulaError = null;
2326 $this->_debugLog->clearLog();
2327 $this->_cyclicReferenceStack->clear();
2328
2329 // Disable calculation cacheing because it only applies to cell calculations, not straight formulae
2330 // But don't actually flush any cache
2331 $resetCache = $this->getCalculationCacheEnabled();
2332 $this->_calculationCacheEnabled = FALSE;
2333 // Execute the calculation
2334 try {
2335 $result = self::_unwrapResult($this->_calculateFormulaValue($formula, $cellID, $pCell));
2336 } catch (PHPExcel_Exception $e) {
2337 throw new PHPExcel_Calculation_Exception($e->getMessage());
2338 }
2339
2340 // Reset calculation cacheing to its previous state
2341 $this->_calculationCacheEnabled = $resetCache;
2342
2343 return $result;
2344 } // function calculateFormula()
getCalculationCacheEnabled()
Is calculation caching enabled?

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

+ Here is the call graph for this function:

◆ clearCalculationCache()

PHPExcel_Calculation::clearCalculationCache ( )

Clear calculation cache.

Definition at line 1917 of file Calculation.php.

1917 {
1918 $this->_calculationCache = array();
1919 } // function clearCalculationCache()

Referenced by flushInstance(), and setCalculationCacheEnabled().

+ Here is the caller graph for this function:

◆ clearCalculationCacheForWorksheet()

PHPExcel_Calculation::clearCalculationCacheForWorksheet (   $worksheetName)

Clear calculation cache for a specified worksheet.

Parameters
string$worksheetName

Definition at line 1926 of file Calculation.php.

1926 {
1927 if (isset($this->_calculationCache[$worksheetName])) {
1928 unset($this->_calculationCache[$worksheetName]);
1929 }
1930 } // function clearCalculationCacheForWorksheet()

◆ disableCalculationCache()

PHPExcel_Calculation::disableCalculationCache ( )

Disable calculation cache.

Definition at line 1909 of file Calculation.php.

1909 {
1910 $this->setCalculationCacheEnabled(FALSE);
1911 } // function disableCalculationCache()
setCalculationCacheEnabled($pValue=TRUE)
Enable/disable calculation cache.

References setCalculationCacheEnabled().

+ Here is the call graph for this function:

◆ enableCalculationCache()

PHPExcel_Calculation::enableCalculationCache ( )

Enable calculation cache.

Definition at line 1901 of file Calculation.php.

1901 {
1902 $this->setCalculationCacheEnabled(TRUE);
1903 } // function enableCalculationCache()

References setCalculationCacheEnabled().

+ Here is the call graph for this function:

◆ extractCellRange()

PHPExcel_Calculation::extractCellRange ( $pRange = 'A1',
PHPExcel_Worksheet  $pSheet = NULL,
  $resetLog = TRUE 
)

Extract range values.

Parameters
string&$pRangeString based range representation
PHPExcel_Worksheet$pSheetWorksheet
boolean$resetLogFlag indicating whether calculation log should be reset or not
Returns
mixed Array of values in range if range contains more than one element. Otherwise, a single value is returned.
Exceptions
PHPExcel_Calculation_Exception

Definition at line 3748 of file Calculation.php.

3748 {
3749 // Return value
3750 $returnValue = array ();
3751
3752// echo 'extractCellRange('.$pRange.')',PHP_EOL;
3753 if ($pSheet !== NULL) {
3754 $pSheetName = $pSheet->getTitle();
3755// echo 'Passed sheet name is '.$pSheetName.PHP_EOL;
3756// echo 'Range reference is '.$pRange.PHP_EOL;
3757 if (strpos ($pRange, '!') !== false) {
3758// echo '$pRange reference includes sheet reference',PHP_EOL;
3759 list($pSheetName,$pRange) = PHPExcel_Worksheet::extractSheetTitle($pRange, true);
3760// echo 'New sheet name is '.$pSheetName,PHP_EOL;
3761// echo 'Adjusted Range reference is '.$pRange,PHP_EOL;
3762 $pSheet = $this->_workbook->getSheetByName($pSheetName);
3763 }
3764
3765 // Extract range
3766 $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange);
3767 $pRange = $pSheetName.'!'.$pRange;
3768 if (!isset($aReferences[1])) {
3769 // Single cell in range
3770 sscanf($aReferences[0],'%[A-Z]%d', $currentCol, $currentRow);
3771 $cellValue = NULL;
3772 if ($pSheet->cellExists($aReferences[0])) {
3773 $returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog);
3774 } else {
3775 $returnValue[$currentRow][$currentCol] = NULL;
3776 }
3777 } else {
3778 // Extract cell data for all cells in the range
3779 foreach ($aReferences as $reference) {
3780 // Extract range
3781 sscanf($reference,'%[A-Z]%d', $currentCol, $currentRow);
3782 $cellValue = NULL;
3783 if ($pSheet->cellExists($reference)) {
3784 $returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog);
3785 } else {
3786 $returnValue[$currentRow][$currentCol] = NULL;
3787 }
3788 }
3789 }
3790 }
3791
3792 // Return
3793 return $returnValue;
3794 } // function extractCellRange()
static extractAllCellReferencesInRange($pRange='A1')
Extract all cell references in range.
Definition: Cell.php:854
getCell($pCoordinate='A1')
Get cell at a specific coordinate.
Definition: Worksheet.php:1153
static extractSheetTitle($pRange, $returnRange=false)
Extract worksheet title from range.
Definition: Worksheet.php:2654
getTitle()
Get title.
Definition: Worksheet.php:817
cellExists($pCoordinate='A1')
Does the cell at a specific coordinate exist?
Definition: Worksheet.php:1256

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

Referenced by _processTokenStack().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ extractNamedRange()

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.
Parameters
boolean$resetLogFlag indicating whether calculation log should be reset or not
Exceptions
PHPExcel_Calculation_Exception

Definition at line 3806 of file Calculation.php.

3806 {
3807 // Return value
3808 $returnValue = array ();
3809
3810// echo 'extractNamedRange('.$pRange.')<br />';
3811 if ($pSheet !== NULL) {
3812 $pSheetName = $pSheet->getTitle();
3813// echo 'Current sheet name is '.$pSheetName.'<br />';
3814// echo 'Range reference is '.$pRange.'<br />';
3815 if (strpos ($pRange, '!') !== false) {
3816// echo '$pRange reference includes sheet reference',PHP_EOL;
3817 list($pSheetName,$pRange) = PHPExcel_Worksheet::extractSheetTitle($pRange, true);
3818// echo 'New sheet name is '.$pSheetName,PHP_EOL;
3819// echo 'Adjusted Range reference is '.$pRange,PHP_EOL;
3820 $pSheet = $this->_workbook->getSheetByName($pSheetName);
3821 }
3822
3823 // Named range?
3824 $namedRange = PHPExcel_NamedRange::resolveRange($pRange, $pSheet);
3825 if ($namedRange !== NULL) {
3826 $pSheet = $namedRange->getWorksheet();
3827// echo 'Named Range '.$pRange.' (';
3828 $pRange = $namedRange->getRange();
3829 $splitRange = PHPExcel_Cell::splitRange($pRange);
3830 // Convert row and column references
3831 if (ctype_alpha($splitRange[0][0])) {
3832 $pRange = $splitRange[0][0] . '1:' . $splitRange[0][1] . $namedRange->getWorksheet()->getHighestRow();
3833 } elseif(ctype_digit($splitRange[0][0])) {
3834 $pRange = 'A' . $splitRange[0][0] . ':' . $namedRange->getWorksheet()->getHighestColumn() . $splitRange[0][1];
3835 }
3836// echo $pRange.') is in sheet '.$namedRange->getWorksheet()->getTitle().'<br />';
3837
3838// if ($pSheet->getTitle() != $namedRange->getWorksheet()->getTitle()) {
3839// if (!$namedRange->getLocalOnly()) {
3840// $pSheet = $namedRange->getWorksheet();
3841// } else {
3842// return $returnValue;
3843// }
3844// }
3845 } else {
3847 }
3848
3849 // Extract range
3850 $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange);
3851// var_dump($aReferences);
3852 if (!isset($aReferences[1])) {
3853 // Single cell (or single column or row) in range
3854 list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($aReferences[0]);
3855 $cellValue = NULL;
3856 if ($pSheet->cellExists($aReferences[0])) {
3857 $returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog);
3858 } else {
3859 $returnValue[$currentRow][$currentCol] = NULL;
3860 }
3861 } else {
3862 // Extract cell data for all cells in the range
3863 foreach ($aReferences as $reference) {
3864 // Extract range
3865 list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($reference);
3866// echo 'NAMED RANGE: $currentCol='.$currentCol.' $currentRow='.$currentRow.'<br />';
3867 $cellValue = NULL;
3868 if ($pSheet->cellExists($reference)) {
3869 $returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog);
3870 } else {
3871 $returnValue[$currentRow][$currentCol] = NULL;
3872 }
3873 }
3874 }
3875// print_r($returnValue);
3876// echo '<br />';
3877 }
3878
3879 // Return
3880 return $returnValue;
3881 } // function extractNamedRange()
static splitRange($pRange='A1:A1')
Split range into coordinate strings.
Definition: Cell.php:660
static resolveRange($pNamedRange='', PHPExcel_Worksheet $pSheet)
Resolve a named range to a regular cell range.
Definition: NamedRange.php:229

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

Referenced by _processTokenStack().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ flushInstance()

PHPExcel_Calculation::flushInstance ( )

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

@access public

Returns
null

Definition at line 1801 of file Calculation.php.

1801 {
1802 $this->clearCalculationCache();
1803 } // function flushInstance()
clearCalculationCache()
Clear calculation cache.

References clearCalculationCache().

+ Here is the call graph for this function:

◆ getArrayReturnType()

static PHPExcel_Calculation::getArrayReturnType ( )
static

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

@access public

Returns
string $returnType Array return type

Definition at line 1871 of file Calculation.php.

1871 {
1873 } // function getArrayReturnType()

References $returnArrayAsType.

Referenced by PHPExcel_Writer_PDF_Core\prepareForSave(), PHPExcel_Writer_CSV\save(), and PHPExcel_Writer_HTML\save().

+ Here is the caller graph for this function:

◆ getCalculationCacheEnabled()

PHPExcel_Calculation::getCalculationCacheEnabled ( )

Is calculation caching enabled?

@access public

Returns
boolean

Definition at line 1882 of file Calculation.php.

1882 {
1884 } // function getCalculationCacheEnabled()

References $_calculationCacheEnabled.

Referenced by calculateFormula().

+ Here is the caller graph for this function:

◆ getDebugLog()

PHPExcel_Calculation::getDebugLog ( )

Get the debuglog for this claculation engine instance.

@access public

Returns
PHPExcel_CalcEngine_Logger

Definition at line 1812 of file Calculation.php.

1812 {
1813 return $this->_debugLog;
1814 }

◆ getFALSE()

◆ getInstance()

static PHPExcel_Calculation::getInstance ( PHPExcel  $workbook = NULL)
static

Get an instance of this class.

@access public

Parameters
PHPExcel$workbookInjected workbook for working with a PHPExcel object, or NULL to create a standalone claculation engine
Returns
PHPExcel_Calculation

Definition at line 1765 of file Calculation.php.

1765 {
1766 if ($workbook !== NULL) {
1767 if (isset(self::$_workbookSets[$workbook->getID()])) {
1768 return self::$_workbookSets[$workbook->getID()];
1769 }
1770 return new PHPExcel_Calculation($workbook);
1771 }
1772
1773 if (!isset(self::$_instance) || (self::$_instance === NULL)) {
1774 self::$_instance = new PHPExcel_Calculation();
1775 }
1776
1777 return self::$_instance;
1778 } // function getInstance()

References $_instance.

Referenced by PHPExcel\__construct(), PHPExcel_Worksheet\__destruct(), PHPExcel_Calculation_Database\__filter(), PHPExcel_Calculation_Statistical\AVERAGEIF(), PHPExcel_Shared_String\convertToNumberIfFraction(), PHPExcel_Calculation_Statistical\COUNTIF(), PHPExcel_Cell\getCalculatedValue(), PHPExcel_Calculation_LookupRef\INDIRECT(), PHPExcel_Calculation_Statistical\MAXIF(), PHPExcel_Calculation_Statistical\MINIF(), PHPExcel_Calculation_LookupRef\OFFSET(), PHPExcel_Chart_DataSeriesValues\refresh(), PHPExcel_Writer_CSV\save(), PHPExcel_Writer_Excel2007\save(), PHPExcel_Writer_Excel5\save(), PHPExcel_Writer_HTML\save(), PHPExcel_Settings\setLocale(), PHPExcel_Worksheet\setTitle(), PHPExcel_Worksheet_AutoFilter\showHideRows(), PHPExcel_Calculation_MathTrig\SUMIF(), and CalculationTest\testBinaryComparisonOperation().

+ Here is the caller graph for this function:

◆ getLocale()

PHPExcel_Calculation::getLocale ( )

Get the currently defined locale code.

Returns
string

Definition at line 1951 of file Calculation.php.

1951 {
1953 } // function getLocale()

References $_localeLanguage.

◆ getTRUE()

◆ getValueFromCache()

PHPExcel_Calculation::getValueFromCache (   $cellReference,
$cellValue 
)

Definition at line 2347 of file Calculation.php.

2347 {
2348 // Is calculation cacheing enabled?
2349 // Is the value present in calculation cache?
2350 $this->_debugLog->writeDebugLog('Testing cache value for cell ', $cellReference);
2351 if (($this->_calculationCacheEnabled) && (isset($this->_calculationCache[$cellReference]))) {
2352 $this->_debugLog->writeDebugLog('Retrieving value for cell ', $cellReference, ' from cache');
2353 // Return the cached result
2354 $cellValue = $this->_calculationCache[$cellReference];
2355 return TRUE;
2356 }
2357 return FALSE;
2358 }

Referenced by _calculateFormulaValue().

+ Here is the caller graph for this function:

◆ isImplemented()

PHPExcel_Calculation::isImplemented (   $pFunction = '')

Is a specific function implemented?

Parameters
string$pFunctionFunction Name
Returns
boolean

Definition at line 3890 of file Calculation.php.

3890 {
3891 $pFunction = strtoupper ($pFunction);
3892 if (isset(self::$_PHPExcelFunctions[$pFunction])) {
3893 return (self::$_PHPExcelFunctions[$pFunction]['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY');
3894 } else {
3895 return FALSE;
3896 }
3897 } // function isImplemented()

◆ listAllFunctionNames()

PHPExcel_Calculation::listAllFunctionNames ( )

Get a list of all Excel function names.

Returns
array

Definition at line 3928 of file Calculation.php.

3928 {
3929 return array_keys(self::$_PHPExcelFunctions);
3930 } // function listAllFunctionNames()

◆ listFunctionNames()

PHPExcel_Calculation::listFunctionNames ( )

Get a list of implemented Excel function names.

Returns
array

Definition at line 3937 of file Calculation.php.

3937 {
3938 // Return value
3939 $returnValue = array();
3940 // Loop functions
3941 foreach(self::$_PHPExcelFunctions as $functionName => $function) {
3942 if ($function['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY') {
3943 $returnValue[] = $functionName;
3944 }
3945 }
3946
3947 // Return
3948 return $returnValue;
3949 } // function listFunctionNames()

◆ listFunctions()

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 3905 of file Calculation.php.

3905 {
3906 // Return value
3907 $returnValue = array();
3908 // Loop functions
3909 foreach(self::$_PHPExcelFunctions as $functionName => $function) {
3910 if ($function['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY') {
3911 $returnValue[$functionName] = new PHPExcel_Calculation_Function($function['category'],
3912 $functionName,
3913 $function['functionCall']
3914 );
3915 }
3916 }
3917
3918 // Return
3919 return $returnValue;
3920 } // function listFunctions()

◆ parseFormula()

PHPExcel_Calculation::parseFormula (   $formula)

Validate and parse a formula string.

Parameters
string$formulaFormula to parse
Returns
array
Exceptions
PHPExcel_Calculation_Exception

Definition at line 2301 of file Calculation.php.

2301 {
2302 // Basic validation that this is indeed a formula
2303 // We return an empty array if not
2304 $formula = trim($formula);
2305 if ((!isset($formula{0})) || ($formula{0} != '=')) return array();
2306 $formula = ltrim(substr($formula,1));
2307 if (!isset($formula{0})) return array();
2308
2309 // Parse the formula and return the token stack
2310 return $this->_parseFormula($formula);
2311 } // function parseFormula()

References _parseFormula().

+ Here is the call graph for this function:

◆ renameCalculationCacheForWorksheet()

PHPExcel_Calculation::renameCalculationCacheForWorksheet (   $fromWorksheetName,
  $toWorksheetName 
)

Rename calculation cache for a specified worksheet.

Parameters
string$fromWorksheetName
string$toWorksheetName

Definition at line 1938 of file Calculation.php.

1938 {
1939 if (isset($this->_calculationCache[$fromWorksheetName])) {
1940 $this->_calculationCache[$toWorksheetName] = &$this->_calculationCache[$fromWorksheetName];
1941 unset($this->_calculationCache[$fromWorksheetName]);
1942 }
1943 } // function renameCalculationCacheForWorksheet()

◆ saveValueToCache()

PHPExcel_Calculation::saveValueToCache (   $cellReference,
  $cellValue 
)

Definition at line 2360 of file Calculation.php.

2360 {
2361 if ($this->_calculationCacheEnabled) {
2362 $this->_calculationCache[$cellReference] = $cellValue;
2363 }
2364 }

Referenced by _calculateFormulaValue().

+ Here is the caller graph for this function:

◆ setArrayReturnType()

static PHPExcel_Calculation::setArrayReturnType (   $returnType)
static

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

@access public

Parameters
string$returnTypeArray return type
Returns
boolean Success or failure

Definition at line 1854 of file Calculation.php.

1854 {
1855 if (($returnType == self::RETURN_ARRAY_AS_VALUE) ||
1856 ($returnType == self::RETURN_ARRAY_AS_ERROR) ||
1857 ($returnType == self::RETURN_ARRAY_AS_ARRAY)) {
1858 self::$returnArrayAsType = $returnType;
1859 return TRUE;
1860 }
1861 return FALSE;
1862 } // function setArrayReturnType()

Referenced by PHPExcel_Writer_PDF_Core\prepareForSave(), PHPExcel_Writer_PDF_Core\restoreStateAfterSave(), PHPExcel_Writer_CSV\save(), PHPExcel_Writer_HTML\save(), and MathTrigTest\testMROUND().

+ Here is the caller graph for this function:

◆ setCalculationCacheEnabled()

PHPExcel_Calculation::setCalculationCacheEnabled (   $pValue = TRUE)

Enable/disable calculation cache.

@access public

Parameters
boolean$pValue

Definition at line 1892 of file Calculation.php.

1892 {
1893 $this->_calculationCacheEnabled = $pValue;
1894 $this->clearCalculationCache();
1895 } // function setCalculationCacheEnabled()

References clearCalculationCache().

Referenced by disableCalculationCache(), and enableCalculationCache().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setLocale()

PHPExcel_Calculation::setLocale (   $locale = 'en_us')

Set the locale code.

Parameters
string$localeThe locale to use for formula translation
Returns
boolean

Definition at line 1962 of file Calculation.php.

1962 {
1963 // Identify our locale and language
1964 $language = $locale = strtolower($locale);
1965 if (strpos($locale,'_') !== FALSE) {
1966 list($language) = explode('_',$locale);
1967 }
1968
1969 if (count(self::$_validLocaleLanguages) == 1)
1971
1972 // Test whether we have any language data for this language (any locale)
1973 if (in_array($language,self::$_validLocaleLanguages)) {
1974 // initialise language/locale settings
1975 self::$_localeFunctions = array();
1976 self::$_localeArgumentSeparator = ',';
1977 self::$_localeBoolean = array('TRUE' => 'TRUE', 'FALSE' => 'FALSE', 'NULL' => 'NULL');
1978 // Default is English, if user isn't requesting english, then read the necessary data from the locale files
1979 if ($locale != 'en_us') {
1980 // Search for a file with a list of function names for locale
1981 $functionNamesFile = PHPEXCEL_ROOT . 'PHPExcel'.DIRECTORY_SEPARATOR.'locale'.DIRECTORY_SEPARATOR.str_replace('_',DIRECTORY_SEPARATOR,$locale).DIRECTORY_SEPARATOR.'functions';
1982 if (!file_exists($functionNamesFile)) {
1983 // If there isn't a locale specific function file, look for a language specific function file
1984 $functionNamesFile = PHPEXCEL_ROOT . 'PHPExcel'.DIRECTORY_SEPARATOR.'locale'.DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.'functions';
1985 if (!file_exists($functionNamesFile)) {
1986 return FALSE;
1987 }
1988 }
1989 // Retrieve the list of locale or language specific function names
1990 $localeFunctions = file($functionNamesFile,FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
1991 foreach ($localeFunctions as $localeFunction) {
1992 list($localeFunction) = explode('##',$localeFunction); // Strip out comments
1993 if (strpos($localeFunction,'=') !== FALSE) {
1994 list($fName,$lfName) = explode('=',$localeFunction);
1995 $fName = trim($fName);
1996 $lfName = trim($lfName);
1997 if ((isset(self::$_PHPExcelFunctions[$fName])) && ($lfName != '') && ($fName != $lfName)) {
1998 self::$_localeFunctions[$fName] = $lfName;
1999 }
2000 }
2001 }
2002 // Default the TRUE and FALSE constants to the locale names of the TRUE() and FALSE() functions
2003 if (isset(self::$_localeFunctions['TRUE'])) { self::$_localeBoolean['TRUE'] = self::$_localeFunctions['TRUE']; }
2004 if (isset(self::$_localeFunctions['FALSE'])) { self::$_localeBoolean['FALSE'] = self::$_localeFunctions['FALSE']; }
2005
2006 $configFile = PHPEXCEL_ROOT . 'PHPExcel'.DIRECTORY_SEPARATOR.'locale'.DIRECTORY_SEPARATOR.str_replace('_',DIRECTORY_SEPARATOR,$locale).DIRECTORY_SEPARATOR.'config';
2007 if (!file_exists($configFile)) {
2008 $configFile = PHPEXCEL_ROOT . 'PHPExcel'.DIRECTORY_SEPARATOR.'locale'.DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.'config';
2009 }
2010 if (file_exists($configFile)) {
2011 $localeSettings = file($configFile,FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
2012 foreach ($localeSettings as $localeSetting) {
2013 list($localeSetting) = explode('##',$localeSetting); // Strip out comments
2014 if (strpos($localeSetting,'=') !== FALSE) {
2015 list($settingName,$settingValue) = explode('=',$localeSetting);
2016 $settingName = strtoupper(trim($settingName));
2017 switch ($settingName) {
2018 case 'ARGUMENTSEPARATOR' :
2019 self::$_localeArgumentSeparator = trim($settingValue);
2020 break;
2021 }
2022 }
2023 }
2024 }
2025 }
2026
2027 self::$functionReplaceFromExcel = self::$functionReplaceToExcel =
2028 self::$functionReplaceFromLocale = self::$functionReplaceToLocale = NULL;
2029 self::$_localeLanguage = $locale;
2030 return TRUE;
2031 }
2032 return FALSE;
2033 } // function setLocale()

References _loadLocales().

+ Here is the call graph for this function:

◆ strcmpLowercaseFirst()

PHPExcel_Calculation::strcmpLowercaseFirst (   $str1,
  $str2 
)
private

Compare two strings in the same way as strcmp() except that lowercase come before uppercase letters.

Parameters
string$str1First string value for the comparison
string$str2Second string value for the comparison
Returns
integer

Definition at line 3653 of file Calculation.php.

3654 {
3655 $inversedStr1 = PHPExcel_Shared_String::StrCaseReverse($str1);
3656 $inversedStr2 = PHPExcel_Shared_String::StrCaseReverse($str2);
3657
3658 return strcmp($inversedStr1, $inversedStr2);
3659 }
static StrCaseReverse($pValue='')
Reverse the case of a string, so that all uppercase characters become lowercase and all lowercase cha...
Definition: String.php:648

References PHPExcel_Shared_String\StrCaseReverse().

Referenced by _executeBinaryComparisonOperation().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unsetInstance()

static PHPExcel_Calculation::unsetInstance ( PHPExcel  $workbook = NULL)
static

Unset an instance of this class.

@access public

Parameters
PHPExcel$workbookInjected workbook identifying the instance to unset

Definition at line 1786 of file Calculation.php.

1786 {
1787 if ($workbook !== NULL) {
1788 if (isset(self::$_workbookSets[$workbook->getID()])) {
1789 unset(self::$_workbookSets[$workbook->getID()]);
1790 }
1791 }
1792 }

Referenced by PHPExcel\__destruct().

+ Here is the caller graph for this function:

Field Documentation

◆ $_binaryOperators

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

Definition at line 153 of file Calculation.php.

◆ $_calculationCache

PHPExcel_Calculation::$_calculationCache = array ()
private

Definition at line 121 of file Calculation.php.

◆ $_calculationCacheEnabled

PHPExcel_Calculation::$_calculationCacheEnabled = TRUE
private

Definition at line 130 of file Calculation.php.

Referenced by getCalculationCacheEnabled().

◆ $_cellStack

PHPExcel_Calculation::$_cellStack = array()
private

Definition at line 197 of file Calculation.php.

◆ $_comparisonOperators

PHPExcel_Calculation::$_comparisonOperators = array('>' => TRUE, '<' => TRUE, '=' => TRUE, '>=' => TRUE, '<=' => TRUE, '<>' => TRUE)
staticprivate

Definition at line 2722 of file Calculation.php.

◆ $_controlFunctions

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

Definition at line 1714 of file Calculation.php.

◆ $_cyclicFormulaCell

PHPExcel_Calculation::$_cyclicFormulaCell = ''
private

Definition at line 209 of file Calculation.php.

◆ $_cyclicFormulaCount

PHPExcel_Calculation::$_cyclicFormulaCount = 1
private

Definition at line 207 of file Calculation.php.

Referenced by _calculateFormulaValue().

◆ $_cyclicReferenceStack

PHPExcel_Calculation::$_cyclicReferenceStack
private

Definition at line 195 of file Calculation.php.

◆ $_ExcelConstants

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

Definition at line 273 of file Calculation.php.

◆ $_instance

PHPExcel_Calculation::$_instance
staticprivate

Definition at line 96 of file Calculation.php.

Referenced by getInstance().

◆ $_localeArgumentSeparator

PHPExcel_Calculation::$_localeArgumentSeparator = ','
staticprivate

Definition at line 251 of file Calculation.php.

◆ $_localeBoolean

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

Definition at line 260 of file Calculation.php.

◆ $_localeFunctions

PHPExcel_Calculation::$_localeFunctions = array()
staticprivate

Definition at line 252 of file Calculation.php.

◆ $_localeLanguage

PHPExcel_Calculation::$_localeLanguage = 'en_us'
staticprivate

Definition at line 234 of file Calculation.php.

Referenced by getLocale().

◆ $_operatorAssociativity

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

Definition at line 2711 of file Calculation.php.

◆ $_operatorPrecedence

PHPExcel_Calculation::$_operatorPrecedence
staticprivate
Initial value:
= array(
':' => 8,
'|' => 7,
'~' => 6,
'%' => 5,
'^' => 4,
'*' => 3, '/' => 3,
'+' => 2, '-' => 2,
'&' => 1,
'>' => 0, '<' => 0, '=' => 0, '>=' => 0, '<=' => 0, '<>' => 0
)

Definition at line 2727 of file Calculation.php.

◆ $_operators

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 140 of file Calculation.php.

◆ $_PHPExcelFunctions

PHPExcel_Calculation::$_PHPExcelFunctions
staticprivate

Definition at line 279 of file Calculation.php.

◆ $_savedPrecision

PHPExcel_Calculation::$_savedPrecision = 14
private

Definition at line 225 of file Calculation.php.

◆ $_validLocaleLanguages

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

Definition at line 243 of file Calculation.php.

◆ $_workbook

PHPExcel_Calculation::$_workbook
private

Definition at line 105 of file Calculation.php.

◆ $_workbookSets

PHPExcel_Calculation::$_workbookSets
staticprivate

Definition at line 113 of file Calculation.php.

◆ $cyclicFormulaCount

PHPExcel_Calculation::$cyclicFormulaCount = 1

Definition at line 217 of file Calculation.php.

◆ $debugLog

PHPExcel_Calculation::$debugLog
private

Definition at line 166 of file Calculation.php.

◆ $formulaError

PHPExcel_Calculation::$formulaError = NULL

Definition at line 186 of file Calculation.php.

◆ $functionReplaceFromExcel

PHPExcel_Calculation::$functionReplaceFromExcel = NULL
staticprivate

Definition at line 2085 of file Calculation.php.

◆ $functionReplaceFromLocale

PHPExcel_Calculation::$functionReplaceFromLocale = NULL
staticprivate

Definition at line 2114 of file Calculation.php.

◆ $functionReplaceToExcel

PHPExcel_Calculation::$functionReplaceToExcel = NULL
staticprivate

Definition at line 2115 of file Calculation.php.

◆ $functionReplaceToLocale

PHPExcel_Calculation::$functionReplaceToLocale = NULL
staticprivate

Definition at line 2086 of file Calculation.php.

◆ $returnArrayAsType

PHPExcel_Calculation::$returnArrayAsType = self::RETURN_ARRAY_AS_VALUE
staticprivate

Definition at line 87 of file Calculation.php.

Referenced by calculateCellValue(), and getArrayReturnType().

◆ $suppressFormulaErrors

PHPExcel_Calculation::$suppressFormulaErrors = FALSE

Definition at line 177 of file Calculation.php.

◆ CALCULATION_REGEXP_CELLREF

const PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF = CALCULATION_REGEXP_CELLREF

◆ CALCULATION_REGEXP_ERROR

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

Definition at line 79 of file Calculation.php.

◆ CALCULATION_REGEXP_FUNCTION

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

Definition at line 73 of file Calculation.php.

◆ CALCULATION_REGEXP_NAMEDRANGE

const PHPExcel_Calculation::CALCULATION_REGEXP_NAMEDRANGE = CALCULATION_REGEXP_NAMEDRANGE

◆ CALCULATION_REGEXP_NUMBER

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().

◆ CALCULATION_REGEXP_OPENBRACE

const PHPExcel_Calculation::CALCULATION_REGEXP_OPENBRACE = '\‍('

Definition at line 71 of file Calculation.php.

◆ CALCULATION_REGEXP_STRING

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

Definition at line 69 of file Calculation.php.

◆ RETURN_ARRAY_AS_ARRAY

const PHPExcel_Calculation::RETURN_ARRAY_AS_ARRAY = 'array'

Definition at line 85 of file Calculation.php.

Referenced by calculateCellValue(), and MathTrigTest\testMROUND().

◆ RETURN_ARRAY_AS_ERROR

const PHPExcel_Calculation::RETURN_ARRAY_AS_ERROR = 'error'

constants

Definition at line 83 of file Calculation.php.

◆ RETURN_ARRAY_AS_VALUE

const PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE = 'value'

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