From 36afa01d33a0ee81746c3b1de4482954028667bc Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Sat, 21 Apr 2018 01:33:26 +0100 Subject: [PATCH] SUBTOTAL within a SUBTOAL range should be ignored --- src/PhpSpreadsheet/Calculation/MathTrig.php | 2 +- .../Calculation/MathTrigTest.php | 45 +++++++++++++++++-- .../Calculation/MathTrig/SUBTOTALNESTED.php | 16 +++++++ 3 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 tests/data/Calculation/MathTrig/SUBTOTALNESTED.php diff --git a/src/PhpSpreadsheet/Calculation/MathTrig.php b/src/PhpSpreadsheet/Calculation/MathTrig.php index bdc1e026..99a52e97 100644 --- a/src/PhpSpreadsheet/Calculation/MathTrig.php +++ b/src/PhpSpreadsheet/Calculation/MathTrig.php @@ -1088,7 +1088,7 @@ class MathTrig list(, $row, $column) = explode('.', $index); if ($cellReference->getWorksheet()->cellExists($column . $row)) { //take this cell out if it contains the SUBTOTAL formula - return strpos(strtoupper($cellReference->getWorksheet()->getCell($column . $row)->getValue()), '=SUBTOTAL(') === false; + return !preg_match('/=.*\b(SUBTOTAL)\s*\(/', strtoupper($cellReference->getWorksheet()->getCell($column . $row)->getValue())); } return true; }, diff --git a/tests/PhpSpreadsheetTests/Calculation/MathTrigTest.php b/tests/PhpSpreadsheetTests/Calculation/MathTrigTest.php index 4d6048f1..eda750af 100644 --- a/tests/PhpSpreadsheetTests/Calculation/MathTrigTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/MathTrigTest.php @@ -547,11 +547,11 @@ class MathTrigTest extends TestCase } /** - * @dataProvider providerSUBTOTALHIDDEN + * @dataProvider providerHiddenSUBTOTAL * * @param mixed $expectedResult */ - public function testSUBTOTALHIDDEN($expectedResult, ...$args) + public function testHiddenSUBTOTAL($expectedResult, ...$args) { $generator = \PhpOffice\PhpSpreadsheetTests\Calculation\MathTrigTest::rowVisibility(); $rowDimension = $this->getMockBuilder(RowDimension::class) @@ -596,8 +596,47 @@ class MathTrigTest extends TestCase self::assertEquals($expectedResult, $result, null, 1E-12); } - public function providerSUBTOTALHIDDEN() + public function providerHiddenSUBTOTAL() { return require 'data/Calculation/MathTrig/SUBTOTALHIDDEN.php'; } + + /** + * @dataProvider providerNestedSUBTOTAL + * + * @param mixed $expectedResult + */ + public function testNestedSUBTOTAL($expectedResult, ...$args) + { + $cell = $this->getMockBuilder(Cell::class) + ->setMethods(['getValue']) + ->disableOriginalConstructor() + ->getMock(); + $cell->method('getValue') + ->willReturn(null); + $worksheet = $this->getMockBuilder(Worksheet::class) + ->setMethods(['cellExists', 'getCell']) + ->disableOriginalConstructor() + ->getMock(); + $worksheet->method('cellExists') + ->willReturn(true); + $worksheet->method('getCell') + ->willReturn($cell); + $cellReference = $this->getMockBuilder(Cell::class) + ->setMethods(['getWorksheet']) + ->disableOriginalConstructor() + ->getMock(); + $cellReference->method('getWorksheet') + ->willReturn($worksheet); + + array_push($args, $cellReference); + $result = MathTrig::SUBTOTAL(...$args); + self::assertEquals($expectedResult, $result, null, 1E-12); + } + + public function providerNestedSUBTOTAL() + { + return require 'data/Calculation/MathTrig/SUBTOTALNESTED.php'; + } + } diff --git a/tests/data/Calculation/MathTrig/SUBTOTALNESTED.php b/tests/data/Calculation/MathTrig/SUBTOTALNESTED.php new file mode 100644 index 00000000..20a8e170 --- /dev/null +++ b/tests/data/Calculation/MathTrig/SUBTOTALNESTED.php @@ -0,0 +1,16 @@ + ['A' => 1], + 2 => ['A' => 1], + 3 => ['A' => '=SUBTOTAL(1, A1:A2)'], + 4 => ['A' => '=ROMAN(SUBTOTAL(1, A1:A2))'] +]; + +return [ + [ + 2, + 2, + $baseTestData, + ], +];