PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception
Merge can only be removed from a range of cells.
Error message
Merge can only be removed from a range of cells.
What it means
Worksheet::unmergeCells() requires the normalized range to contain ':' — merges are always stored as (at least) 'A1:B2' style ranges, so removing a merge identified by a single cell address is rejected before the map lookup. (mergeCells() auto-expands 'A1' to 'A1:A1', but unmergeCells() deliberately does not.)
Source
Thrown at src/PhpSpreadsheet/Worksheet/Worksheet.php:1976
*
* @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;
}
/**
* Set merge cells array for the entire sheet. Use instead mergeCells() to merge
* a single cell range.View on GitHub (pinned to 65b080eef4)
Solutions
- Pass the full merged range: unmergeCells('A1:B2')
- When only the cell is known, look up the containing merge in getMergeCells() and unmerge that exact string
Example fix
// before
$sheet->unmergeCells('A1'); // single cell -> throws
// after
foreach ($sheet->getMergeCells() as $merge) {
[$from] = explode(':', $merge);
if ($from === 'A1') {
$sheet->unmergeCells($merge);
}
} Defensive patterns
Strategy: validation
Validate before calling
if (str_contains($range, ':')) {
$sheet->unmergeCells($range);
} else {
foreach ($sheet->getMergeCells() as $merge) {
if (str_starts_with($merge, $range . ':') || explode(':', $merge)[0] === $range) {
$sheet->unmergeCells($merge);
}
}
} Prevention
- Treat 'unmerge' as an operation on stored ranges, not on cells
- Single-cell 'A1' style arguments belong to cell APIs, never unmergeCells
- When in doubt, dump getMergeCells() and choose the entry programmatically
When it happens
Trigger: $sheet->unmergeCells('A1'); unmerging with a coordinate variable that holds a single address because the ':B2' part was lost; splitting a range string and passing only the first half.
Common situations: Application code that knows 'the merged cell A1' and tries to unmerge just it; generic 'clear formatting at X' routines that forward single coordinates to unmergeCells().
Related errors
- Cell range {$range} not known as merged.
- CellRange array length must be 2 or 4
- Unsupported binary comparison operator
- Cloning the calculation engine is not allowed!
- Unsupported numeric binary operation
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/f2a0e41d51004040.
Report an issue: GitHub.