From d682f2f95e2c1b9a6c663a8fb2a64fe6ea35e257 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Fri, 23 Sep 2022 14:03:38 +0200 Subject: [PATCH] Correct update to named ranges and formulae when inserting/deleting columns/rows --- CHANGELOG.md | 1 + src/PhpSpreadsheet/DefinedName.php | 2 +- src/PhpSpreadsheet/ReferenceHelper.php | 64 +++++++++++++--------- src/PhpSpreadsheet/Worksheet/Worksheet.php | 2 +- 4 files changed, 40 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 225ea2af..0f731ba4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ and this project adheres to [Semantic Versioning](https://semver.org). ### Fixed +- Fix update to defined names when inserting/deleting rows/columns [Issue #3076](https://github.com/PHPOffice/PhpSpreadsheet/issues/3076) [PR #3077](https://github.com/PHPOffice/PhpSpreadsheet/pull/3077) - Fix DataValidation sqRef when inserting/deleting rows/columns [Issue #3056](https://github.com/PHPOffice/PhpSpreadsheet/issues/3056) [PR #3074](https://github.com/PHPOffice/PhpSpreadsheet/pull/3074) - Named ranges not usable as anchors in OFFSET function [Issue #3013](https://github.com/PHPOffice/PhpSpreadsheet/issues/3013) - Fully flatten an array [Issue #2955](https://github.com/PHPOffice/PhpSpreadsheet/issues/2955) [PR #2956](https://github.com/PHPOffice/PhpSpreadsheet/pull/2956) diff --git a/src/PhpSpreadsheet/DefinedName.php b/src/PhpSpreadsheet/DefinedName.php index 3b874b43..464fa8e3 100644 --- a/src/PhpSpreadsheet/DefinedName.php +++ b/src/PhpSpreadsheet/DefinedName.php @@ -150,7 +150,7 @@ abstract class DefinedName // New title $newTitle = $this->name; - ReferenceHelper::getInstance()->updateNamedFormulas($this->worksheet->getParent(), $oldTitle, $newTitle); + ReferenceHelper::getInstance()->updateNamedFormulae($this->worksheet->getParent(), $oldTitle, $newTitle); } return $this; diff --git a/src/PhpSpreadsheet/ReferenceHelper.php b/src/PhpSpreadsheet/ReferenceHelper.php index 16323ed5..1d2ab6a0 100644 --- a/src/PhpSpreadsheet/ReferenceHelper.php +++ b/src/PhpSpreadsheet/ReferenceHelper.php @@ -862,13 +862,13 @@ class ReferenceHelper } /** - * Update named formulas (i.e. containing worksheet references / named ranges). + * Update named formulae (i.e. containing worksheet references / named ranges). * * @param Spreadsheet $spreadsheet Object to update * @param string $oldName Old name (name to replace) * @param string $newName New name */ - public function updateNamedFormulas(Spreadsheet $spreadsheet, $oldName = '', $newName = ''): void + public function updateNamedFormulae(Spreadsheet $spreadsheet, $oldName = '', $newName = ''): void { if ($oldName == '') { return; @@ -889,6 +889,41 @@ class ReferenceHelper } } + private function updateDefinedNames(Worksheet $worksheet, string $beforeCellAddress, int $numberOfColumns, int $numberOfRows): void + { + foreach ($worksheet->getParent()->getDefinedNames() as $definedName) { + if ($definedName->isFormula() === false) { + $this->updateNamedRange($definedName, $worksheet, $beforeCellAddress, $numberOfColumns, $numberOfRows); + } else { + $this->updateNamedFormula($definedName, $worksheet, $beforeCellAddress, $numberOfColumns, $numberOfRows); + } + } + } + + private function updateNamedRange(DefinedName $definedName, Worksheet $worksheet, string $beforeCellAddress, int $numberOfColumns, int $numberOfRows): void + { + $cellAddress = $definedName->getValue(); + $asFormula = ($cellAddress[0] === '='); + if ($definedName->getWorksheet() !== null && $definedName->getWorksheet()->getHashCode() === $worksheet->getHashCode()) { + if ($asFormula === true) { + $formula = $definedName->getValue(); + $formula = $this->updateFormulaReferences($formula, $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle()); + $definedName->setValue($formula); + } else { + $definedName->setValue($asFormula . $this->updateCellReference(ltrim($cellAddress, '='))); + } + } + } + + private function updateNamedFormula(DefinedName $definedName, Worksheet $worksheet, string $beforeCellAddress, int $numberOfColumns, int $numberOfRows): void + { + if ($definedName->getWorksheet() !== null && $definedName->getWorksheet()->getHashCode() === $worksheet->getHashCode()) { + $formula = $definedName->getValue(); + $formula = $this->updateFormulaReferences($formula, $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle()); + $definedName->setValue($formula); + } + } + /** * Update cell range. * @@ -1159,29 +1194,4 @@ class ReferenceHelper { throw new Exception('Cloning a Singleton is not allowed!'); } - - public function updateDefinedNames(Worksheet $worksheet, string $beforeCellAddress, int $numberOfColumns, int $numberOfRows): void - { - foreach ($worksheet->getParent()->getDefinedNames() as $definedName) { - if ($definedName->isFormula() === false) { - $cellAddress = $definedName->getValue(); - $asFormula = ($cellAddress[0] === '='); - if ($definedName->getWorksheet() !== null && $definedName->getWorksheet()->getHashCode() === $worksheet->getHashCode()) { - if ($asFormula === true) { - $formula = $definedName->getValue(); - $formula = $this->updateFormulaReferences($formula, $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle()); - $definedName->setValue($formula); - } else { - $definedName->setValue($asFormula . $this->updateCellReference(ltrim($cellAddress, '='))); - } - } - } else { - $formula = $definedName->getValue(); - if ($definedName->getWorksheet() !== null && $definedName->getWorksheet()->getHashCode() === $worksheet->getHashCode()) { - $formula = $this->updateFormulaReferences($formula, $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle()); - $definedName->setValue($formula); - } - } - } - } } diff --git a/src/PhpSpreadsheet/Worksheet/Worksheet.php b/src/PhpSpreadsheet/Worksheet/Worksheet.php index 55327932..8235ccf1 100644 --- a/src/PhpSpreadsheet/Worksheet/Worksheet.php +++ b/src/PhpSpreadsheet/Worksheet/Worksheet.php @@ -923,7 +923,7 @@ class Worksheet implements IComparable $this->parent->getCalculationEngine() ->renameCalculationCacheForWorksheet($oldTitle, $newTitle); if ($updateFormulaCellReferences) { - ReferenceHelper::getInstance()->updateNamedFormulas($this->parent, $oldTitle, $newTitle); + ReferenceHelper::getInstance()->updateNamedFormulae($this->parent, $oldTitle, $newTitle); } }