Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mpdf and Tcpdf Hidden Columns and Merged Cells #4320

Merged
merged 3 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
16 changes: 14 additions & 2 deletions src/PhpSpreadsheet/Writer/Html.php
Original file line number Diff line number Diff line change
Expand Up @@ -1565,7 +1565,7 @@ private function generateRowWriteCell(
/**
* 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'
*/
Expand All @@ -1577,7 +1577,19 @@ private function generateRow(Worksheet $worksheet, array $values, int $row, stri

// 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
Expand Down
142 changes: 142 additions & 0 deletions tests/PhpSpreadsheetTests/Writer/Dompdf/HideMergeTest.php
Original file line number Diff line number Diff line change
@@ -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();
}
}
142 changes: 142 additions & 0 deletions tests/PhpSpreadsheetTests/Writer/Html/HideMergeTest.php
Original file line number Diff line number Diff line change
@@ -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();
}
}
Loading
Loading