Skip to content

Commit a846a93

Browse files
authored
Merge pull request #3066 from PHPOffice/Issue-3065_Merge-Cell-Options
Additional options for mergeCells() method
2 parents c6e84fb + 84d6d98 commit a846a93

18 files changed

+435
-29
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ and this project adheres to [Semantic Versioning](https://semver.org).
1717

1818
### Changed
1919

20-
- Nothing
20+
- Allow variant behaviour when merging cells [Issue #3065](https://github.com/PHPOffice/PhpSpreadsheet/issues/3065)
21+
- Merge methods now allow an additional `$behaviour` argument. Permitted values are:
22+
- Worksheet::MERGE_CELL_CONTENT_EMPTY - Empty the content of the hidden cells (the default behaviour)
23+
- Worksheet::MERGE_CELL_CONTENT_HIDE - Keep the content of the hidden cells
24+
- Worksheet::MERGE_CELL_CONTENT_MERGE - Move the content of the hidden cells into the first cell
2125

2226
### Deprecated
2327

3.24 KB
Loading
4.91 KB
Loading
22 KB
Loading

docs/topics/recipes.md

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,22 +1332,72 @@ rows (default), or above. The following code adds the summary above:
13321332
$spreadsheet->getActiveSheet()->setShowSummaryBelow(false);
13331333
```
13341334

1335-
## Merge/unmerge cells
1335+
## Merge/Unmerge cells
13361336

1337-
If you have a big piece of data you want to display in a worksheet, you
1338-
can merge two or more cells together, to become one cell. This can be
1339-
done using the following code:
1337+
If you have a big piece of data you want to display in a worksheet, or a
1338+
heading that needs to span multiple sub-heading columns, you can merge
1339+
two or more cells together, to become one cell. This can be done using
1340+
the following code:
13401341

13411342
```php
13421343
$spreadsheet->getActiveSheet()->mergeCells('A18:E22');
13431344
```
13441345

1345-
Removing a merge can be done using the unmergeCells method:
1346+
Removing a merge can be done using the `unmergeCells()` method:
13461347

13471348
```php
13481349
$spreadsheet->getActiveSheet()->unmergeCells('A18:E22');
13491350
```
13501351

1352+
MS Excel itself doesn't yet offer the functionality to simply hide the merged cells, or to merge the content of cells into a single cell, but it is available in Open/Libre Office.
1353+
1354+
### Merge with MERGE_CELL_CONTENT_EMPTY
1355+
1356+
The default behaviour is to empty all cells except for the top-left corner cell in the merge range; and this is also the default behaviour for the `mergeCells()` method in PhpSpreadsheet.
1357+
When this behaviour is applied, those cell values will be set to null; and if they are subsequently Unmerged, they will be empty cells.
1358+
1359+
Passing an extra flag value to the `mergeCells()` method in PhpSpreadsheet can change this behaviour.
1360+
1361+
![12-01-MergeCells-Options.png](./images/12-01-MergeCells-Options.png)
1362+
1363+
Possible flag values are:
1364+
- Worksheet::MERGE_CELL_CONTENT_EMPTY (the default)
1365+
- Worksheet::MERGE_CELL_CONTENT_HIDE
1366+
- Worksheet::MERGE_CELL_CONTENT_MERGE
1367+
1368+
### Merge with MERGE_CELL_CONTENT_HIDE
1369+
1370+
The first alternative, available only in OpenOffice, is to hide those cells, but to leave their content intact.
1371+
When a file saved as `Xlsx` in those applications is opened in MS Excel, and those cells are unmerged, the original content will still be present.
1372+
1373+
```php
1374+
$spreadsheet->getActiveSheet()->mergeCells('A1:C3', Worksheet::MERGE_CELL_CONTENT_HIDE);
1375+
```
1376+
1377+
Will replicate that behaviour.
1378+
1379+
### Merge with MERGE_CELL_CONTENT_MERGE
1380+
1381+
The second alternative, available in both OpenOffice and LibreOffice is to merge the content of every cell in the merge range into the top-left cell, while setting those hidden cells to empty.
1382+
1383+
```php
1384+
$spreadsheet->getActiveSheet()->mergeCells('A1:C3', Worksheet::MERGE_CELL_CONTENT_MERGE);
1385+
```
1386+
1387+
Particularly when the merged cells contain formulae, the logic for this merge seems strange:
1388+
walking through the merge range, each cell is calculated in turn, and appended to the "master" cell, then it is emptied, so any subsequent calculations that reference the cell see an empty cell, not the pre-merge value.
1389+
For example, suppose our spreadsheet contains
1390+
1391+
![12-01-MergeCells-Options-2.png](./images/12-01-MergeCells-Options-2.png)
1392+
1393+
where `B2` is the formula `=5-B1` and `C2` is the formula `=A2/B2`,
1394+
and we want to merge cells `A2` to `C2` with all the cell values merged.
1395+
The result is:
1396+
1397+
![12-01-MergeCells-Options-3.png](./images/12-01-MergeCells-Options-3.png)
1398+
1399+
The cell value `12` from cell `A2` is fixed; the value from `B2` is the result of the formula `=5-B1` (`4`, which is appended to our merged value), and cell `B2` is then emptied, so when we evaluate cell `C2` with the formula `=A2/B2` it gives us `12 / 0` which results in a `#DIV/0!` error (so the error `#DIV/0!` is appended to our merged value rather than the original calculation result of `3`).
1400+
13511401
## Inserting or Removing rows/columns
13521402

13531403
You can insert/remove rows/columns at a specific position. The following

src/PhpSpreadsheet/Reader/Gnumeric.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ private function processMergedCells(?SimpleXMLElement $sheet): void
363363
if ($sheet !== null && isset($sheet->MergedRegions)) {
364364
foreach ($sheet->MergedRegions->Merge as $mergeCells) {
365365
if (strpos((string) $mergeCells, ':') !== false) {
366-
$this->spreadsheet->getActiveSheet()->mergeCells($mergeCells);
366+
$this->spreadsheet->getActiveSheet()->mergeCells($mergeCells, Worksheet::MERGE_CELL_CONTENT_HIDE);
367367
}
368368
}
369369
}

src/PhpSpreadsheet/Reader/Ods.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use PhpOffice\PhpSpreadsheet\Shared\File;
2121
use PhpOffice\PhpSpreadsheet\Spreadsheet;
2222
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
23+
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
2324
use Throwable;
2425
use XMLReader;
2526
use ZipArchive;
@@ -759,7 +760,7 @@ private function processMergedCells(
759760
}
760761

761762
$cellRange = $columnID . $rowID . ':' . $columnTo . $rowTo;
762-
$spreadsheet->getActiveSheet()->mergeCells($cellRange);
763+
$spreadsheet->getActiveSheet()->mergeCells($cellRange, Worksheet::MERGE_CELL_CONTENT_HIDE);
763764
}
764765
}
765766
}

src/PhpSpreadsheet/Reader/Xls.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4585,7 +4585,7 @@ private function readMergedCells(): void
45854585
(strpos($cellRangeAddress, ':') !== false) &&
45864586
($this->includeCellRangeFiltered($cellRangeAddress))
45874587
) {
4588-
$this->phpSheet->mergeCells($cellRangeAddress);
4588+
$this->phpSheet->mergeCells($cellRangeAddress, Worksheet::MERGE_CELL_CONTENT_HIDE);
45894589
}
45904590
}
45914591
}

src/PhpSpreadsheet/Reader/Xlsx.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
914914
foreach ($xmlSheet->mergeCells->mergeCell as $mergeCell) {
915915
$mergeRef = (string) $mergeCell['ref'];
916916
if (strpos($mergeRef, ':') !== false) {
917-
$docSheet->mergeCells((string) $mergeCell['ref']);
917+
$docSheet->mergeCells((string) $mergeCell['ref'], Worksheet::MERGE_CELL_CONTENT_HIDE);
918918
}
919919
}
920920
}

src/PhpSpreadsheet/Reader/Xml.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use PhpOffice\PhpSpreadsheet\Shared\File;
1919
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
2020
use PhpOffice\PhpSpreadsheet\Spreadsheet;
21+
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
2122
use SimpleXMLElement;
2223

2324
/**
@@ -364,7 +365,7 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet)
364365
$rowTo = $rowTo + $cell_ss['MergeDown'];
365366
}
366367
$cellRange .= ':' . $columnTo . $rowTo;
367-
$spreadsheet->getActiveSheet()->mergeCells($cellRange);
368+
$spreadsheet->getActiveSheet()->mergeCells($cellRange, Worksheet::MERGE_CELL_CONTENT_HIDE);
368369
}
369370

370371
$hasCalculatedValue = false;

0 commit comments

Comments
 (0)