PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception
A Worksheet has already been assigned. Drawings can only exi
Error message
A Worksheet has already been assigned. Drawings can only exist on one Worksheet.
What it means
BaseDrawing::setWorksheet() throws when the drawing already belongs to a worksheet and the $overrideOld flag is false (the default). A drawing object can live on only one worksheet, so attaching the same instance to a second sheet is refused instead of duplicating it silently.
Source
Thrown at src/PhpSpreadsheet/Worksheet/BaseDrawing.php:240
$this->worksheet->getDrawingCollection(),
$this->worksheet->getInCellDrawingCollection(),
];
foreach ($collections as $collection) {
foreach ($collection as $key => $drawing) {
if ($drawing->getHashCode() === $this->getHashCode()) {
$collection->offsetUnset($key);
$this->worksheet = null;
break 2; // break both loops
}
}
}
// Set new Worksheet
$this->setWorksheet($worksheet);
} else {
throw new PhpSpreadsheetException('A Worksheet has already been assigned. Drawings can only exist on one Worksheet.');
}
}
return $this;
}
public function getCoordinates(): string
{
return $this->coordinates;
}
public function setCoordinates(string $coordinates): self
{
$this->coordinates = $coordinates;
if ($this->worksheet !== null) {
if (!($this instanceof Drawing && $this->getPath() === '')) {
$this->worksheet->getCell($this->coordinates);
}View on GitHub (pinned to 65b080eef4)
Solutions
- Clone the drawing for each additional sheet: $copy = clone $drawing; $copy->setWorksheet($sheet2);
- Or pass overrideOld = true to move (not copy) it: $drawing->setWorksheet($sheet2, true)
- When loading a file and reassigning drawings, always instantiate or clone fresh objects per sheet
Example fix
// before $sheet1->addDrawing($drawing); $sheet2->addDrawing($drawing); // throws // after $sheet1->addDrawing($drawing); $copy = clone $drawing; $sheet2->addDrawing($copy);
Defensive patterns
Strategy: validation
Validate before calling
function attachDrawing(Worksheet $target, BaseDrawing $drawing): void
{
if ($drawing->getWorksheet() !== null && $drawing->getWorksheet() !== $target) {
$drawing = clone $drawing; // separate copy per sheet
}
$drawing->setWorksheet($target);
} Type guard
function isUnassignedDrawing(\PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing $d): bool
{
return $d->getWorksheet() === null;
} Try / catch
try {
$drawing->setWorksheet($sheet2);
} catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
// already owned by sheet1: clone for the second sheet (or pass true to move it)
$copy = clone $drawing;
$copy->setWorksheet($sheet2);
} Prevention
- Never add the same drawing instance to two sheets; clone per sheet
- Use setWorksheet($sheet, true) when you intend to move, not copy
- Remember cloned drawings still reference the same image path (shared, not duplicated)
When it happens
Trigger: $sheet2->addDrawing($drawing) where $drawing was already added to $sheet1; re-adding a drawing retrieved from $sheet1->getDrawingCollection() to another sheet.
Common situations: Copying an image/chart to multiple sheets using the same object; template code that moves drawings between sheets without cloning.
Related errors
- File $filename does not exist
- Cannot update when cell is not bound to a worksheet
- Cannot get column when cell is not bound to a worksheet
- Cannot get row when cell is not bound to a worksheet
- Item is not a drawing
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/6c2c696bed379d4d.
Report an issue: GitHub.