From ddd43ac727a6ef708b57a64fd1b595c4f994f713 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 1 Feb 2023 19:13:10 +0100 Subject: [PATCH 1/2] Potential resolution for Issue 3355, where the worksheet for a defined name has a quote-prefixed style for default cell A1. I wish `_calculateFormulaValue()` was private; sadly not --- src/PhpSpreadsheet/Calculation/Calculation.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index 6277694ac3..228644b075 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -3696,15 +3696,16 @@ public function saveValueToCache($cellReference, $cellValue): void * @param string $formula The formula to parse and calculate * @param string $cellID The ID (e.g. A3) of the cell that we are calculating * @param Cell $cell Cell to calculate + * @param bool $ignoreQuotePrefix If set to true, evaluate the formyla even if the referenced cell is quote prefixed * * @return mixed */ - public function _calculateFormulaValue($formula, $cellID = null, ?Cell $cell = null) + public function _calculateFormulaValue($formula, $cellID = null, ?Cell $cell = null, bool $ignoreQuotePrefix = false) { $cellValue = null; // Quote-Prefixed cell values cannot be formulae, but are treated as strings - if ($cell !== null && $cell->getStyle()->getQuotePrefix() === true) { + if ($cell !== null && $ignoreQuotePrefix === false && $cell->getStyle()->getQuotePrefix() === true) { return self::wrapResult((string) $formula); } @@ -5720,7 +5721,7 @@ private function evaluateDefinedName(Cell $cell, DefinedName $namedRange, Worksh $recursiveCalculator = new self($this->spreadsheet); $recursiveCalculator->getDebugLog()->setWriteDebugLog($this->getDebugLog()->getWriteDebugLog()); $recursiveCalculator->getDebugLog()->setEchoDebugLog($this->getDebugLog()->getEchoDebugLog()); - $result = $recursiveCalculator->_calculateFormulaValue($definedNameValue, $recursiveCalculationCellAddress, $recursiveCalculationCell); + $result = $recursiveCalculator->_calculateFormulaValue($definedNameValue, $recursiveCalculationCellAddress, $recursiveCalculationCell, true); if ($this->getDebugLog()->getWriteDebugLog()) { $this->debugLog->mergeDebugLog(array_slice($recursiveCalculator->getDebugLog()->getLog(), 3)); From ea3be3b53b7a52f58d8df2a0c1449e10e68ba9f1 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 1 Feb 2023 21:10:19 +0100 Subject: [PATCH 2/2] Unit tests for evaluation of defined name with a quote-prefixed cell --- CHANGELOG.md | 2 +- README.md | 7 +++-- .../Calculation/CalculationTest.php | 2 +- .../DefinedNameWithQuotePrefixedCellTest.php | 28 +++++++++++++++++++ 4 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 tests/PhpSpreadsheetTests/Calculation/DefinedNameWithQuotePrefixedCellTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ef24bfb3e..1a08b56e15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org). ### Fixed -- Nothing +- Calculation Engine doesn't evaluate Defined Name when default cell A1 is quote-prefixed [Issue #3335](https://github.com/PHPOffice/PhpSpreadsheet/issues/3335) [PR #3336](https://github.com/PHPOffice/PhpSpreadsheet/pull/3336) ## 1.27.0 - 2023-01-24 diff --git a/README.md b/README.md index 77b8a3aea6..d9a8073267 100644 --- a/README.md +++ b/README.md @@ -100,16 +100,19 @@ Supporters will receive access to articles about working with PhpSpreadsheet, an Posts already available to Patreon supporters: - The Dating Game - A look at how MS Excel (and PhpSpreadsheet) handle date and time values. +- Looping the Loop + - Advice on Iterating through the rows and cells in a worksheet. The next post (currently being written) will be: - - Looping the Loop - - Advice on Iterating through the cells in a worksheet. + - Behind the Mask + - A look at Number Format Masks. My aim is to post at least one article each month, taking a detailed look at some feature of MS Excel and how to use that feature in PhpSpreadsheet, or on how to perform different activities in PhpSpreadsheet. Planned posts for the future include topics like: - Tables - Structured References + - AutoFiltering - Array Formulae - Conditional Formatting - Data Validation diff --git a/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php b/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php index 5aaf7a615e..c9d1d374bf 100644 --- a/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php @@ -369,7 +369,7 @@ public function testBranchPruningFormulaParsingInequalitiesConditionsCase(): voi * * @dataProvider dataProviderBranchPruningFullExecution */ - public function testFullExecution( + public function testFullExecutionDataPruning( $expectedResult, $dataArray, $formula, diff --git a/tests/PhpSpreadsheetTests/Calculation/DefinedNameWithQuotePrefixedCellTest.php b/tests/PhpSpreadsheetTests/Calculation/DefinedNameWithQuotePrefixedCellTest.php new file mode 100644 index 0000000000..0c2511640e --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/DefinedNameWithQuotePrefixedCellTest.php @@ -0,0 +1,28 @@ +getActiveSheet(); + $sheet1->setTitle('Sheet1'); + $sheet2 = $spreadsheet->createSheet(); + $sheet2->setTitle('Sheet2'); + $sheet2->getCell('A1')->setValue('July 2019'); + $sheet2->getStyle('A1') + ->setQuotePrefix(true); + $sheet2->getCell('A2')->setValue(3); + $spreadsheet->addNamedRange(new NamedRange('FM', $sheet2, '$A$2')); + $sheet1->getCell('A1')->setValue('=(A2+FM)'); + $sheet1->getCell('A2')->setValue(38.42); + + self::assertSame(41.42, $sheet1->getCell('A1')->getCalculatedValue()); + } +}