PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception
Cell range {$range} not known as merged.
Error message
Cell range {$range} not known as merged. What it means
Worksheet::unmergeCells() looks the exact normalized range string up in the sheet's merged-cells map and throws when it is absent. Unlike mergeCells() it does not normalize bounds or expand single cells, so the string must byte-for-byte equal a stored entry (which mergeCells stores in normalized 'A1:B2' form: colon present, top-left first).
Source
Thrown at src/PhpSpreadsheet/Worksheet/Worksheet.php:1973
/**
* Remove merge on a cell range.
*
* @param AddressRange<CellAddress>|AddressRange<int>|AddressRange<string>|array{0: int, 1: int, 2: int, 3: int}|array{0: int, 1: int}|string $range A simple string containing a Cell range like 'A1:E10'
* or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]),
* or an AddressRange.
*
* @return $this
*/
public function unmergeCells(AddressRange|string|array $range): static
{
$range = Functions::trimSheetFromCellReference(Validations::validateCellRange($range));
if (str_contains($range, ':')) {
if (isset($this->mergeCells[$range])) {
unset($this->mergeCells[$range]);
} else {
throw new Exception('Cell range ' . $range . ' not known as merged.');
}
} else {
throw new Exception('Merge can only be removed from a range of cells.');
}
return $this;
}
/**
* Get merge cells array.
*
* @return string[]
*/
public function getMergeCells(): array
{
return $this->mergeCells;
}
View on GitHub (pinned to 65b080eef4)
Solutions
- List the real merges first: $merges = $sheet->getMergeCells(); and pass one of those exact strings to unmergeCells()
- To unmerge 'the block containing A1', find the containing entry: foreach ($sheet->getMergeCells() as $m) { if (Coordinate::coordinateIsInside? — check bounds) unmergeCells($m); } using rangeBoundaries containment
- Guard with in_array($range, $sheet->getMergeCells(), true) before calling
Example fix
// before
$sheet->unmergeCells('A1:C3'); // actual merge was 'A1:B2' -> throws
// after
$target = 'A1:C3';
if (in_array($target, $sheet->getMergeCells(), true)) {
$sheet->unmergeCells($target);
} else {
foreach ($sheet->getMergeCells() as $merge) {
if (str_contains($merge, 'A1:') || str_starts_with($merge, 'A1')) {
$sheet->unmergeCells($merge);
}
}
} Defensive patterns
Strategy: validation
Validate before calling
if (in_array($range, $sheet->getMergeCells(), true)) {
$sheet->unmergeCells($range);
} else {
// pick the exact stored string from getMergeCells() instead
} Try / catch
try {
$sheet->unmergeCells($range);
} catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
if (str_contains($e->getMessage(), 'not known as merged')) {
// range was never merged — nothing to do
} else {
throw $e;
}
} Prevention
- Always source the unmerge argument from getMergeCells(), never from memory
- When unmerging 'the block containing a cell', find the containing stored range first
- Remember unmergeCells does not normalize bounds — pass the stored string verbatim
When it happens
Trigger: unmergeCells('A1:C3') when the actual merge is 'A1:B2'; unmerging before any mergeCells() call on that range; passing reversed bounds 'C3:A1' or a lowercase variant of a stored merge.
Common situations: Unmerging a guessed/remembered range instead of the exact one; loading third-party files where merge boundaries differ from expectations; unmerging a sub-block assumed to be independently merged.
Related errors
- Merge can only be removed from a range of cells.
- Cell range {$range} not known as protected.
- CellRange array length must be 2 or 4
- Unsupported binary comparison operator
- Cloning the calculation engine is not allowed!
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/57b03c4355ad4ddb.
Report an issue: GitHub.