private function PHPExcel_Calculation::_parseFormula in Loft Data Grids 7.2
Same name and namespace in other branches
- 6.2 vendor/phpoffice/phpexcel/Classes/PHPExcel/Calculation.php \PHPExcel_Calculation::_parseFormula()
2 calls to PHPExcel_Calculation::_parseFormula()
- PHPExcel_Calculation::parseFormula in vendor/phpoffice/phpexcel/Classes/PHPExcel/Calculation.php
- * Validate and parse a formula string
*
*
- 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 2740
Class
- PHPExcel_Calculation
- PHPExcel_Calculation (Multiton)
Code
private function _parseFormula($formula, PHPExcel_Cell $pCell = NULL) {
if (($formula = $this
->_convertMatrixReferences(trim($formula))) === FALSE) {
return FALSE;
}
$pCellParent = $pCell !== NULL ? $pCell
->getWorksheet() : NULL;
$regexpMatchString = '/^(' . self::CALCULATION_REGEXP_FUNCTION . '|' . self::CALCULATION_REGEXP_CELLREF . '|' . self::CALCULATION_REGEXP_NUMBER . '|' . self::CALCULATION_REGEXP_STRING . '|' . self::CALCULATION_REGEXP_OPENBRACE . '|' . self::CALCULATION_REGEXP_NAMEDRANGE . '|' . self::CALCULATION_REGEXP_ERROR . ')/si';
$index = 0;
$stack = new PHPExcel_Calculation_Token_Stack();
$output = array();
$expectingOperator = FALSE;
$expectingOperand = FALSE;
while (TRUE) {
$opCharacter = $formula[$index];
if (isset(self::$_comparisonOperators[$opCharacter]) && strlen($formula) > $index && isset(self::$_comparisonOperators[$formula[$index + 1]])) {
$opCharacter .= $formula[++$index];
}
$isOperandOrFunction = preg_match($regexpMatchString, substr($formula, $index), $match);
if ($opCharacter == '-' && !$expectingOperator) {
$stack
->push('Unary Operator', '~');
++$index;
}
elseif ($opCharacter == '%' && $expectingOperator) {
$stack
->push('Unary Operator', '%');
++$index;
}
elseif ($opCharacter == '+' && !$expectingOperator) {
++$index;
}
elseif (($opCharacter == '~' || $opCharacter == '|') && !$isOperandOrFunction) {
return $this
->_raiseFormulaError("Formula Error: Illegal character '~'");
}
elseif ((isset(self::$_operators[$opCharacter]) or $isOperandOrFunction) && $expectingOperator) {
while ($stack
->count() > 0 && ($o2 = $stack
->last()) && isset(self::$_operators[$o2['value']]) && @(self::$_operatorAssociativity[$opCharacter] ? self::$_operatorPrecedence[$opCharacter] < self::$_operatorPrecedence[$o2['value']] : self::$_operatorPrecedence[$opCharacter] <= self::$_operatorPrecedence[$o2['value']])) {
$output[] = $stack
->pop();
}
$stack
->push('Binary Operator', $opCharacter);
++$index;
$expectingOperator = FALSE;
}
elseif ($opCharacter == ')' && $expectingOperator) {
$expectingOperand = FALSE;
while (($o2 = $stack
->pop()) && $o2['value'] != '(') {
if ($o2 === NULL) {
return $this
->_raiseFormulaError('Formula Error: Unexpected closing brace ")"');
}
else {
$output[] = $o2;
}
}
$d = $stack
->last(2);
if (preg_match('/^' . self::CALCULATION_REGEXP_FUNCTION . '$/i', $d['value'], $matches)) {
$functionName = $matches[1];
$d = $stack
->pop();
$argumentCount = $d['value'];
$output[] = $d;
$output[] = $stack
->pop();
if (isset(self::$_controlFunctions[$functionName])) {
$expectedArgumentCount = self::$_controlFunctions[$functionName]['argumentCount'];
$functionCall = self::$_controlFunctions[$functionName]['functionCall'];
}
elseif (isset(self::$_PHPExcelFunctions[$functionName])) {
$expectedArgumentCount = self::$_PHPExcelFunctions[$functionName]['argumentCount'];
$functionCall = self::$_PHPExcelFunctions[$functionName]['functionCall'];
}
else {
return $this
->_raiseFormulaError("Formula Error: Internal error, non-function on stack");
}
$argumentCountError = FALSE;
if (is_numeric($expectedArgumentCount)) {
if ($expectedArgumentCount < 0) {
if ($argumentCount > abs($expectedArgumentCount)) {
$argumentCountError = TRUE;
$expectedArgumentCountString = 'no more than ' . abs($expectedArgumentCount);
}
}
else {
if ($argumentCount != $expectedArgumentCount) {
$argumentCountError = TRUE;
$expectedArgumentCountString = $expectedArgumentCount;
}
}
}
elseif ($expectedArgumentCount != '*') {
$isOperandOrFunction = preg_match('/(\\d*)([-+,])(\\d*)/', $expectedArgumentCount, $argMatch);
switch ($argMatch[2]) {
case '+':
if ($argumentCount < $argMatch[1]) {
$argumentCountError = TRUE;
$expectedArgumentCountString = $argMatch[1] . ' or more ';
}
break;
case '-':
if ($argumentCount < $argMatch[1] || $argumentCount > $argMatch[3]) {
$argumentCountError = TRUE;
$expectedArgumentCountString = 'between ' . $argMatch[1] . ' and ' . $argMatch[3];
}
break;
case ',':
if ($argumentCount != $argMatch[1] && $argumentCount != $argMatch[3]) {
$argumentCountError = TRUE;
$expectedArgumentCountString = 'either ' . $argMatch[1] . ' or ' . $argMatch[3];
}
break;
}
}
if ($argumentCountError) {
return $this
->_raiseFormulaError("Formula Error: Wrong number of arguments for {$functionName}() function: {$argumentCount} given, " . $expectedArgumentCountString . " expected");
}
}
++$index;
}
elseif ($opCharacter == ',') {
while (($o2 = $stack
->pop()) && $o2['value'] != '(') {
if ($o2 === NULL) {
return $this
->_raiseFormulaError("Formula Error: Unexpected ,");
}
else {
$output[] = $o2;
}
}
if ($expectingOperand || !$expectingOperator) {
$output[] = array(
'type' => 'NULL Value',
'value' => self::$_ExcelConstants['NULL'],
'reference' => NULL,
);
}
$d = $stack
->last(2);
if (!preg_match('/^' . self::CALCULATION_REGEXP_FUNCTION . '$/i', $d['value'], $matches)) {
return $this
->_raiseFormulaError("Formula Error: Unexpected ,");
}
$d = $stack
->pop();
$stack
->push($d['type'], ++$d['value'], $d['reference']);
$stack
->push('Brace', '(');
$expectingOperator = FALSE;
$expectingOperand = TRUE;
++$index;
}
elseif ($opCharacter == '(' && !$expectingOperator) {
$stack
->push('Brace', '(');
++$index;
}
elseif ($isOperandOrFunction && !$expectingOperator) {
$expectingOperator = TRUE;
$expectingOperand = FALSE;
$val = $match[1];
$length = strlen($val);
if (preg_match('/^' . self::CALCULATION_REGEXP_FUNCTION . '$/i', $val, $matches)) {
$val = preg_replace('/\\s/u', '', $val);
if (isset(self::$_PHPExcelFunctions[strtoupper($matches[1])]) || isset(self::$_controlFunctions[strtoupper($matches[1])])) {
$stack
->push('Function', strtoupper($val));
$ax = preg_match('/^\\s*(\\s*\\))/ui', substr($formula, $index + $length), $amatch);
if ($ax) {
$stack
->push('Operand Count for Function ' . strtoupper($val) . ')', 0);
$expectingOperator = TRUE;
}
else {
$stack
->push('Operand Count for Function ' . strtoupper($val) . ')', 1);
$expectingOperator = FALSE;
}
$stack
->push('Brace', '(');
}
else {
$output[] = array(
'type' => 'Value',
'value' => $matches[1],
'reference' => NULL,
);
}
}
elseif (preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '$/i', $val, $matches)) {
$testPrevOp = $stack
->last(1);
if ($testPrevOp['value'] == ':') {
if ($matches[2] == '') {
$startCellRef = $output[count($output) - 1]['value'];
preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '$/i', $startCellRef, $startMatches);
if ($startMatches[2] > '') {
$val = $startMatches[2] . '!' . $val;
}
}
else {
return $this
->_raiseFormulaError("3D Range references are not yet supported");
}
}
$output[] = array(
'type' => 'Cell Reference',
'value' => $val,
'reference' => $val,
);
}
else {
$testPrevOp = $stack
->last(1);
if ($testPrevOp['value'] == ':') {
$startRowColRef = $output[count($output) - 1]['value'];
$rangeWS1 = '';
if (strpos('!', $startRowColRef) !== FALSE) {
list($rangeWS1, $startRowColRef) = explode('!', $startRowColRef);
}
if ($rangeWS1 != '') {
$rangeWS1 .= '!';
}
$rangeWS2 = $rangeWS1;
if (strpos('!', $val) !== FALSE) {
list($rangeWS2, $val) = explode('!', $val);
}
if ($rangeWS2 != '') {
$rangeWS2 .= '!';
}
if (is_integer($startRowColRef) && ctype_digit($val) && $startRowColRef <= 1048576 && $val <= 1048576) {
$endRowColRef = $pCellParent !== NULL ? $pCellParent
->getHighestColumn() : 'XFD';
$output[count($output) - 1]['value'] = $rangeWS1 . 'A' . $startRowColRef;
$val = $rangeWS2 . $endRowColRef . $val;
}
elseif (ctype_alpha($startRowColRef) && ctype_alpha($val) && strlen($startRowColRef) <= 3 && strlen($val) <= 3) {
$endRowColRef = $pCellParent !== NULL ? $pCellParent
->getHighestRow() : 1048576;
$output[count($output) - 1]['value'] = $rangeWS1 . strtoupper($startRowColRef) . '1';
$val = $rangeWS2 . $val . $endRowColRef;
}
}
$localeConstant = FALSE;
if ($opCharacter == '"') {
$val = self::_wrapResult(str_replace('""', '"', self::_unwrapResult($val)));
}
elseif (is_numeric($val)) {
if (strpos($val, '.') !== FALSE || stripos($val, 'e') !== FALSE || $val > PHP_INT_MAX || $val < -PHP_INT_MAX) {
$val = (double) $val;
}
else {
$val = (int) $val;
}
}
elseif (isset(self::$_ExcelConstants[trim(strtoupper($val))])) {
$excelConstant = trim(strtoupper($val));
$val = self::$_ExcelConstants[$excelConstant];
}
elseif (($localeConstant = array_search(trim(strtoupper($val)), self::$_localeBoolean)) !== FALSE) {
$val = self::$_ExcelConstants[$localeConstant];
}
$details = array(
'type' => 'Value',
'value' => $val,
'reference' => NULL,
);
if ($localeConstant) {
$details['localeValue'] = $localeConstant;
}
$output[] = $details;
}
$index += $length;
}
elseif ($opCharacter == '$') {
++$index;
}
elseif ($opCharacter == ')') {
if ($expectingOperand) {
$output[] = array(
'type' => 'NULL Value',
'value' => self::$_ExcelConstants['NULL'],
'reference' => NULL,
);
$expectingOperand = FALSE;
$expectingOperator = TRUE;
}
else {
return $this
->_raiseFormulaError("Formula Error: Unexpected ')'");
}
}
elseif (isset(self::$_operators[$opCharacter]) && !$expectingOperator) {
return $this
->_raiseFormulaError("Formula Error: Unexpected operator '{$opCharacter}'");
}
else {
return $this
->_raiseFormulaError("Formula Error: An unexpected error occured");
}
if ($index == strlen($formula)) {
if (isset(self::$_operators[$opCharacter]) && $opCharacter != '%') {
return $this
->_raiseFormulaError("Formula Error: Operator '{$opCharacter}' has no operands");
}
else {
break;
}
}
while ($formula[$index] == "\n" || $formula[$index] == "\r") {
++$index;
}
if ($formula[$index] == ' ') {
while ($formula[$index] == ' ') {
++$index;
}
if ($expectingOperator && preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '.*/Ui', substr($formula, $index), $match) && $output[count($output) - 1]['type'] == 'Cell Reference') {
while ($stack
->count() > 0 && ($o2 = $stack
->last()) && isset(self::$_operators[$o2['value']]) && @(self::$_operatorAssociativity[$opCharacter] ? self::$_operatorPrecedence[$opCharacter] < self::$_operatorPrecedence[$o2['value']] : self::$_operatorPrecedence[$opCharacter] <= self::$_operatorPrecedence[$o2['value']])) {
$output[] = $stack
->pop();
}
$stack
->push('Binary Operator', '|');
$expectingOperator = FALSE;
}
}
}
while (($op = $stack
->pop()) !== NULL) {
if (is_array($op) && $op['value'] == '(' || $op === '(') {
return $this
->_raiseFormulaError("Formula Error: Expecting ')'");
}
$output[] = $op;
}
return $output;
}