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

  1. Clone the drawing for each additional sheet: $copy = clone $drawing; $copy->setWorksheet($sheet2);
  2. Or pass overrideOld = true to move (not copy) it: $drawing->setWorksheet($sheet2, true)
  3. 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

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


AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17). Data as JSON: /api/errors/6c2c696bed379d4d. Report an issue: GitHub.