private function PHPExcel_Calculation::_processTokenStack in Loft Data Grids 7.2
Same name and namespace in other branches
- 6.2 vendor/phpoffice/phpexcel/Classes/PHPExcel/Calculation.php \PHPExcel_Calculation::_processTokenStack()
1 call to PHPExcel_Calculation::_processTokenStack()
- PHPExcel_Calculation::_calculateFormulaValue in vendor/phpoffice/phpexcel/Classes/PHPExcel/Calculation.php
- * Parse a cell formula and calculate its value
*
*
File
- vendor/phpoffice/phpexcel/Classes/PHPExcel/Calculation.php, line 3098
Class
- PHPExcel_Calculation
- PHPExcel_Calculation (Multiton)
Code
private function _processTokenStack($tokens, $cellID = NULL, PHPExcel_Cell $pCell = NULL) {
if ($tokens == FALSE) {
return FALSE;
}
$pCellWorksheet = $pCell !== NULL ? $pCell
->getWorksheet() : NULL;
$pCellParent = $pCell !== NULL ? $pCell
->getParent() : null;
$stack = new PHPExcel_Calculation_Token_Stack();
foreach ($tokens as $tokenData) {
$token = $tokenData['value'];
if (isset(self::$_binaryOperators[$token])) {
if (($operand2Data = $stack
->pop()) === NULL) {
return $this
->_raiseFormulaError('Internal error - Operand value missing from stack');
}
if (($operand1Data = $stack
->pop()) === NULL) {
return $this
->_raiseFormulaError('Internal error - Operand value missing from stack');
}
$operand1 = self::_dataTestReference($operand1Data);
$operand2 = self::_dataTestReference($operand2Data);
if ($token == ':') {
$this->_debugLog
->writeDebugLog('Evaluating Range ', $this
->_showValue($operand1Data['reference']), ' ', $token, ' ', $this
->_showValue($operand2Data['reference']));
}
else {
$this->_debugLog
->writeDebugLog('Evaluating ', $this
->_showValue($operand1), ' ', $token, ' ', $this
->_showValue($operand2));
}
switch ($token) {
case '>':
case '<':
case '>=':
case '<=':
case '=':
case '<>':
$this
->_executeBinaryComparisonOperation($cellID, $operand1, $operand2, $token, $stack);
break;
case ':':
$sheet1 = $sheet2 = '';
if (strpos($operand1Data['reference'], '!') !== FALSE) {
list($sheet1, $operand1Data['reference']) = explode('!', $operand1Data['reference']);
}
else {
$sheet1 = $pCellParent !== NULL ? $pCellWorksheet
->getTitle() : '';
}
if (strpos($operand2Data['reference'], '!') !== FALSE) {
list($sheet2, $operand2Data['reference']) = explode('!', $operand2Data['reference']);
}
else {
$sheet2 = $sheet1;
}
if ($sheet1 == $sheet2) {
if ($operand1Data['reference'] === NULL) {
if (trim($operand1Data['value']) != '' && is_numeric($operand1Data['value'])) {
$operand1Data['reference'] = $pCell
->getColumn() . $operand1Data['value'];
}
elseif (trim($operand1Data['reference']) == '') {
$operand1Data['reference'] = $pCell
->getCoordinate();
}
else {
$operand1Data['reference'] = $operand1Data['value'] . $pCell
->getRow();
}
}
if ($operand2Data['reference'] === NULL) {
if (trim($operand2Data['value']) != '' && is_numeric($operand2Data['value'])) {
$operand2Data['reference'] = $pCell
->getColumn() . $operand2Data['value'];
}
elseif (trim($operand2Data['reference']) == '') {
$operand2Data['reference'] = $pCell
->getCoordinate();
}
else {
$operand2Data['reference'] = $operand2Data['value'] . $pCell
->getRow();
}
}
$oData = array_merge(explode(':', $operand1Data['reference']), explode(':', $operand2Data['reference']));
$oCol = $oRow = array();
foreach ($oData as $oDatum) {
$oCR = PHPExcel_Cell::coordinateFromString($oDatum);
$oCol[] = PHPExcel_Cell::columnIndexFromString($oCR[0]) - 1;
$oRow[] = $oCR[1];
}
$cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)) . min($oRow) . ':' . PHPExcel_Cell::stringFromColumnIndex(max($oCol)) . max($oRow);
if ($pCellParent !== NULL) {
$cellValue = $this
->extractCellRange($cellRef, $this->_workbook
->getSheetByName($sheet1), FALSE);
}
else {
return $this
->_raiseFormulaError('Unable to access Cell Reference');
}
$stack
->push('Cell Reference', $cellValue, $cellRef);
}
else {
$stack
->push('Error', PHPExcel_Calculation_Functions::REF(), NULL);
}
break;
case '+':
$this
->_executeNumericBinaryOperation($cellID, $operand1, $operand2, $token, 'plusEquals', $stack);
break;
case '-':
$this
->_executeNumericBinaryOperation($cellID, $operand1, $operand2, $token, 'minusEquals', $stack);
break;
case '*':
$this
->_executeNumericBinaryOperation($cellID, $operand1, $operand2, $token, 'arrayTimesEquals', $stack);
break;
case '/':
$this
->_executeNumericBinaryOperation($cellID, $operand1, $operand2, $token, 'arrayRightDivide', $stack);
break;
case '^':
$this
->_executeNumericBinaryOperation($cellID, $operand1, $operand2, $token, 'power', $stack);
break;
case '&':
if (is_bool($operand1)) {
$operand1 = $operand1 ? self::$_localeBoolean['TRUE'] : self::$_localeBoolean['FALSE'];
}
if (is_bool($operand2)) {
$operand2 = $operand2 ? self::$_localeBoolean['TRUE'] : self::$_localeBoolean['FALSE'];
}
if (is_array($operand1) || is_array($operand2)) {
self::_checkMatrixOperands($operand1, $operand2, 2);
try {
$matrix = new PHPExcel_Shared_JAMA_Matrix($operand1);
$matrixResult = $matrix
->concat($operand2);
$result = $matrixResult
->getArray();
} catch (PHPExcel_Exception $ex) {
$this->_debugLog
->writeDebugLog('JAMA Matrix Exception: ', $ex
->getMessage());
$result = '#VALUE!';
}
}
else {
$result = '"' . str_replace('""', '"', self::_unwrapResult($operand1, '"') . self::_unwrapResult($operand2, '"')) . '"';
}
$this->_debugLog
->writeDebugLog('Evaluation Result is ', $this
->_showTypeDetails($result));
$stack
->push('Value', $result);
break;
case '|':
$rowIntersect = array_intersect_key($operand1, $operand2);
$cellIntersect = $oCol = $oRow = array();
foreach (array_keys($rowIntersect) as $row) {
$oRow[] = $row;
foreach ($rowIntersect[$row] as $col => $data) {
$oCol[] = PHPExcel_Cell::columnIndexFromString($col) - 1;
$cellIntersect[$row] = array_intersect_key($operand1[$row], $operand2[$row]);
}
}
$cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)) . min($oRow) . ':' . PHPExcel_Cell::stringFromColumnIndex(max($oCol)) . max($oRow);
$this->_debugLog
->writeDebugLog('Evaluation Result is ', $this
->_showTypeDetails($cellIntersect));
$stack
->push('Value', $cellIntersect, $cellRef);
break;
}
}
elseif ($token === '~' || $token === '%') {
if (($arg = $stack
->pop()) === NULL) {
return $this
->_raiseFormulaError('Internal error - Operand value missing from stack');
}
$arg = $arg['value'];
if ($token === '~') {
$this->_debugLog
->writeDebugLog('Evaluating Negation of ', $this
->_showValue($arg));
$multiplier = -1;
}
else {
$this->_debugLog
->writeDebugLog('Evaluating Percentile of ', $this
->_showValue($arg));
$multiplier = 0.01;
}
if (is_array($arg)) {
self::_checkMatrixOperands($arg, $multiplier, 2);
try {
$matrix1 = new PHPExcel_Shared_JAMA_Matrix($arg);
$matrixResult = $matrix1
->arrayTimesEquals($multiplier);
$result = $matrixResult
->getArray();
} catch (PHPExcel_Exception $ex) {
$this->_debugLog
->writeDebugLog('JAMA Matrix Exception: ', $ex
->getMessage());
$result = '#VALUE!';
}
$this->_debugLog
->writeDebugLog('Evaluation Result is ', $this
->_showTypeDetails($result));
$stack
->push('Value', $result);
}
else {
$this
->_executeNumericBinaryOperation($cellID, $multiplier, $arg, '*', 'arrayTimesEquals', $stack);
}
}
elseif (preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '$/i', $token, $matches)) {
$cellRef = NULL;
if (isset($matches[8])) {
if ($pCell === NULL) {
$cellValue = PHPExcel_Calculation_Functions::REF();
}
else {
$cellRef = $matches[6] . $matches[7] . ':' . $matches[9] . $matches[10];
if ($matches[2] > '') {
$matches[2] = trim($matches[2], "\"'");
if (strpos($matches[2], '[') !== FALSE || strpos($matches[2], ']') !== FALSE) {
return $this
->_raiseFormulaError('Unable to access External Workbook');
}
$matches[2] = trim($matches[2], "\"'");
$this->_debugLog
->writeDebugLog('Evaluating Cell Range ', $cellRef, ' in worksheet ', $matches[2]);
if ($pCellParent !== NULL) {
$cellValue = $this
->extractCellRange($cellRef, $this->_workbook
->getSheetByName($matches[2]), FALSE);
}
else {
return $this
->_raiseFormulaError('Unable to access Cell Reference');
}
$this->_debugLog
->writeDebugLog('Evaluation Result for cells ', $cellRef, ' in worksheet ', $matches[2], ' is ', $this
->_showTypeDetails($cellValue));
}
else {
$this->_debugLog
->writeDebugLog('Evaluating Cell Range ', $cellRef, ' in current worksheet');
if ($pCellParent !== NULL) {
$cellValue = $this
->extractCellRange($cellRef, $pCellWorksheet, FALSE);
}
else {
return $this
->_raiseFormulaError('Unable to access Cell Reference');
}
$this->_debugLog
->writeDebugLog('Evaluation Result for cells ', $cellRef, ' is ', $this
->_showTypeDetails($cellValue));
}
}
}
else {
if ($pCell === NULL) {
$cellValue = PHPExcel_Calculation_Functions::REF();
}
else {
$cellRef = $matches[6] . $matches[7];
if ($matches[2] > '') {
$matches[2] = trim($matches[2], "\"'");
if (strpos($matches[2], '[') !== FALSE || strpos($matches[2], ']') !== FALSE) {
return $this
->_raiseFormulaError('Unable to access External Workbook');
}
$this->_debugLog
->writeDebugLog('Evaluating Cell ', $cellRef, ' in worksheet ', $matches[2]);
if ($pCellParent !== NULL) {
$cellSheet = $this->_workbook
->getSheetByName($matches[2]);
if ($cellSheet && $cellSheet
->cellExists($cellRef)) {
$cellValue = $this
->extractCellRange($cellRef, $this->_workbook
->getSheetByName($matches[2]), FALSE);
$pCell
->attach($pCellParent);
}
else {
$cellValue = NULL;
}
}
else {
return $this
->_raiseFormulaError('Unable to access Cell Reference');
}
$this->_debugLog
->writeDebugLog('Evaluation Result for cell ', $cellRef, ' in worksheet ', $matches[2], ' is ', $this
->_showTypeDetails($cellValue));
}
else {
$this->_debugLog
->writeDebugLog('Evaluating Cell ', $cellRef, ' in current worksheet');
if ($pCellParent
->isDataSet($cellRef)) {
$cellValue = $this
->extractCellRange($cellRef, $pCellWorksheet, FALSE);
$pCell
->attach($pCellParent);
}
else {
$cellValue = NULL;
}
$this->_debugLog
->writeDebugLog('Evaluation Result for cell ', $cellRef, ' is ', $this
->_showTypeDetails($cellValue));
}
}
}
$stack
->push('Value', $cellValue, $cellRef);
}
elseif (preg_match('/^' . self::CALCULATION_REGEXP_FUNCTION . '$/i', $token, $matches)) {
$functionName = $matches[1];
$argCount = $stack
->pop();
$argCount = $argCount['value'];
if ($functionName != 'MKMATRIX') {
$this->_debugLog
->writeDebugLog('Evaluating Function ', self::_localeFunc($functionName), '() with ', $argCount == 0 ? 'no' : $argCount, ' argument', $argCount == 1 ? '' : 's');
}
if (isset(self::$_PHPExcelFunctions[$functionName]) || isset(self::$_controlFunctions[$functionName])) {
if (isset(self::$_PHPExcelFunctions[$functionName])) {
$functionCall = self::$_PHPExcelFunctions[$functionName]['functionCall'];
$passByReference = isset(self::$_PHPExcelFunctions[$functionName]['passByReference']);
$passCellReference = isset(self::$_PHPExcelFunctions[$functionName]['passCellReference']);
}
elseif (isset(self::$_controlFunctions[$functionName])) {
$functionCall = self::$_controlFunctions[$functionName]['functionCall'];
$passByReference = isset(self::$_controlFunctions[$functionName]['passByReference']);
$passCellReference = isset(self::$_controlFunctions[$functionName]['passCellReference']);
}
$args = $argArrayVals = array();
for ($i = 0; $i < $argCount; ++$i) {
$arg = $stack
->pop();
$a = $argCount - $i - 1;
if ($passByReference && isset(self::$_PHPExcelFunctions[$functionName]['passByReference'][$a]) && self::$_PHPExcelFunctions[$functionName]['passByReference'][$a]) {
if ($arg['reference'] === NULL) {
$args[] = $cellID;
if ($functionName != 'MKMATRIX') {
$argArrayVals[] = $this
->_showValue($cellID);
}
}
else {
$args[] = $arg['reference'];
if ($functionName != 'MKMATRIX') {
$argArrayVals[] = $this
->_showValue($arg['reference']);
}
}
}
else {
$args[] = self::_unwrapResult($arg['value']);
if ($functionName != 'MKMATRIX') {
$argArrayVals[] = $this
->_showValue($arg['value']);
}
}
}
krsort($args);
if ($passByReference && $argCount == 0) {
$args[] = $cellID;
$argArrayVals[] = $this
->_showValue($cellID);
}
if ($functionName != 'MKMATRIX') {
if ($this->_debugLog
->getWriteDebugLog()) {
krsort($argArrayVals);
$this->_debugLog
->writeDebugLog('Evaluating ', self::_localeFunc($functionName), '( ', implode(self::$_localeArgumentSeparator . ' ', PHPExcel_Calculation_Functions::flattenArray($argArrayVals)), ' )');
}
}
if ($passCellReference) {
$args[] = $pCell;
}
if (strpos($functionCall, '::') !== FALSE) {
$result = call_user_func_array(explode('::', $functionCall), $args);
}
else {
foreach ($args as &$arg) {
$arg = PHPExcel_Calculation_Functions::flattenSingleValue($arg);
}
unset($arg);
$result = call_user_func_array($functionCall, $args);
}
if ($functionName != 'MKMATRIX') {
$this->_debugLog
->writeDebugLog('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this
->_showTypeDetails($result));
}
$stack
->push('Value', self::_wrapResult($result));
}
}
else {
if (isset(self::$_ExcelConstants[strtoupper($token)])) {
$excelConstant = strtoupper($token);
$stack
->push('Constant Value', self::$_ExcelConstants[$excelConstant]);
$this->_debugLog
->writeDebugLog('Evaluating Constant ', $excelConstant, ' as ', $this
->_showTypeDetails(self::$_ExcelConstants[$excelConstant]));
}
elseif (is_numeric($token) || $token === NULL || is_bool($token) || $token == '' || $token[0] == '"' || $token[0] == '#') {
$stack
->push('Value', $token);
}
elseif (preg_match('/^' . self::CALCULATION_REGEXP_NAMEDRANGE . '$/i', $token, $matches)) {
$namedRange = $matches[6];
$this->_debugLog
->writeDebugLog('Evaluating Named Range ', $namedRange);
$cellValue = $this
->extractNamedRange($namedRange, NULL !== $pCell ? $pCellWorksheet : NULL, FALSE);
$pCell
->attach($pCellParent);
$this->_debugLog
->writeDebugLog('Evaluation Result for named range ', $namedRange, ' is ', $this
->_showTypeDetails($cellValue));
$stack
->push('Named Range', $cellValue, $namedRange);
}
else {
return $this
->_raiseFormulaError("undefined variable '{$token}'");
}
}
}
if ($stack
->count() != 1) {
return $this
->_raiseFormulaError("internal error");
}
$output = $stack
->pop();
$output = $output['value'];
return $output;
}