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
- Verify existence first: if ($spreadsheet->sheetNameExists($name)) { ... } before activating.
- Inspect the real titles: $spreadsheet->getSheetNames(); and trim/normalize your $name to match.
- Fall back to activating by index when the name is missing: setActiveSheetIndex(0).
- 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
- Store tab names in shared constants, not string literals in each call site.
- Normalize (trim, case) names from config or user input.
- Validate expected tabs right after loading a template.
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
- Sheet {$worksheetName} does not exist.
- You tried to set a sheet active by the out of bounds index:
- Sheet not found for name: {$worksheetReference[0]}
- Cannot update when cell is not bound to a worksheet
- Cannot get column when cell is not bound to a worksheet
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/1591fc178e98286e.
Report an issue: GitHub.