From 6c27ed99a54bced66b989ec0477dc4eca932767d Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Thu, 8 Apr 2021 18:17:29 +0200 Subject: [PATCH 1/2] Implement Defined Name handling in INDIRECT() function (No unit tests yet) --- .../Calculation/Calculation.php | 2 +- .../Calculation/LookupRef/Indirect.php | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index 9477131fda..df9ec18c93 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -5312,7 +5312,7 @@ private function getTokensAsString($tokens) /** * @return mixed|string */ - private function evaluateDefinedName(Cell $pCell, DefinedName $namedRange, Worksheet $pCellWorksheet, Stack $stack) + public function evaluateDefinedName(Cell $pCell, DefinedName $namedRange, Worksheet $pCellWorksheet, Stack $stack) { $definedNameScope = $namedRange->getScope(); if ($definedNameScope !== null && $definedNameScope !== $pCellWorksheet) { diff --git a/src/PhpSpreadsheet/Calculation/LookupRef/Indirect.php b/src/PhpSpreadsheet/Calculation/LookupRef/Indirect.php index c34dd9651b..12324eb8a0 100644 --- a/src/PhpSpreadsheet/Calculation/LookupRef/Indirect.php +++ b/src/PhpSpreadsheet/Calculation/LookupRef/Indirect.php @@ -4,7 +4,9 @@ use PhpOffice\PhpSpreadsheet\Calculation\Calculation; use PhpOffice\PhpSpreadsheet\Calculation\Functions; +use PhpOffice\PhpSpreadsheet\Calculation\Token\Stack; use PhpOffice\PhpSpreadsheet\Cell\Cell; +use PhpOffice\PhpSpreadsheet\DefinedName; use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; class Indirect @@ -34,6 +36,10 @@ public static function INDIRECT($cellAddress = null, ?Cell $pCell = null) return Functions::REF(); } + if (preg_match('/^' . Calculation::CALCULATION_REGEXP_DEFINEDNAME . '$/miu', $cellAddress, $matches)) { + return self::evaluateDefinedName($matches[6], $pCell); + } + [$cellAddress, $pSheet] = self::extractWorksheet($cellAddress, $pCell); $cellAddress1 = $cellAddress; @@ -72,4 +78,17 @@ private static function extractWorksheet($cellAddress, Cell $pCell): array return [$cellAddress, $pSheet]; } + + private static function evaluateDefinedName(string $definedName, Cell $pCell) + { + $workSheet = $pCell->getWorksheet(); + $namedRange = DefinedName::resolveName($definedName, $workSheet); + if ($namedRange === null) { + return Functions::REF(); + } + + $calculationEngine = Calculation::getInstance($workSheet->getParent()); + + return $calculationEngine->evaluateDefinedName($pCell, $namedRange, $workSheet, new Stack()); + } } From adcf79ca84584c50df970098dc7895d66d17a730 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Thu, 8 Apr 2021 18:26:43 +0200 Subject: [PATCH 2/2] Avoid confusing define names with cell references --- .../Calculation/LookupRef/Indirect.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/LookupRef/Indirect.php b/src/PhpSpreadsheet/Calculation/LookupRef/Indirect.php index 12324eb8a0..6d81700287 100644 --- a/src/PhpSpreadsheet/Calculation/LookupRef/Indirect.php +++ b/src/PhpSpreadsheet/Calculation/LookupRef/Indirect.php @@ -3,6 +3,7 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\LookupRef; use PhpOffice\PhpSpreadsheet\Calculation\Calculation; +use PhpOffice\PhpSpreadsheet\Calculation\Exception; use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Calculation\Token\Stack; use PhpOffice\PhpSpreadsheet\Cell\Cell; @@ -36,8 +37,14 @@ public static function INDIRECT($cellAddress = null, ?Cell $pCell = null) return Functions::REF(); } - if (preg_match('/^' . Calculation::CALCULATION_REGEXP_DEFINEDNAME . '$/miu', $cellAddress, $matches)) { - return self::evaluateDefinedName($matches[6], $pCell); + if ( + (!preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $cellAddress, $matches)) && + (preg_match('/^' . Calculation::CALCULATION_REGEXP_DEFINEDNAME . '$/miu', $cellAddress, $matches)) + ) { + try { + return self::evaluateDefinedName($matches[6], $pCell); + } catch (Exception $e) { + } } [$cellAddress, $pSheet] = self::extractWorksheet($cellAddress, $pCell); @@ -84,7 +91,7 @@ private static function evaluateDefinedName(string $definedName, Cell $pCell) $workSheet = $pCell->getWorksheet(); $namedRange = DefinedName::resolveName($definedName, $workSheet); if ($namedRange === null) { - return Functions::REF(); + throw new Exception(Functions::REF()); } $calculationEngine = Calculation::getInstance($workSheet->getParent());