Skip to content

Commit

Permalink
Adjust calc engine identification of quoted worksheet names to fix bu…
Browse files Browse the repository at this point in the history
…g with multiple quoted worksheets in formula
  • Loading branch information
MarkBaker committed Jun 17, 2022
1 parent adf4531 commit 80e8994
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 7 deletions.
10 changes: 5 additions & 5 deletions src/PhpSpreadsheet/Calculation/Calculation.php
Expand Up @@ -33,17 +33,17 @@ class Calculation
// Function (allow for the old @ symbol that could be used to prefix a function, but we'll ignore it)
const CALCULATION_REGEXP_FUNCTION = '@?(?:_xlfn\.)?([\p{L}][\p{L}\p{N}\.]*)[\s]*\(';
// Cell reference (cell or range of cells, with or without a sheet reference)
const CALCULATION_REGEXP_CELLREF = '((([^\s,!&%^\/\*\+<>=:`-]*)|(\'(?:[^\']|\'\')+?\')|(\"(?:[^\"]|\"\")+?\"))!)?\$?\b([a-z]{1,3})\$?(\d{1,7})(?![\w.])';
const CALCULATION_REGEXP_CELLREF = '((([^\s,!&%^\/\*\+<>=:`-]*)|(\'(?:[^\']|\'[^!])+?\')|(\"(?:[^\"]|\"[^!])+?\"))!)?\$?\b([a-z]{1,3})\$?(\d{1,7})(?![\w.])';
// Cell reference (with or without a sheet reference) ensuring absolute/relative
const CALCULATION_REGEXP_CELLREF_RELATIVE = '((([^\s\(,!&%^\/\*\+<>=:`-]*)|(\'(?:[^\']|\'\')+?\')|(\"(?:[^\"]|\"\")+?\"))!)?(\$?\b[a-z]{1,3})(\$?\d{1,7})(?![\w.])';
const CALCULATION_REGEXP_COLUMN_RANGE = '(((([^\s\(,!&%^\/\*\+<>=:`-]*)|(\'(?:[^\']|\'\')+?\')|(\".(?:[^\"]|\"\")?\"))!)?(\$?[a-z]{1,3})):(?![.*])';
const CALCULATION_REGEXP_ROW_RANGE = '(((([^\s\(,!&%^\/\*\+<>=:`-]*)|(\'(?:[^\']|\'\')+?\')|(\"(?:[^\"]|\"\")+?\"))!)?(\$?[1-9][0-9]{0,6})):(?![.*])';
const CALCULATION_REGEXP_CELLREF_RELATIVE = '((([^\s\(,!&%^\/\*\+<>=:`-]*)|(\'(?:[^\']|\'[^!])+?\')|(\"(?:[^\"]|\"[^!])+?\"))!)?(\$?\b[a-z]{1,3})(\$?\d{1,7})(?![\w.])';
const CALCULATION_REGEXP_COLUMN_RANGE = '(((([^\s\(,!&%^\/\*\+<>=:`-]*)|(\'(?:[^\']|\'[^!])+?\')|(\".(?:[^\"]|\"[^!])?\"))!)?(\$?[a-z]{1,3})):(?![.*])';
const CALCULATION_REGEXP_ROW_RANGE = '(((([^\s\(,!&%^\/\*\+<>=:`-]*)|(\'(?:[^\']|\'[^!])+?\')|(\"(?:[^\"]|\"[^!])+?\"))!)?(\$?[1-9][0-9]{0,6})):(?![.*])';
// Cell reference (with or without a sheet reference) ensuring absolute/relative
// Cell ranges ensuring absolute/relative
const CALCULATION_REGEXP_COLUMNRANGE_RELATIVE = '(\$?[a-z]{1,3}):(\$?[a-z]{1,3})';
const CALCULATION_REGEXP_ROWRANGE_RELATIVE = '(\$?\d{1,7}):(\$?\d{1,7})';
// Defined Names: Named Range of cells, or Named Formulae
const CALCULATION_REGEXP_DEFINEDNAME = '((([^\s,!&%^\/\*\+<>=-]*)|(\'(?:[^\']|\'\')+?\')|(\"(?:[^\"]|\"\")+?\"))!)?([_\p{L}][_\p{L}\p{N}\.]*)';
const CALCULATION_REGEXP_DEFINEDNAME = '((([^\s,!&%^\/\*\+<>=-]*)|(\'(?:[^\']|\'[^!])+?\')|(\"(?:[^\"]|\"[^!])+?\"))!)?([_\p{L}][_\p{L}\p{N}\.]*)';
// Error
const CALCULATION_REGEXP_ERROR = '\#[A-Z][A-Z0_\/]*[!\?]?';

Expand Down
52 changes: 50 additions & 2 deletions tests/PhpSpreadsheetTests/Calculation/ParseFormulaTest.php
Expand Up @@ -170,10 +170,34 @@ public function providerBinaryOperations(): array
['type' => 'Operand Count for Function MIN()', 'value' => 1, 'reference' => null],
['type' => 'Function', 'value' => 'MIN(', 'reference' => null],
['type' => 'Cell Reference', 'value' => "'sheet1'!A1", 'reference' => "'sheet1'!A1"],
['type' => 'Binary Operator', 'value' => '+','reference' => null],
['type' => 'Binary Operator', 'value' => '+', 'reference' => null],
],
"=MIN('sheet1'!A:A) + 'sheet1'!A1",
],
'Combined Cell Reference and Column Range with quote' => [
[
['type' => 'Column Reference', 'value' => "'sheet1'!A1", 'reference' => "'Mark''s sheet1'!A1"],
['type' => 'Column Reference', 'value' => "'sheet1'!A1048576", 'reference' => "'Mark''s sheet1'!A1048576"],
['type' => 'Binary Operator', 'value' => ':', 'reference' => null],
['type' => 'Operand Count for Function MIN()', 'value' => 1, 'reference' => null],
['type' => 'Function', 'value' => 'MIN(', 'reference' => null],
['type' => 'Cell Reference', 'value' => "'sheet1'!A1", 'reference' => "'Mark''s sheet1'!A1"],
['type' => 'Binary Operator', 'value' => '+', 'reference' => null],
],
"=MIN('Mark''s sheet1'!A:A) + 'Mark''s sheet1'!A1",
],
'Combined Cell Reference and Column Range with unescaped quote' => [
[
['type' => 'Column Reference', 'value' => "'sheet1'!A1", 'reference' => "'Mark's sheet1'!A1"],
['type' => 'Column Reference', 'value' => "'sheet1'!A1048576", 'reference' => "'Mark's sheet1'!A1048576"],
['type' => 'Binary Operator', 'value' => ':', 'reference' => null],
['type' => 'Operand Count for Function MIN()', 'value' => 1, 'reference' => null],
['type' => 'Function', 'value' => 'MIN(', 'reference' => null],
['type' => 'Cell Reference', 'value' => "'sheet1'!A1", 'reference' => "'Mark's sheet1'!A1"],
['type' => 'Binary Operator', 'value' => '+', 'reference' => null],
],
"=MIN('Mark's sheet1'!A:A) + 'Mark's sheet1'!A1",
],
'Combined Column Range and Cell Reference' => [
[
['type' => 'Cell Reference', 'value' => "'sheet1'!A1", 'reference' => "'sheet1'!A1"],
Expand All @@ -182,10 +206,34 @@ public function providerBinaryOperations(): array
['type' => 'Binary Operator', 'value' => ':', 'reference' => null],
['type' => 'Operand Count for Function MIN()', 'value' => 1, 'reference' => null],
['type' => 'Function', 'value' => 'MIN(', 'reference' => null],
['type' => 'Binary Operator', 'value' => '+','reference' => null],
['type' => 'Binary Operator', 'value' => '+', 'reference' => null],
],
"='sheet1'!A1 + MIN('sheet1'!A:A)",
],
'Combined Column Range and Cell Reference with quote' => [
[
['type' => 'Cell Reference', 'value' => "'sheet1'!A1", 'reference' => "'Mark''s sheet1'!A1"],
['type' => 'Column Reference', 'value' => "'sheet1'!A1", 'reference' => "'Mark''s sheet1'!A1"],
['type' => 'Column Reference', 'value' => "'sheet1'!A1048576", 'reference' => "'Mark''s sheet1'!A1048576"],
['type' => 'Binary Operator', 'value' => ':', 'reference' => null],
['type' => 'Operand Count for Function MIN()', 'value' => 1, 'reference' => null],
['type' => 'Function', 'value' => 'MIN(', 'reference' => null],
['type' => 'Binary Operator', 'value' => '+', 'reference' => null],
],
"='Mark''s sheet1'!A1 + MIN('Mark''s sheet1'!A:A)",
],
'Combined Column Range and Cell Reference with unescaped quote' => [
[
['type' => 'Cell Reference', 'value' => "'sheet1'!A1", 'reference' => "'Mark's sheet1'!A1"],
['type' => 'Column Reference', 'value' => "'sheet1'!A1", 'reference' => "'Mark's sheet1'!A1"],
['type' => 'Column Reference', 'value' => "'sheet1'!A1048576", 'reference' => "'Mark's sheet1'!A1048576"],
['type' => 'Binary Operator', 'value' => ':', 'reference' => null],
['type' => 'Operand Count for Function MIN()', 'value' => 1, 'reference' => null],
['type' => 'Function', 'value' => 'MIN(', 'reference' => null],
['type' => 'Binary Operator', 'value' => '+', 'reference' => null],
],
"='Mark's sheet1'!A1 + MIN('Mark's sheet1'!A:A)",
],
'Range with Defined Names' => [
[
['type' => 'Defined Name', 'value' => 'GROUP1', 'reference' => 'GROUP1'],
Expand Down

0 comments on commit 80e8994

Please sign in to comment.