From 8b2bba9bdb6ca5969730462626d7866bac4bb00c Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Fri, 29 May 2020 21:53:28 +0200 Subject: [PATCH] Range operator tests (#1498) * Fix intersection operator when working with named ranges --- .../Calculation/Calculation.php | 10 ++-- .../Calculation/Engine/RangeTest.php | 53 ++++++++++++++++++- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index cdfe7b53..5aa309c5 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -3456,10 +3456,8 @@ class Calculation if ((isset(self::$comparisonOperators[$opCharacter])) && (strlen($formula) > $index) && (isset(self::$comparisonOperators[$formula[$index + 1]]))) { $opCharacter .= $formula[++$index]; } - // Find out if we're currently at the beginning of a number, variable, cell reference, function, parenthesis or operand $isOperandOrFunction = preg_match($regexpMatchString, substr($formula, $index), $match); - if ($opCharacter == '-' && !$expectingOperator) { // Is it a negation instead of a minus? // Put a negation on the stack $stack->push('Unary Operator', '~', null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot); @@ -3776,8 +3774,12 @@ class Calculation } // If we're expecting an operator, but only have a space between the previous and next operands (and both are // Cell References) then we have an INTERSECTION operator - if (($expectingOperator) && (preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '.*/Ui', substr($formula, $index), $match)) && - ($output[count($output) - 1]['type'] == 'Cell Reference')) { + if (($expectingOperator) && + ((preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '.*/Ui', substr($formula, $index), $match)) && + ($output[count($output) - 1]['type'] == 'Cell Reference') || + (preg_match('/^' . self::CALCULATION_REGEXP_NAMEDRANGE . '.*/Ui', substr($formula, $index), $match)) && + ($output[count($output) - 1]['type'] == 'Named Range' || $output[count($output) - 1]['type'] == 'Value') + )) { while ($stack->count() > 0 && ($o2 = $stack->last()) && isset(self::$operators[$o2['value']]) && diff --git a/tests/PhpSpreadsheetTests/Calculation/Engine/RangeTest.php b/tests/PhpSpreadsheetTests/Calculation/Engine/RangeTest.php index 84cac747..d1ad229b 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Engine/RangeTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Engine/RangeTest.php @@ -3,6 +3,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Engine; use PhpOffice\PhpSpreadsheet\Calculation\Functions; +use PhpOffice\PhpSpreadsheet\NamedRange; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PHPUnit\Framework\TestCase; @@ -28,7 +29,7 @@ class RangeTest extends TestCase /** * @dataProvider providerRangeEvaluation * - * @param mixed $formula + * @param string $formula * @param int $expectedResult */ public function testRangeEvaluation($formula, $expectedResult): void @@ -51,4 +52,54 @@ class RangeTest extends TestCase ['=SUM(A1:B2 B2:C3)', 5], ]; } + + /** + * @dataProvider providerNamedRangeEvaluation + * + * @param string $group1 + * @param string $group2 + * @param string $formula + * @param int $expectedResult + */ + public function testNamedRangeEvaluation($group1, $group2, $formula, $expectedResult): void + { + $workSheet = $this->spreadSheet->getActiveSheet(); + $this->spreadSheet->addNamedRange(new NamedRange('GROUP1', $workSheet, $group1)); + $this->spreadSheet->addNamedRange(new NamedRange('GROUP2', $workSheet, $group2)); + + $workSheet->setCellValue('E1', $formula); + + $actualRresult = $workSheet->getCell('E1')->getCalculatedValue(); + self::assertSame($expectedResult, $actualRresult); + } + + public function providerNamedRangeEvaluation() + { + return[ + [ + 'A1:B3', + 'A1:C2', + '=SUM(GROUP1,GROUP2)', + 48, + ], + [ + 'A1:B3', + 'A1:C2', + '=SUM(GROUP1 GROUP2)', + 12, + ], + [ + 'A1:B2', + 'B2:C3', + '=SUM(GROUP1,GROUP2)', + 40, + ], + [ + 'A1:B2', + 'B2:C3', + '=SUM(GROUP1 GROUP2)', + 5, + ], + ]; + } }