Source for file Calculation.php
Documentation is available at Calculation.php
* Copyright (c) 2006 - 2008 PHPExcel
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* @copyright Copyright (c) 2006 - 2008 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version 1.6.4, 2008-10-27
/** PHPExcel_Worksheet */
require_once 'PHPExcel/Worksheet.php';
require_once 'PHPExcel/Cell.php';
/** PHPExcel_Cell_DataType */
require_once 'PHPExcel/Cell/DataType.php';
require_once 'PHPExcel/RichText.php';
/** PHPExcel_NamedRange */
require_once 'PHPExcel/NamedRange.php';
/** PHPExcel_Calculation_FormulaParser */
require_once 'PHPExcel/Calculation/FormulaParser.php';
/** PHPExcel_Calculation_FormulaToken */
require_once 'PHPExcel/Calculation/FormulaToken.php';
/** PHPExcel_Calculation_Functions */
require_once 'PHPExcel/Calculation/Functions.php';
/** PHPExcel_Calculation_Function */
require_once 'PHPExcel/Calculation/Function.php';
* PHPExcel_Calculation (Singleton)
* @copyright Copyright (c) 2006 - 2008 PHPExcel (http://www.codeplex.com/PHPExcel)
* Function mappings (from Excel to PHPExcel)
* Calculation cache enabled
* Calculation cache expiration time
* @var PHPExcel_Calculation
private static $_instance;
* Get an instance of this class
* @return PHPExcel_Calculation
if (! isset ( self::$_instance ) || is_null ( self::$_instance )) {
self::$_instance = new PHPExcel_Calculation ( );
* Create a new PHPExcel_Calculation
// Assign function mappings
* Is calculation caching enabled?
* Enable/disable calculation cache
* Clear calculation cache
* Get calculation cache expiration time
* Set calculation cache expiration time
* Calculate cell value (using formula)
* @param PHPExcel_Cell $pCell Cell to calculate
public function calculate(PHPExcel_Cell $pCell = null) {
// Is the value present in calculation cache?
if (isset ( $this->_calculationCache [$pCell->getParent ()->getTitle ()] [$pCell->getCoordinate ()] )) {
return $this->_calculationCache [$pCell->getParent ()->getTitle ()] [$pCell->getCoordinate ()] ['data'];
unset ( $this->_calculationCache [$pCell->getParent ()->getTitle ()] [$pCell->getCoordinate ()] );
$formula = $pCell->getValue ();
// Executable formula array
$executableFormulaArray = array ( );
// Parse formula into a tree of tokens
// Loop trough parsed tokens and create an executable formula
$tokenCount = $objParser->getTokenCount();
for($i = 0; $i < $tokenCount; ++ $i) {
$token = $objParser->getToken ( $i );
$tokenType = $token->getTokenType();
$tokenSubType = $token->getTokenSubType();
$tokenValue = $token->getValue();
// Is it a cell reference? Not in a function?
if ($pCell->getParent ()->getCell ( $reference )->getValue () instanceof PHPExcel_RichText) {
$calculatedValue = $pCell->getParent ()->getCell ( $reference )->getValue ()->getPlainText ();
$calculatedValue = $pCell->getParent ()->getCell ( $reference )->getCalculatedValue ();
$calculatedValue = '"' . $calculatedValue . '"';
// Add to executable formula array
array_push ( $executableFormulaArray, $calculatedValue );
// Is it a cell reference? In a function?
// Add to executable formula array
array_push ( $executableFormulaArray, '$this->extractRange("' . $reference . '", $pCell->getParent())' );
// Is it a concatenation operator?
// Add to executable formula array
// Is it a logical operator?
// Add to executable formula array
// Is it a subexpression?
// Add to executable formula array
// Check the function type
if ($tokenValue == 'ARRAY' || $tokenValue == 'ARRAYROW') {
// An array or an array row...
// A regular function call...
// Check if the function call is allowed...
// Add to executable formula array
// Add to executable formula array
array_push ( $executableFormulaArray, '"' . $tmp . '"' );
// Add to executable formula array
array_push ( $executableFormulaArray, $tokenValue );
// Is it an error? Add it as text...
// Add to executable formula array
array_push ( $executableFormulaArray, '"' . $tokenValue . '"' );
array_push ( $executableFormulaArray, $tokenValue );
$fromArray = array('(,', ',,', ',)', '$this');
$toArray = array('(null,', ',null,', ',null)', '$pThat');
$formula = implode ( ' ', $executableFormulaArray );
$formula = str_replace ( $fromArray, $toArray, $formula );
* The following code block can cause an error like:
* Fatal error: Unsupported operand types in ...: runtime-created function on line 1
* This is due to the fact that a FATAL error is an E_ERROR,
* and it can not be caught using try/catch or any other
* Exception/error handling feature in PHP.
* A feature request seems to be made once, but it has been
* closed without any deliverables:
* http://bugs.php.net/bug.php?id=40014
$temporaryCalculationFunction = @create_function ( '$pThat, $pCell', "return $formula;" );
if ($temporaryCalculationFunction === FALSE) {
} catch ( Exception $ex ) {
// Save to calculation cache
$this->_calculationCache [$pCell->getParent ()->getTitle ()] [$pCell->getCoordinate ()] ['data'] = $returnValue;
* __clone implementation. Cloning should not be allowed in a Singleton!
throw new Exception ( "Cloning a Singleton is not allowed!" );
* @param string $pRange String based range representation
* @param PHPExcel_Worksheet $pSheet Worksheet
* @return mixed Array of values in range if range contains more than one element. Otherwise, a single value is returned.
public function extractRange($pRange = 'A1', PHPExcel_Worksheet $pSheet = null) {
$returnValue = array ( );
if (strpos ( $pRange, '!' ) !== false) {
$pSheet = $pSheet->getParent ()->getSheetByName ( $worksheetReference [0] );
$pRange = $worksheetReference [1];
$pRange = $namedRange->getRange ();
if ($pSheet->getHashCode () != $namedRange->getWorksheet ()->getHashCode ()) {
if (! $namedRange->getLocalOnly ()) {
$pSheet = $namedRange->getWorksheet ();
foreach ( $aReferences as $reference ) {
$returnValue [$currentCol] [$currentRow] = $pSheet->getCell ( $reference )->getCalculatedValue ();
// if (strpos ( $pRange, ':' ) === false) {
// while ( is_array ( $returnValue ) ) {
// $returnValue = array_pop ( $returnValue );
* Is a specific function implemented?
* @param string $pFunction Function
return $this->_functionMappings [$pFunction]->getPHPExcelName () == 'PHPExcel_Calculation_Functions::DUMMY';
* Get a list of implemented functions
$returnValue = array ( );
if ($value->getPHPExcelName () != 'PHPExcel_Calculation_Functions::DUMMY') {
$returnValue [] = $value;
* Get a list of implemented Excel function names
$returnValue = array ( );
foreach ( $aFunctions as $key => $value ) {
$returnValue [] = $value->getExcelName ();
|