Merge pull request #2751 from PHPOffice/CalcEngine-Bugfix-Row-Column-Ranges
Resolve Calculation Engine bug with row and column ranges being identified as named ranges
This commit is contained in:
commit
de173d4705
|
|
@ -4178,7 +4178,10 @@ class Calculation
|
|||
$testPrevOp = $stack->last(1);
|
||||
if ($testPrevOp !== null && $testPrevOp['value'] === ':') {
|
||||
$stackItemType = 'Cell Reference';
|
||||
|
||||
if (
|
||||
!is_numeric($val) &&
|
||||
((ctype_alpha($val) === false || strlen($val) > 3)) &&
|
||||
(preg_match('/^' . self::CALCULATION_REGEXP_DEFINEDNAME . '$/mui', $val) !== false) &&
|
||||
($this->spreadsheet->getNamedRange($val) !== null)
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
namespace PhpOffice\PhpSpreadsheetTests\Calculation;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\NamedRange;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ParseFormulaTest extends TestCase
|
||||
|
|
@ -12,7 +14,11 @@ class ParseFormulaTest extends TestCase
|
|||
*/
|
||||
public function testParseOperations(array $expectedStack, string $formula): void
|
||||
{
|
||||
$parser = Calculation::getInstance();
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$spreadsheet->addNamedRange(new NamedRange('GROUP1', $spreadsheet->getActiveSheet(), 'B2:D4'));
|
||||
$spreadsheet->addNamedRange(new NamedRange('GROUP2', $spreadsheet->getActiveSheet(), 'D4:F6'));
|
||||
|
||||
$parser = Calculation::getInstance($spreadsheet);
|
||||
$stack = $parser->parseFormula($formula);
|
||||
self::assertSame($expectedStack, $stack);
|
||||
}
|
||||
|
|
@ -80,6 +86,36 @@ class ParseFormulaTest extends TestCase
|
|||
],
|
||||
'=-DEFINED_NAME%',
|
||||
],
|
||||
'Integer Numbers with Operator' => [
|
||||
[
|
||||
['type' => 'Value', 'value' => 2, 'reference' => null],
|
||||
['type' => 'Value', 'value' => 3, 'reference' => null],
|
||||
['type' => 'Binary Operator', 'value' => '*', 'reference' => null],
|
||||
],
|
||||
'=2*3',
|
||||
],
|
||||
'Float Numbers with Operator' => [
|
||||
[
|
||||
['type' => 'Value', 'value' => 2.5, 'reference' => null],
|
||||
['type' => 'Value', 'value' => 3.5, 'reference' => null],
|
||||
['type' => 'Binary Operator', 'value' => '*', 'reference' => null],
|
||||
],
|
||||
'=2.5*3.5',
|
||||
],
|
||||
'Strings with Operator' => [
|
||||
[
|
||||
['type' => 'Value', 'value' => '"HELLO"', 'reference' => null],
|
||||
['type' => 'Value', 'value' => '"WORLD"', 'reference' => null],
|
||||
['type' => 'Binary Operator', 'value' => '&', 'reference' => null],
|
||||
],
|
||||
'="HELLO"&"WORLD"',
|
||||
],
|
||||
'Error' => [
|
||||
[
|
||||
['type' => 'Value', 'value' => '#DIV0!', 'reference' => null],
|
||||
],
|
||||
'=#DIV0!',
|
||||
],
|
||||
'Cell Range' => [
|
||||
[
|
||||
['type' => 'Cell Reference', 'value' => 'A1', 'reference' => 'A1'],
|
||||
|
|
@ -88,6 +124,16 @@ class ParseFormulaTest extends TestCase
|
|||
],
|
||||
'=A1:C3',
|
||||
],
|
||||
'Chained Cell Range' => [
|
||||
[
|
||||
['type' => 'Cell Reference', 'value' => 'A1', 'reference' => 'A1'],
|
||||
['type' => 'Cell Reference', 'value' => 'C3', 'reference' => 'C3'],
|
||||
['type' => 'Binary Operator', 'value' => ':', 'reference' => null],
|
||||
['type' => 'Cell Reference', 'value' => 'E5', 'reference' => 'E5'],
|
||||
['type' => 'Binary Operator', 'value' => ':', 'reference' => null],
|
||||
],
|
||||
'=A1:C3:E5',
|
||||
],
|
||||
'Cell Range Intersection' => [
|
||||
[
|
||||
['type' => 'Cell Reference', 'value' => 'A1', 'reference' => 'A1'],
|
||||
|
|
@ -100,6 +146,40 @@ class ParseFormulaTest extends TestCase
|
|||
],
|
||||
'=A1:C3 B2:D4',
|
||||
],
|
||||
'Row Range' => [
|
||||
[
|
||||
['type' => 'Row Reference', 'value' => 'A2', 'reference' => 'A2'],
|
||||
['type' => 'Row Reference', 'value' => 'XFD3', 'reference' => 'XFD3'],
|
||||
['type' => 'Binary Operator', 'value' => ':', 'reference' => null],
|
||||
],
|
||||
'=2:3',
|
||||
],
|
||||
'Column Range' => [
|
||||
[
|
||||
['type' => 'Column Reference', 'value' => 'B1', 'reference' => 'B1'],
|
||||
['type' => 'Column Reference', 'value' => 'C1048576', 'reference' => 'C1048576'],
|
||||
['type' => 'Binary Operator', 'value' => ':', 'reference' => null],
|
||||
],
|
||||
'=B:C',
|
||||
],
|
||||
'Range with Defined Names' => [
|
||||
[
|
||||
['type' => 'Defined Name', 'value' => 'GROUP1', 'reference' => 'GROUP1'],
|
||||
['type' => 'Defined Name', 'value' => 'D4', 'reference' => 'GROUP2'],
|
||||
['type' => 'Binary Operator', 'value' => ':', 'reference' => null],
|
||||
['type' => 'Defined Name', 'value' => 'F6', 'reference' => 'GROUP2'],
|
||||
['type' => 'Binary Operator', 'value' => ':', 'reference' => null],
|
||||
],
|
||||
'=GROUP1:GROUP2',
|
||||
],
|
||||
'Named Range with Binary Operator' => [
|
||||
[
|
||||
['type' => 'Defined Name', 'value' => 'DEFINED_NAME_1', 'reference' => 'DEFINED_NAME_1'],
|
||||
['type' => 'Defined Name', 'value' => 'DEFINED_NAME_2', 'reference' => 'DEFINED_NAME_2'],
|
||||
['type' => 'Binary Operator', 'value' => '/', 'reference' => null],
|
||||
],
|
||||
'=DEFINED_NAME_1/DEFINED_NAME_2',
|
||||
],
|
||||
'Named Range Intersection' => [
|
||||
[
|
||||
['type' => 'Defined Name', 'value' => 'DEFINED_NAME_1', 'reference' => 'DEFINED_NAME_1'],
|
||||
|
|
@ -108,6 +188,22 @@ class ParseFormulaTest extends TestCase
|
|||
],
|
||||
'=DEFINED_NAME_1 DEFINED_NAME_2',
|
||||
],
|
||||
// 'Structured Reference Arithmetic' => [
|
||||
// [
|
||||
// ['type' => 'Structured Reference', 'value' => '[@Quantity]', 'reference' => null],
|
||||
// ['type' => 'Structured Reference', 'value' => '[@[Unit Price]]', 'reference' => null],
|
||||
// ['type' => 'Binary Operator', 'value' => '*', 'reference' => null],
|
||||
// ],
|
||||
// '=[@Quantity]*[@[Unit Price]]',
|
||||
// ],
|
||||
// 'Structured Reference Intersection' => [
|
||||
// [
|
||||
// ['type' => 'Structured Reference', 'value' => 'DeptSales[[Sales Person]:[Sales Amount]]', 'reference' => null],
|
||||
// ['type' => 'Structured Reference', 'value' => 'DeptSales[[Region]:[% Commission]]', 'reference' => null],
|
||||
// ['type' => 'Binary Operator', 'value' => '∩', 'reference' => null],
|
||||
// ],
|
||||
// '=DeptSales[[Sales Person]:[Sales Amount]] DeptSales[[Region]:[% Commission]]',
|
||||
// ],
|
||||
// 'Cell Range Union' => [
|
||||
// [
|
||||
// ['type' => 'Cell Reference', 'value' => 'A1', 'reference' => 'A1'],
|
||||
|
|
|
|||
Loading…
Reference in New Issue