{"record":{"id":"5cf9c673ed47112d","repo":"PHPOffice/PhpSpreadsheet","slug":"workbook-already-contains-a-worksheet-named-wor-5cf9c6","errorCode":null,"errorMessage":"Workbook already contains a worksheet named '{$worksheet->getTitle()}'. Rename the external sheet first.","messagePattern":"Workbook already contains a worksheet named '(.+?)'\\. Rename the external sheet first\\.","errorType":"exception","errorClass":"PhpOffice\\PhpSpreadsheet\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/Spreadsheet.php","lineNumber":871,"sourceCode":"        $returnValue = [];\n        $worksheetCount = $this->getSheetCount();\n        for ($i = 0; $i < $worksheetCount; ++$i) {\n            $returnValue[] = $this->getSheet($i)->getTitle();\n        }\n\n        return $returnValue;\n    }\n\n    /**\n     * Add external sheet.\n     *\n     * @param Worksheet $worksheet External sheet to add\n     * @param null|int $sheetIndex Index where sheet should go (0,1,..., or null for last)\n     */\n    public function addExternalSheet(Worksheet $worksheet, ?int $sheetIndex = null): Worksheet\n    {\n        if ($this->sheetNameExists($worksheet->getTitle())) {\n            throw new Exception(\"Workbook already contains a worksheet named '{$worksheet->getTitle()}'. Rename the external sheet first.\");\n        }\n\n        // count how many cellXfs there are in this workbook currently, we will need this below\n        $countCellXfs = count($this->cellXfCollection);\n\n        // copy all the shared cellXfs from the external workbook and append them to the current\n        foreach ($worksheet->getParentOrThrow()->getCellXfCollection() as $cellXf) {\n            $this->addCellXf(clone $cellXf);\n        }\n\n        // move sheet to this workbook\n        $worksheet->rebindParent($this);\n\n        // update the cellXfs\n        foreach ($worksheet->getCoordinates(false) as $coordinate) {\n            $cell = $worksheet->getCell($coordinate);\n            $cell->setXfIndex($cell->getXfIndex() + $countCellXfs);\n        }","sourceCodeStart":853,"sourceCodeEnd":889,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/Spreadsheet.php#L853-L889","documentation":"Spreadsheet::addExternalSheet() moves a worksheet that belongs to another workbook into this one, copying the external workbook's shared cellXf styles along with it. Unlike addSheet() there is no auto-rename path: if this workbook already has a sheet with the incoming title, it throws immediately and tells you to rename the external sheet first.","triggerScenarios":"Merging two workbooks whose sheets share names (both contain 'Sheet1'): $target->addExternalSheet($source->getSheetByNameOrThrow('Sheet1')); importing a generated 'Data' tab into a report that already has 'Data'; consolidating monthly files that all use the same tab name.","commonSituations":"Report consolidation pipelines (many source files, one destination) without a per-source prefix/suffix on tab names; combining a template workbook with uploaded workbooks where users keep default names; merging after copying sheets with Worksheet::copy().","solutions":["Rename before moving: $sheet->setTitle('Source - ' . $sheet->getTitle()); then addExternalSheet($sheet).","Or rename the collision target in the destination workbook to free the name.","Or drop the existing destination sheet first: $target->removeSheetByIndex($target->getIndex($target->getSheetByName($name)));","Unify names with a prefix/suffix scheme (source file basename, date) so merges never collide."],"exampleFix":"// before\n$target->addExternalSheet($source->getSheetByNameOrThrow('Sheet1')); // throws\n\n// after\n$sheet = $source->getSheetByNameOrThrow('Sheet1');\nif ($target->sheetNameExists($sheet->getTitle())) {\n    $sheet->setTitle(pathinfo($sourcePath, PATHINFO_FILENAME) . ' - ' . $sheet->getTitle());\n}\n$target->addExternalSheet($sheet);","handlingStrategy":"validation","validationCode":"if ($target->sheetNameExists($sheet->getTitle())) {\n    $sheet->setTitle($prefix . ' - ' . $sheet->getTitle());\n}\n$target->addExternalSheet($sheet);","typeGuard":"function externalSheetTitleIsFree(\\PhpOffice\\PhpSpreadsheet\\Spreadsheet $target, \\PhpOffice\\PhpSpreadsheet\\Worksheet\\Worksheet $w): bool\n{\n    return !$target->sheetNameExists($w->getTitle());\n}","tryCatchPattern":"try {\n    $target->addExternalSheet($sheet);\n} catch (\\PhpOffice\\PhpSpreadsheet\\Exception $e) {\n    $sheet->setTitle(uniqid('sheet-'));\n    $target->addExternalSheet($sheet);\n}","preventionTips":["Prefix merged sheet titles with the source file/date by convention.","Check sheetNameExists() on the target before every merge.","Centralize merge logic in one helper that always uniquifies."],"tags":["worksheet","duplicate-name","merge-workbooks","phpspreadsheet"],"backgroundTag":"duplicate-sheet-name","analyzedSha":"65b080eef4d9fd11a5796135ab145883e5c3d6a6","analyzedAt":"2026-08-17T05:40:41.646Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}