PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception

Workbook does not contain sheet:{$worksheetName}

Error message

Workbook does not contain sheet:{$worksheetName}

What it means

Spreadsheet::setActiveSheetIndexByName() resolves a sheet title via getSheetByName() and activates it; when no sheet carries that name it throws 'Workbook does not contain sheet:{name}'. Name matching follows getSheetByName's rules (case-insensitive, otherwise exact).

Source

Thrown at src/PhpSpreadsheet/Spreadsheet.php:843

        $this->activeSheetIndex = $worksheetIndex;

        return $this->getActiveSheet();
    }

    /**
     * Set active sheet index by name.
     *
     * @param string $worksheetName Sheet title
     */
    public function setActiveSheetIndexByName(string $worksheetName): Worksheet
    {
        if (($worksheet = $this->getSheetByName($worksheetName)) instanceof Worksheet) {
            $this->setActiveSheetIndex($this->getIndex($worksheet));

            return $worksheet;
        }

        throw new Exception('Workbook does not contain sheet:' . $worksheetName);
    }

    /**
     * Get sheet names.
     *
     * @return string[]
     */
    public function getSheetNames(): array
    {
        $returnValue = [];
        $worksheetCount = $this->getSheetCount();
        for ($i = 0; $i < $worksheetCount; ++$i) {
            $returnValue[] = $this->getSheet($i)->getTitle();
        }

        return $returnValue;
    }

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Verify existence first: if ($spreadsheet->sheetNameExists($name)) { ... } before activating.
  2. Inspect the real titles: $spreadsheet->getSheetNames(); and trim/normalize your $name to match.
  3. Fall back to activating by index when the name is missing: setActiveSheetIndex(0).
  4. Centralize tab names as constants shared by producer and consumer code instead of literals scattered around.

Example fix

// before
$spreadsheet->setActiveSheetIndexByName('summary '); // throws

// after
$name = trim('summary '); // 'summary' matches case-insensitively
if ($spreadsheet->sheetNameExists($name)) {
    $spreadsheet->setActiveSheetIndexByName($name);
} else {
    $spreadsheet->setActiveSheetIndex(0);
}
Defensive patterns

Strategy: validation

Validate before calling

$name = trim($name);
if ($spreadsheet->sheetNameExists($name)) {
    $spreadsheet->setActiveSheetIndexByName($name);
} else {
    $spreadsheet->setActiveSheetIndex(0);
}

Type guard

function canActivateSheetByName(\PhpOffice\PhpSpreadsheet\Spreadsheet $s, string $name): bool
{
    return $s->sheetNameExists(trim($name));
}

Try / catch

try {
    $spreadsheet->setActiveSheetIndexByName($name);
} catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
    $spreadsheet->setActiveSheetIndex(0);
}

Prevention

When it happens

Trigger: setActiveSheetIndexByName('Summary') with a trailing space in the real title; activating a template tab ('Tabelle1' vs 'Sheet1') in localized files; activating a name computed from variables ('Report ' . $period) that does not match; running after code that renamed or removed the tab.

Common situations: Multi-language templates where the first tab's title differs by locale; names assembled from dates/periods where formatting differs (leading zeros, separators); files edited by users who renamed tabs; whitespace introduced when names come from CSV/config cells.

Related errors


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