diff --git a/src/PhpSpreadsheet/Spreadsheet.php b/src/PhpSpreadsheet/Spreadsheet.php index 943db95cc..530a56da8 100644 --- a/src/PhpSpreadsheet/Spreadsheet.php +++ b/src/PhpSpreadsheet/Spreadsheet.php @@ -514,6 +514,16 @@ class Spreadsheet implements JsonSerializable public function createSheet(?int $sheetIndex = null): Worksheet { $newSheet = new Worksheet($this); + $title = $newSheet->getTitle(); + if ($this->sheetNameExists($title)) { + $i = 1; + $newTitle = "$title $i"; + while ($this->sheetNameExists($newTitle)) { + ++$i; + $newTitle = "$title $i"; + } + $newSheet->setTitle($newTitle); + } $this->addSheet($newSheet, $sheetIndex); return $newSheet; diff --git a/src/PhpSpreadsheet/Worksheet/Worksheet.php b/src/PhpSpreadsheet/Worksheet/Worksheet.php index 546a6ffe5..a3ee4818b 100644 --- a/src/PhpSpreadsheet/Worksheet/Worksheet.php +++ b/src/PhpSpreadsheet/Worksheet/Worksheet.php @@ -321,6 +321,7 @@ class Worksheet { // Set parent and title $this->parent = $parent; + $this->hash = spl_object_id($this); $this->setTitle($title, false); // setTitle can change $pTitle $this->setCodeName($this->getTitle()); @@ -349,7 +350,6 @@ class Worksheet $this->autoFilter = new AutoFilter('', $this); // Table collection $this->tableCollection = new ArrayObject(); - $this->hash = spl_object_id($this); } /** @@ -869,7 +869,7 @@ class Worksheet // Syntax check self::checkSheetTitle($title); - if ($this->parent) { + if ($this->parent && $this->parent->getIndex($this, true) >= 0) { // Is there already such sheet name? if ($this->parent->sheetNameExists($title)) { // Use name, but append with lowest possible integer @@ -899,7 +899,7 @@ class Worksheet // Set title $this->title = $title; - if ($this->parent && $this->parent->getCalculationEngine()) { + if ($this->parent && $this->parent->getIndex($this, true) >= 0 && $this->parent->getCalculationEngine()) { // New title $newTitle = $this->getTitle(); $this->parent->getCalculationEngine() diff --git a/tests/PhpSpreadsheetTests/Worksheet/Issue641Test.php b/tests/PhpSpreadsheetTests/Worksheet/Issue641Test.php new file mode 100644 index 000000000..bbb6c8bf0 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Worksheet/Issue641Test.php @@ -0,0 +1,82 @@ +removeSheetByIndex(0); + $availableWs = []; + + $worksheet = $xlsx->createSheet(); + $worksheet->setTitle('Condensed A'); + $worksheet->getCell('A1')->setValue("=SUM('Detailed A'!A1:A10)"); + $worksheet->getCell('A2')->setValue(mt_rand(1, 30)); + $availableWs[] = 'Condensed A'; + + $worksheet = $xlsx->createSheet(); + $worksheet->setTitle('Condensed B'); + $worksheet->getCell('A1')->setValue("=SUM('Detailed B'!A1:A10)"); + $worksheet->getCell('A2')->setValue(mt_rand(1, 30)); + $availableWs[] = 'Condensed B'; + + // at this point the value in worksheet 'Condensed B' cell A1 is + // =SUM('Detailed B'!A1:A10) + + // worksheet in question is cloned and totals are attached + $totalWs1 = clone $xlsx->getSheet($xlsx->getSheetCount() - 1); + $totalWs1->setTitle('Condensed Total'); + $xlsx->addSheet($totalWs1); + $formula = '='; + foreach ($availableWs as $ws) { + $formula .= sprintf("+'%s'!A2", $ws); + } + $totalWs1->getCell('A1')->setValue("=SUM('Detailed Total'!A1:A10)"); + $totalWs1->getCell('A2')->setValue($formula); + + $availableWs = []; + + $worksheet = $xlsx->createSheet(); + $worksheet->setTitle('Detailed A'); + for ($step = 1; $step <= 10; ++$step) { + $worksheet->getCell("A{$step}")->setValue(mt_rand(1, 30)); + } + $availableWs[] = 'Detailed A'; + + $worksheet = $xlsx->createSheet(); + $worksheet->setTitle('Detailed B'); + for ($step = 1; $step <= 10; ++$step) { + $worksheet->getCell("A{$step}")->setValue(mt_rand(1, 30)); + } + $availableWs[] = 'Detailed B'; + + $totalWs2 = clone $xlsx->getSheet($xlsx->getSheetCount() - 1); + $totalWs2->setTitle('Detailed Total'); + $xlsx->addSheet($totalWs2); + + for ($step = 1; $step <= 10; ++$step) { + $formula = '='; + foreach ($availableWs as $ws) { + $formula .= sprintf("+'%s'!A%s", $ws, $step); + } + $totalWs2->getCell("A{$step}")->setValue($formula); + } + + self::assertSame("=SUM('Detailed A'!A1:A10)", $xlsx->getSheetByName('Condensed A')?->getCell('A1')?->getValue()); + self::assertSame("=SUM('Detailed B'!A1:A10)", $xlsx->getSheetByName('Condensed B')?->getCell('A1')?->getValue()); + self::assertSame("=SUM('Detailed Total'!A1:A10)", $xlsx->getSheetByName('Condensed Total')?->getCell('A1')?->getValue()); + self::assertSame("=+'Detailed A'!A1+'Detailed B'!A1", $xlsx->getSheetByName('Detailed Total')?->getCell('A1')?->getValue()); + + $xlsx->disconnectWorksheets(); + } +}