From 81dd743d3f237db1267e8be74f114a8e45b72b82 Mon Sep 17 00:00:00 2001 From: oleibman Date: Tue, 7 Dec 2021 10:46:21 -0800 Subject: [PATCH] Mpdf With Very Many Styles (#2434) Fix #2432. Probably for memory reasons, PhpSpreadsheet divides its data into chunks when writing to Mpdf. However, if the first chunk has so many styles that the `body` tag is not included in the chunk, Mpdf will not handle it correctly. Code is changed to ensure that the first chunk always contains the body tag. Because this error becomes evident only when opening the PDF file itself, it is difficult to write a test case. I have instead added a new sample file which meets the conditions which would have led to the error, and which can be examined to show that it is created correctly. --- samples/Pdf/21c_Pdf.php | 25 +++++++++++++++++++++++++ src/PhpSpreadsheet/Writer/Html.php | 4 +++- src/PhpSpreadsheet/Writer/Pdf/Mpdf.php | 9 +++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 samples/Pdf/21c_Pdf.php diff --git a/samples/Pdf/21c_Pdf.php b/samples/Pdf/21c_Pdf.php new file mode 100644 index 00000000..6fe12664 --- /dev/null +++ b/samples/Pdf/21c_Pdf.php @@ -0,0 +1,25 @@ +getActiveSheet(); +$counter = 0; +$helper->log('Populate spreadsheet'); +for ($row = 1; $row < 501; ++$row) { + $sheet->getCell("A$row")->setValue(++$counter); + // Add many styles by using slight variations of font color for each. + $sheet->getCell("A$row")->getStyle()->getFont()->getColor()->setRgb(sprintf('%06x', $counter)); + $sheet->getCell("B$row")->setValue(++$counter); + $sheet->getCell("C$row")->setValue(++$counter); +} + +$helper->log('Write to Mpdf'); +$writer = new Mpdf($spreadsheet); +$filename = $helper->getFileName('21c_Pdf_mpdf.xlsx', 'pdf'); +$writer->save($filename); +$helper->log("Saved $filename"); diff --git a/src/PhpSpreadsheet/Writer/Html.php b/src/PhpSpreadsheet/Writer/Html.php index d0266cc5..9169d43b 100644 --- a/src/PhpSpreadsheet/Writer/Html.php +++ b/src/PhpSpreadsheet/Writer/Html.php @@ -354,6 +354,8 @@ class Html extends BaseWriter : ''; } + public const BODY_LINE = ' ' . PHP_EOL; + /** * Generate HTML header. * @@ -384,7 +386,7 @@ class Html extends BaseWriter $html .= ' ' . PHP_EOL; $html .= '' . PHP_EOL; - $html .= ' ' . PHP_EOL; + $html .= self::BODY_LINE; return $html; } diff --git a/src/PhpSpreadsheet/Writer/Pdf/Mpdf.php b/src/PhpSpreadsheet/Writer/Pdf/Mpdf.php index 96067dbb..281e1a4f 100644 --- a/src/PhpSpreadsheet/Writer/Pdf/Mpdf.php +++ b/src/PhpSpreadsheet/Writer/Pdf/Mpdf.php @@ -3,6 +3,7 @@ namespace PhpOffice\PhpSpreadsheet\Writer\Pdf; use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup; +use PhpOffice\PhpSpreadsheet\Writer\Html; use PhpOffice\PhpSpreadsheet\Writer\Pdf; class Mpdf extends Pdf @@ -57,6 +58,14 @@ class Mpdf extends Pdf $pdf->SetCreator($this->spreadsheet->getProperties()->getCreator()); $html = $this->generateHTMLAll(); + $bodyLocation = strpos($html, Html::BODY_LINE); + // Make sure first data presented to Mpdf includes body tag + // so that Mpdf doesn't parse it as content. Issue 2432. + if ($bodyLocation !== false) { + $bodyLocation += strlen(Html::BODY_LINE); + $pdf->WriteHTML(substr($html, 0, $bodyLocation)); + $html = substr($html, $bodyLocation); + } foreach (\array_chunk(\explode(PHP_EOL, $html), 1000) as $lines) { $pdf->WriteHTML(\implode(PHP_EOL, $lines)); }