Repository: PHPOffice/PhpSpreadsheet (php)

Issue:
PDFWriter produces incorrectly merged cells as soon as some columns are setVisible(false)
This problem was introduced after Version 2.0. I realized it, when updating to  "phpoffice/phpspreadsheet": "3.8.0"

This is a bug report

### What is the expected behavior?
When a column is setVisible(false) I expect the PDF-Writer to still display merged cells correctly.

### What is the current behavior?
When some colums in the spreadsheet are hidden, the phpWriter is not able to correctly format merged cells anymore. 
- Boxing does not work anymore
- Color-Styles (like bold) are not assigned corretly anymore

## Example
This is a screenshot of the generated PDF with column (A) set to **visible**:
```php 
$worksheet->getColumnDimension("A")->setVisible(TRUE); 
```
![image](https://github.com/user-attachments/assets/c05a276c-3dca-4781-baff-aa807353ece7)

---

This is how the same spreadsheet is generated by the PDF-writer, when column A is set to **hidden**:
```php 
$worksheet->getColumnDimension("A")->setVisible(FALSE); 
```
![image](https://github.com/user-attachments/assets/b44e4cdf-7167-4f49-9f6c-94bf3340327e)

---

### What are the steps to reproduce?
- [ ] Install with Composer `"phpoffice/phpspreadsheet": "3.8.0"` and `"mpdf/mpdf": "^8.2"`
- [ ] store the following file as "test.php" and execute it with  `php test.php`

```php
<?php
// filename: test.php

require_once __DIR__ . "vendor/autoload.php";

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Color;
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

$spreadsheet = new Spreadsheet();

$worksheet = $spreadsheet->getActiveSheet();

// just some labels for better visualisation of the problem
$worksheet->setCellValue("A1", "A");
$worksheet->setCellValue("B1", "B");
$worksheet->setCellValue("C1", "C");

// setting the row height to better visualize the problem
for ($i = 1; $i <= 10; $i++) {
	$worksheet->getRowDimension($i)->setRowHeight(17);
}

// Headline - merged over two cells AND two rows
$worksheet->mergeCells("B2:C3");
$worksheet->setCellValue("B2", "Hello World Headline");
$worksheet->getStyle("B2:C3")->getFont()->setBold(TRUE);
$worksheet->getStyle("B2:C3")->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
$worksheet->getStyle("B2:C3")->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN)->setColor(new Color(Color::COLOR_BLACK));

// Content 1 - merge over two rows
$worksheet->mergeCells("B4:B5");
$worksheet->mergeCells("C4:C5");
$worksheet->setCellValue("B4", "Label 1");
$worksheet->setCellValue("C4", "Text 1");
$worksheet->getStyle("B4:B5")->getFont()->setBold(TRUE);
$worksheet->getStyle("B4:C5")->getAlignment()->setVertical(Alignment::VERTICAL_CENTER);
$worksheet->getStyle("B4:B5")->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN)->setColor(new Color(Color::COLOR_BLACK));
$worksheet->getStyle("C4:C5")->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN)->setColor(new Color(Color::COLOR_BLACK));

// Content 2 - merge over two rows
$worksheet->mergeCells("B6:B7");
$worksheet->mergeCells("C6:C7");
$worksheet->setCellValue("B6", "Label 2");
$worksheet->setCellValue("C6", "Text 2");
$worksheet->getStyle("B6:B7")->getFont()->setBold(TRUE);
$worksheet->getStyle("B6:C7")->getAlignment()->setVertical(Alignment::VERTICAL_CENTER);
$worksheet->getStyle("B6:B7")->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN)->setColor(new Color(Color::COLOR_BLACK));
$worksheet->getStyle("C6:C7")->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN)->setColor(new Color(Color::COLOR_BLACK));


// This is where the error is introduced (!!!)
// Uncomment next line to produce correct results
$worksheet->getColumnDimension("A")->setVisible(FALSE);

// Generate PDF
$pdfWriter = new Mpdf($spreadsheet);
$filename  = 'filename_test';
$pdfWriter->writeAllSheets();
$pdfWriter->save($filename . '.pdf');

// Optional: Generate XLSY to compare
$xlsxWriter = new Xlsx($spreadsheet);
$xlsxWriter->save($filename . '.xlsx');
```

- I narrowed it down to this setup to reproduce the error


### What features do you think are causing the issue

- [ ] Reader
- [x] Writer
- [ ] Styles
- [ ] Data Validations
- [ ] Formula Calculations
- [ ] Charts
- [ ] AutoFilter
- [ ] Form Elements

### Does an issue affect all spreadsheet file formats? If not, which formats are affected?
I don't know.

### Which versions of PhpSpreadsheet and PHP are affected?
- This error does not exist in `"phpoffice/phpspreadsheet": "2.0"` ... 
- I tested multiple versions when upgrading and found the error in all the later versions


Pull request:
Mpdf and Tcpdf Hidden Columns and Merged Cells
Fix #4319. PR #3945 allowed Mpdf and Tcpdf to handle hidden rows and columns. The handling is a little off when merged cells are part of the output. The fix for Mpdf is pretty straightforward. Tcpdf is a little more convoluted. Dompdf and Html do not require a change. Unit tests are added for the same scenario for all of Mpdf, Tcpdf, Dompdf, and Html.

This is:

- [x] a bugfix
- [ ] a new feature
- [ ] refactoring
- [ ] additional unit tests

Checklist:

- [ ] Changes are covered by unit tests
  - [ ] Changes are covered by existing unit tests
  - [x] New unit tests have been added
- [x] Code style is respected
- [x] Commit message explains **why** the change is made (see https://github.com/erlang/otp/wiki/Writing-good-commit-messages)
- [ ] CHANGELOG.md contains a short summary of the change and a link to the pull request if applicable
- [ ] Documentation is updated as necessary

### Why this change is needed?

Provide an explanation of why this change is needed, with links to any Issues (if appropriate).
If this is a bugfix or a new feature, and there are no existing Issues, then please also create an issue that will make it easier to track progress with this PR.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f8e1a1399..032bc3160 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
 ### Fixed
 
 - Ods Reader Sheet Names with Period. [Issue #4311](https://github.com/PHPOffice/PhpSpreadsheet/issues/4311) [PR #4313](https://github.com/PHPOffice/PhpSpreadsheet/pull/4313)
+- Mpdf and Tcpdf Hidden Columns and Merged Cells. [Issue #4319](https://github.com/PHPOffice/PhpSpreadsheet/issues/4319) [PR #4320](https://github.com/PHPOffice/PhpSpreadsheet/pull/4320)
 
 ## 2025-01-11 - 3.8.0
 
diff --git a/src/PhpSpreadsheet/Writer/Html.php b/src/PhpSpreadsheet/Writer/Html.php
index 48e845035..5ddabc858 100644
--- a/src/PhpSpreadsheet/Writer/Html.php
+++ b/src/PhpSpreadsheet/Writer/Html.php
@@ -1565,7 +1565,7 @@ class Html extends BaseWriter
     /**
      * Generate row.
      *
-     * @param array $values Array containing cells in a row
+     * @param array<int, mixed> $values Array containing cells in a row
      * @param int $row Row number (0-based)
      * @param string $cellType eg: 'td'
      */
@@ -1577,7 +1577,19 @@ class Html extends BaseWriter
 
         // Write cells
         $colNum = 0;
-        foreach ($values as $cellAddress) {
+        $tcpdfInited = false;
+        foreach ($values as $key => $cellAddress) {
+            if ($this instanceof Pdf\Mpdf) {
+                $colNum = $key - 1;
+            } elseif ($this instanceof Pdf\Tcpdf) {
+                // It appears that Tcpdf requires first cell in tr.
+                $colNum = $key - 1;
+                if (!$tcpdfInited && $key !== 1) {
+                    $tempspan = ($colNum > 1) ? " colspan='$colNum'" : '';
+                    $html .= "<td$tempspan></td>\n";
+                }
+                $tcpdfInited = true;
+            }
             [$cell, $cssClass, $coordinate] = $this->generateRowCellCss($worksheet, $cellAddress, $row, $colNum);
 
             // Cell Data


Test patch:
diff --git a/tests/PhpSpreadsheetTests/Writer/Dompdf/HideMergeTest.php b/tests/PhpSpreadsheetTests/Writer/Dompdf/HideMergeTest.php
new file mode 100644
index 000000000..c27545ea5
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Writer/Dompdf/HideMergeTest.php
@@ -0,0 +1,142 @@
+<?php
+
+declare(strict_types=1);
+
+namespace PhpOffice\PhpSpreadsheetTests\Writer\Dompdf;
+
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+use PhpOffice\PhpSpreadsheet\Style\Alignment;
+use PhpOffice\PhpSpreadsheet\Style\Border;
+use PhpOffice\PhpSpreadsheet\Style\Color;
+use PhpOffice\PhpSpreadsheet\Writer\Pdf\Dompdf;
+use PHPUnit\Framework\TestCase;
+
+class HideMergeTest extends TestCase
+{
+    public function testHideWithMerge(): void
+    {
+        $spreadsheet = new Spreadsheet();
+        $worksheet = $spreadsheet->getActiveSheet();
+        // just some labels for better visualisation of the problem
+        $worksheet->setCellValue('A1', 'A');
+        $worksheet->setCellValue('B1', 'B');
+        $worksheet->setCellValue('C1', 'C');
+        // setting the row height to better visualize the problem
+        for ($i = 1; $i <= 10; ++$i) {
+            $worksheet->getRowDimension($i)->setRowHeight(17);
+        }
+        // Headline - merged over two cells AND two rows
+        $worksheet->mergeCells('B2:C3');
+        $worksheet->setCellValue('B2', 'Hello World Headline');
+        $worksheet->getStyle('B2:C3')->getFont()->setBold(true);
+        $worksheet->getStyle('B2:C3')
+            ->getAlignment()
+            ->setHorizontal(Alignment::HORIZONTAL_CENTER);
+        $worksheet->getStyle('B2:C3')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+
+        // Content 1 - merge over two rows
+        $worksheet->mergeCells('B4:B5');
+        $worksheet->mergeCells('C4:C5');
+        $worksheet->setCellValue('B4', 'Label 1');
+        $worksheet->setCellValue('C4', 'Text 1');
+        $worksheet->getStyle('B4:B5')->getFont()->setBold(true);
+        $worksheet->getStyle('B4:C5')
+            ->getAlignment()
+            ->setVertical(Alignment::VERTICAL_CENTER);
+        $worksheet->getStyle('B4:B5')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+        $worksheet->getStyle('C4:C5')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+
+        // Content 2 - merge over two rows
+        $worksheet->mergeCells('B6:B7');
+        $worksheet->mergeCells('C6:C7');
+        $worksheet->setCellValue('B6', 'Label 2');
+        $worksheet->setCellValue('C6', 'Text 2');
+        $worksheet->getStyle('B6:B7')->getFont()->setBold(true);
+        $worksheet->getStyle('B6:C7')
+            ->getAlignment()
+            ->setVertical(Alignment::VERTICAL_CENTER);
+        $worksheet->getStyle('B6:B7')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+        $worksheet->getStyle('C6:C7')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+
+        // This is where the error was introduced (!!!)
+        $worksheet->getColumnDimension('A')->setVisible(false);
+        $Dompdf = new Dompdf($spreadsheet);
+        $html = $Dompdf->generateHtmlAll();
+        $html = preg_replace('/^\\s+/m', '', $html) ?? $html;
+        $html = preg_replace('/[\\n\\r]/', '', $html) ?? $html;
+        self::assertStringContainsString(
+            'table.sheet0 .column0 { display:none }',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row0">'
+                . '<td class="column0 style0 s" style="width:42pt; height:17pt">A</td>'
+                . '<td class="column1 style0 s" style="width:42pt; height:17pt">B</td>'
+                . '<td class="column2 style0 s" style="width:42pt; height:17pt">C</td>'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row1">'
+                . '<td class="column0 style0" style="width:42pt; height:17pt">&nbsp;</td>'
+                . '<td class="column1 style1 s style1" style="width:84pt; height:17pt" colspan="2" rowspan="2">Hello World Headline</td>'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row2">'
+                . '<td class="column0 style0" style="width:42pt; height:17pt">&nbsp;</td>'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row3">'
+                . '<td class="column0 style0" style="width:42pt; height:17pt">&nbsp;</td>'
+                . '<td class="column1 style2 s style2" style="width:42pt; height:17pt" rowspan="2">Label 1</td>'
+                . '<td class="column2 style3 s style3" style="width:42pt; height:17pt" rowspan="2">Text 1</td>'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row4">'
+                . '<td class="column0 style0" style="width:42pt; height:17pt">&nbsp;</td>'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row5">'
+                . '<td class="column0 style0" style="width:42pt; height:17pt">&nbsp;</td>'
+                . '<td class="column1 style2 s style2" style="width:42pt; height:17pt" rowspan="2">Label 2</td>'
+                . '<td class="column2 style3 s style3" style="width:42pt; height:17pt" rowspan="2">Text 2</td>'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row6">'
+                . '<td class="column0 style0" style="width:42pt; height:17pt">&nbsp;</td>'
+                . '</tr>',
+            $html
+        );
+        $spreadsheet->disconnectWorksheets();
+    }
+}
diff --git a/tests/PhpSpreadsheetTests/Writer/Html/HideMergeTest.php b/tests/PhpSpreadsheetTests/Writer/Html/HideMergeTest.php
new file mode 100644
index 000000000..1075bcca2
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Writer/Html/HideMergeTest.php
@@ -0,0 +1,142 @@
+<?php
+
+declare(strict_types=1);
+
+namespace PhpOffice\PhpSpreadsheetTests\Writer\Html;
+
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+use PhpOffice\PhpSpreadsheet\Style\Alignment;
+use PhpOffice\PhpSpreadsheet\Style\Border;
+use PhpOffice\PhpSpreadsheet\Style\Color;
+use PhpOffice\PhpSpreadsheet\Writer\Html;
+use PHPUnit\Framework\TestCase;
+
+class HideMergeTest extends TestCase
+{
+    public function testHideWithMerge(): void
+    {
+        $spreadsheet = new Spreadsheet();
+        $worksheet = $spreadsheet->getActiveSheet();
+        // just some labels for better visualisation of the problem
+        $worksheet->setCellValue('A1', 'A');
+        $worksheet->setCellValue('B1', 'B');
+        $worksheet->setCellValue('C1', 'C');
+        // setting the row height to better visualize the problem
+        for ($i = 1; $i <= 10; ++$i) {
+            $worksheet->getRowDimension($i)->setRowHeight(17);
+        }
+        // Headline - merged over two cells AND two rows
+        $worksheet->mergeCells('B2:C3');
+        $worksheet->setCellValue('B2', 'Hello World Headline');
+        $worksheet->getStyle('B2:C3')->getFont()->setBold(true);
+        $worksheet->getStyle('B2:C3')
+            ->getAlignment()
+            ->setHorizontal(Alignment::HORIZONTAL_CENTER);
+        $worksheet->getStyle('B2:C3')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+
+        // Content 1 - merge over two rows
+        $worksheet->mergeCells('B4:B5');
+        $worksheet->mergeCells('C4:C5');
+        $worksheet->setCellValue('B4', 'Label 1');
+        $worksheet->setCellValue('C4', 'Text 1');
+        $worksheet->getStyle('B4:B5')->getFont()->setBold(true);
+        $worksheet->getStyle('B4:C5')
+            ->getAlignment()
+            ->setVertical(Alignment::VERTICAL_CENTER);
+        $worksheet->getStyle('B4:B5')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+        $worksheet->getStyle('C4:C5')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+
+        // Content 2 - merge over two rows
+        $worksheet->mergeCells('B6:B7');
+        $worksheet->mergeCells('C6:C7');
+        $worksheet->setCellValue('B6', 'Label 2');
+        $worksheet->setCellValue('C6', 'Text 2');
+        $worksheet->getStyle('B6:B7')->getFont()->setBold(true);
+        $worksheet->getStyle('B6:C7')
+            ->getAlignment()
+            ->setVertical(Alignment::VERTICAL_CENTER);
+        $worksheet->getStyle('B6:B7')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+        $worksheet->getStyle('C6:C7')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+
+        // This is where the error was introduced (!!!)
+        $worksheet->getColumnDimension('A')->setVisible(false);
+        $Dompdf = new Html($spreadsheet);
+        $html = $Dompdf->generateHtmlAll();
+        $html = preg_replace('/^\\s+/m', '', $html) ?? $html;
+        $html = preg_replace('/[\\n\\r]/', '', $html) ?? $html;
+        self::assertStringContainsString(
+            'table.sheet0 .column0 { display:none }',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row0">'
+                . '<td class="column0 style0 s">A</td>'
+                . '<td class="column1 style0 s">B</td>'
+                . '<td class="column2 style0 s">C</td>'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row1">'
+                . '<td class="column0 style0">&nbsp;</td>'
+                . '<td class="column1 style1 s style1" colspan="2" rowspan="2">Hello World Headline</td>'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row2">'
+                . '<td class="column0 style0">&nbsp;</td>'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row3">'
+                . '<td class="column0 style0">&nbsp;</td>'
+                . '<td class="column1 style2 s style2" rowspan="2">Label 1</td>'
+                . '<td class="column2 style3 s style3" rowspan="2">Text 1</td>'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row4">'
+                . '<td class="column0 style0">&nbsp;</td>'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row5">'
+                . '<td class="column0 style0">&nbsp;</td>'
+                . '<td class="column1 style2 s style2" rowspan="2">Label 2</td>'
+                . '<td class="column2 style3 s style3" rowspan="2">Text 2</td>'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row6">'
+                . '<td class="column0 style0">&nbsp;</td>'
+                . '</tr>',
+            $html
+        );
+        $spreadsheet->disconnectWorksheets();
+    }
+}
diff --git a/tests/PhpSpreadsheetTests/Writer/Mpdf/HideMergeTest.php b/tests/PhpSpreadsheetTests/Writer/Mpdf/HideMergeTest.php
new file mode 100644
index 000000000..a3b789d98
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Writer/Mpdf/HideMergeTest.php
@@ -0,0 +1,131 @@
+<?php
+
+declare(strict_types=1);
+
+namespace PhpOffice\PhpSpreadsheetTests\Writer\Mpdf;
+
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+use PhpOffice\PhpSpreadsheet\Style\Alignment;
+use PhpOffice\PhpSpreadsheet\Style\Border;
+use PhpOffice\PhpSpreadsheet\Style\Color;
+use PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf;
+use PHPUnit\Framework\TestCase;
+
+class HideMergeTest extends TestCase
+{
+    public function testHideWithMerge(): void
+    {
+        $spreadsheet = new Spreadsheet();
+        $worksheet = $spreadsheet->getActiveSheet();
+        // just some labels for better visualisation of the problem
+        $worksheet->setCellValue('A1', 'A');
+        $worksheet->setCellValue('B1', 'B');
+        $worksheet->setCellValue('C1', 'C');
+        // setting the row height to better visualize the problem
+        for ($i = 1; $i <= 10; ++$i) {
+            $worksheet->getRowDimension($i)->setRowHeight(17);
+        }
+        // Headline - merged over two cells AND two rows
+        $worksheet->mergeCells('B2:C3');
+        $worksheet->setCellValue('B2', 'Hello World Headline');
+        $worksheet->getStyle('B2:C3')->getFont()->setBold(true);
+        $worksheet->getStyle('B2:C3')
+            ->getAlignment()
+            ->setHorizontal(Alignment::HORIZONTAL_CENTER);
+        $worksheet->getStyle('B2:C3')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+
+        // Content 1 - merge over two rows
+        $worksheet->mergeCells('B4:B5');
+        $worksheet->mergeCells('C4:C5');
+        $worksheet->setCellValue('B4', 'Label 1');
+        $worksheet->setCellValue('C4', 'Text 1');
+        $worksheet->getStyle('B4:B5')->getFont()->setBold(true);
+        $worksheet->getStyle('B4:C5')
+            ->getAlignment()
+            ->setVertical(Alignment::VERTICAL_CENTER);
+        $worksheet->getStyle('B4:B5')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+        $worksheet->getStyle('C4:C5')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+
+        // Content 2 - merge over two rows
+        $worksheet->mergeCells('B6:B7');
+        $worksheet->mergeCells('C6:C7');
+        $worksheet->setCellValue('B6', 'Label 2');
+        $worksheet->setCellValue('C6', 'Text 2');
+        $worksheet->getStyle('B6:B7')->getFont()->setBold(true);
+        $worksheet->getStyle('B6:C7')
+            ->getAlignment()
+            ->setVertical(Alignment::VERTICAL_CENTER);
+        $worksheet->getStyle('B6:B7')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+        $worksheet->getStyle('C6:C7')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+
+        // This is where the error was introduced (!!!)
+        $worksheet->getColumnDimension('A')->setVisible(false);
+        $mpdf = new Mpdf($spreadsheet);
+        $html = $mpdf->generateHtmlAll();
+        $html = preg_replace('/^\\s+/m', '', $html) ?? $html;
+        $html = preg_replace('/[\\n\\r]/', '', $html) ?? $html;
+        self::assertStringContainsString(
+            '<tr class="row0">'
+                . '<td class="column1 style0 s" style="width:42pt; height:17pt">B</td>'
+                . '<td class="column2 style0 s" style="width:42pt; height:17pt">C</td>'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row1">'
+                . '<td class="column1 style1 s style1" style="width:84pt; height:17pt" colspan="2" rowspan="2">Hello World Headline</td>'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row2">'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row3">'
+                . '<td class="column1 style2 s style2" style="width:42pt; height:17pt" rowspan="2">Label 1</td>'
+                . '<td class="column2 style3 s style3" style="width:42pt; height:17pt" rowspan="2">Text 1</td>'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row4">'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row5">'
+                . '<td class="column1 style2 s style2" style="width:42pt; height:17pt" rowspan="2">Label 2</td>'
+                . '<td class="column2 style3 s style3" style="width:42pt; height:17pt" rowspan="2">Text 2</td>'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr class="row6">'
+                . '</tr>',
+            $html
+        );
+        $spreadsheet->disconnectWorksheets();
+    }
+}
diff --git a/tests/PhpSpreadsheetTests/Writer/Tcpdf/HideMergeTest.php b/tests/PhpSpreadsheetTests/Writer/Tcpdf/HideMergeTest.php
new file mode 100644
index 000000000..7b8673489
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Writer/Tcpdf/HideMergeTest.php
@@ -0,0 +1,127 @@
+<?php
+
+declare(strict_types=1);
+
+namespace PhpOffice\PhpSpreadsheetTests\Writer\Tcpdf;
+
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+use PhpOffice\PhpSpreadsheet\Style\Alignment;
+use PhpOffice\PhpSpreadsheet\Style\Border;
+use PhpOffice\PhpSpreadsheet\Style\Color;
+use PhpOffice\PhpSpreadsheet\Writer\Pdf\Tcpdf;
+use PHPUnit\Framework\TestCase;
+
+class HideMergeTest extends TestCase
+{
+    public function testHideWithMerge(): void
+    {
+        $spreadsheet = new Spreadsheet();
+        $worksheet = $spreadsheet->getActiveSheet();
+        // just some labels for better visualisation of the problem
+        $worksheet->setCellValue('A1', 'A');
+        $worksheet->setCellValue('B1', 'B');
+        $worksheet->setCellValue('C1', 'C');
+        // setting the row height to better visualize the problem
+        for ($i = 1; $i <= 10; ++$i) {
+            $worksheet->getRowDimension($i)->setRowHeight(17);
+        }
+        // Headline - merged over two cells AND two rows
+        $worksheet->mergeCells('B2:C3');
+        $worksheet->setCellValue('B2', 'Hello World Headline');
+        $worksheet->getStyle('B2:C3')->getFont()->setBold(true);
+        $worksheet->getStyle('B2:C3')
+            ->getAlignment()
+            ->setHorizontal(Alignment::HORIZONTAL_CENTER);
+        $worksheet->getStyle('B2:C3')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+
+        // Content 1 - merge over two rows
+        $worksheet->mergeCells('B4:B5');
+        $worksheet->mergeCells('C4:C5');
+        $worksheet->setCellValue('B4', 'Label 1');
+        $worksheet->setCellValue('C4', 'Text 1');
+        $worksheet->getStyle('B4:B5')->getFont()->setBold(true);
+        $worksheet->getStyle('B4:C5')
+            ->getAlignment()
+            ->setVertical(Alignment::VERTICAL_CENTER);
+        $worksheet->getStyle('B4:B5')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+        $worksheet->getStyle('C4:C5')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+
+        // Content 2 - merge over two rows
+        $worksheet->mergeCells('B6:B7');
+        $worksheet->mergeCells('C6:C7');
+        $worksheet->setCellValue('B6', 'Label 2');
+        $worksheet->setCellValue('C6', 'Text 2');
+        $worksheet->getStyle('B6:B7')->getFont()->setBold(true);
+        $worksheet->getStyle('B6:C7')
+            ->getAlignment()
+            ->setVertical(Alignment::VERTICAL_CENTER);
+        $worksheet->getStyle('B6:B7')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+        $worksheet->getStyle('C6:C7')
+            ->getBorders()
+            ->getAllBorders()
+            ->setBorderStyle(Border::BORDER_THIN)
+            ->setColor(new Color(Color::COLOR_BLACK));
+
+        // This is where the error was introduced (!!!)
+        $worksheet->getColumnDimension('A')->setVisible(false);
+        $Tcpdf = new Tcpdf($spreadsheet);
+        $html = $Tcpdf->generateHtmlAll();
+        $html = preg_replace('/^\\s+/m', '', $html) ?? $html;
+        $html = preg_replace('/[\\n\\r]/', '', $html) ?? $html;
+        self::assertStringContainsString(
+            '<tbody><tr style="height:17pt">'
+                . '<td></td>'
+                . '<td style="vertical-align:bottom; color:#000000; font-family:\'Calibri\'; font-size:11pt; text-align:left; width:42pt; height:17pt" class="gridlines gridlinesp">B</td>'
+                . '<td style="vertical-align:bottom; color:#000000; font-family:\'Calibri\'; font-size:11pt; text-align:left; width:42pt; height:17pt" class="gridlines gridlinesp">C</td>'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr style="height:17pt">'
+                . '<td></td>'
+                . '<td style="vertical-align:bottom; text-align:center; border-bottom:1px solid #000000 !important; border-top:1px solid #000000 !important; border-left:1px solid #000000 !important; border-right:1px solid #000000 !important; font-weight:bold; color:#000000; font-family:\'Calibri\'; font-size:11pt; width:84pt; height:17pt" class="gridlines gridlinesp" colspan="2" rowspan="2">Hello World Headline</td>'
+                . '</tr>',
+            $html
+        );
+        $emptyRowCount = substr_count(
+            $html,
+            '<tr style="height:17pt">'
+                . '<td></td>'
+                . '</tr>'
+        );
+        self::assertSame(3, $emptyRowCount);
+        self::assertStringContainsString(
+            '<tr style="height:17pt">'
+                . '<td></td>'
+                . '<td style="vertical-align:middle; border-bottom:1px solid #000000 !important; border-top:1px solid #000000 !important; border-left:1px solid #000000 !important; border-right:1px solid #000000 !important; font-weight:bold; color:#000000; font-family:\'Calibri\'; font-size:11pt; text-align:left; width:42pt; height:17pt" class="gridlines gridlinesp" rowspan="2">Label 1</td>'
+                . '<td style="vertical-align:middle; border-bottom:1px solid #000000 !important; border-top:1px solid #000000 !important; border-left:1px solid #000000 !important; border-right:1px solid #000000 !important; color:#000000; font-family:\'Calibri\'; font-size:11pt; text-align:left; width:42pt; height:17pt" class="gridlines gridlinesp" rowspan="2">Text 1</td>'
+                . '</tr>',
+            $html
+        );
+        self::assertStringContainsString(
+            '<tr style="height:17pt">'
+                . '<td></td>'
+                . '<td style="vertical-align:middle; border-bottom:1px solid #000000 !important; border-top:1px solid #000000 !important; border-left:1px solid #000000 !important; border-right:1px solid #000000 !important; font-weight:bold; color:#000000; font-family:\'Calibri\'; font-size:11pt; text-align:left; width:42pt; height:17pt" class="gridlines gridlinesp" rowspan="2">Label 2</td>'
+                . '<td style="vertical-align:middle; border-bottom:1px solid #000000 !important; border-top:1px solid #000000 !important; border-left:1px solid #000000 !important; border-right:1px solid #000000 !important; color:#000000; font-family:\'Calibri\'; font-size:11pt; text-align:left; width:42pt; height:17pt" class="gridlines gridlinesp" rowspan="2">Text 2</td>'
+                . '</tr>',
+            $html
+        );
+        $spreadsheet->disconnectWorksheets();
+    }
+}