From 09eb05f367f7adf0b36869aa405eec84752b1377 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Sun, 21 Oct 2018 17:40:21 +1100 Subject: [PATCH] OFFSET should allow omitted height and width Commit 8dddf56 inadvertently removed the ability to omit the width and height arguments to the OFFSET function. And #REF! is returned because the function is validating that the new $pCell argument is present. It is present, but it has been passed in the $height position. We fixed this by always passing $pCell at the last position and filling missing arguments with NULL values. Fixes #561 Fixes #565 --- CHANGELOG.md | 1 + .../Calculation/Calculation.php | 32 +++++++++++++++++-- .../Calculation/CalculationTest.php | 23 +++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af6832ea2f..cac43c9de8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Sheet title can contain exclamation mark - [#325](https://github.com/PHPOffice/PhpSpreadsheet/issues/325) - Xls file cause the exception during open by Xls reader - [#402](https://github.com/PHPOffice/PhpSpreadsheet/issues/402) - Skip non numeric value in SUMIF - [#618](https://github.com/PHPOffice/PhpSpreadsheet/pull/618) +- OFFSET should allow omitted height and width - [#561](https://github.com/PHPOffice/PhpSpreadsheet/issues/561) ## [1.4.1] - 2018-09-30 diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index 048490f145..2e5f967b5b 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -3942,9 +3942,7 @@ private function processTokenStack($tokens, $cellID = null, Cell $pCell = null) } // Process the argument with the appropriate function call - if ($passCellReference) { - $args[] = $pCell; - } + $args = $this->addCellReference($args, $passCellReference, $pCell, $functionCall); if (!is_array($functionCall)) { foreach ($args as &$arg) { @@ -4436,4 +4434,32 @@ public function getImplementedFunctionNames() return $returnValue; } + + /** + * Add cell reference if needed while making sure that it is the last argument. + * + * @param array $args + * @param bool $passCellReference + * @param Cell $pCell + * @param array $functionCall + * + * @return array + */ + private function addCellReference(array $args, $passCellReference, Cell $pCell, array $functionCall) + { + if ($passCellReference) { + $className = $functionCall[0]; + $methodName = $functionCall[1]; + + $reflectionMethod = new \ReflectionMethod($className, $methodName); + $argumentCount = count($reflectionMethod->getParameters()); + while (count($args) < $argumentCount - 1) { + $args[] = null; + } + + $args[] = $pCell; + } + + return $args; + } } diff --git a/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php b/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php index 871b6ef537..cd77ef84db 100644 --- a/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php @@ -4,6 +4,7 @@ use PhpOffice\PhpSpreadsheet\Calculation\Calculation; use PhpOffice\PhpSpreadsheet\Calculation\Functions; +use PhpOffice\PhpSpreadsheet\Spreadsheet; use PHPUnit\Framework\TestCase; class CalculationTest extends TestCase @@ -117,4 +118,26 @@ public function testDoesHandleXlfnFunctions() $function = $tree[4]; self::assertEquals('Function', $function['type']); } + + public function testFormulaWithOptionalArgumentsAndRequiredCellReferenceShouldPassNullForMissingArguments() + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + + $sheet->fromArray( + [ + [1, 2, 3], + [4, 5, 6], + [7, 8, 9], + ] + ); + + $cell = $sheet->getCell('E5'); + $cell->setValue('=OFFSET(D3, -1, -2, 1, 1)'); + self::assertEquals(5, $cell->getCalculatedValue(), 'with all arguments'); + + $cell = $sheet->getCell('F6'); + $cell->setValue('=OFFSET(D3, -1, -2)'); + self::assertEquals(5, $cell->getCalculatedValue(), 'missing arguments should be filled with null'); + } }