Skip to content

Commit 81dd743

Browse files
authored
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.
1 parent 5174a4a commit 81dd743

File tree

3 files changed

+37
-1
lines changed

3 files changed

+37
-1
lines changed

samples/Pdf/21c_Pdf.php

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
4+
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf;
5+
6+
require __DIR__ . '/../Header.php';
7+
8+
// Issue 2432 - styles were too large to fit in first Mpdf chunk, causing problems.
9+
$spreadsheet = new Spreadsheet();
10+
$sheet = $spreadsheet->getActiveSheet();
11+
$counter = 0;
12+
$helper->log('Populate spreadsheet');
13+
for ($row = 1; $row < 501; ++$row) {
14+
$sheet->getCell("A$row")->setValue(++$counter);
15+
// Add many styles by using slight variations of font color for each.
16+
$sheet->getCell("A$row")->getStyle()->getFont()->getColor()->setRgb(sprintf('%06x', $counter));
17+
$sheet->getCell("B$row")->setValue(++$counter);
18+
$sheet->getCell("C$row")->setValue(++$counter);
19+
}
20+
21+
$helper->log('Write to Mpdf');
22+
$writer = new Mpdf($spreadsheet);
23+
$filename = $helper->getFileName('21c_Pdf_mpdf.xlsx', 'pdf');
24+
$writer->save($filename);
25+
$helper->log("Saved $filename");

src/PhpSpreadsheet/Writer/Html.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,8 @@ private static function generateMeta($val, $desc)
354354
: '';
355355
}
356356

357+
public const BODY_LINE = ' <body>' . PHP_EOL;
358+
357359
/**
358360
* Generate HTML header.
359361
*
@@ -384,7 +386,7 @@ public function generateHTMLHeader($includeStyles = false)
384386

385387
$html .= ' </head>' . PHP_EOL;
386388
$html .= '' . PHP_EOL;
387-
$html .= ' <body>' . PHP_EOL;
389+
$html .= self::BODY_LINE;
388390

389391
return $html;
390392
}

src/PhpSpreadsheet/Writer/Pdf/Mpdf.php

+9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace PhpOffice\PhpSpreadsheet\Writer\Pdf;
44

55
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
6+
use PhpOffice\PhpSpreadsheet\Writer\Html;
67
use PhpOffice\PhpSpreadsheet\Writer\Pdf;
78

89
class Mpdf extends Pdf
@@ -57,6 +58,14 @@ public function save($filename, int $flags = 0): void
5758
$pdf->SetCreator($this->spreadsheet->getProperties()->getCreator());
5859

5960
$html = $this->generateHTMLAll();
61+
$bodyLocation = strpos($html, Html::BODY_LINE);
62+
// Make sure first data presented to Mpdf includes body tag
63+
// so that Mpdf doesn't parse it as content. Issue 2432.
64+
if ($bodyLocation !== false) {
65+
$bodyLocation += strlen(Html::BODY_LINE);
66+
$pdf->WriteHTML(substr($html, 0, $bodyLocation));
67+
$html = substr($html, $bodyLocation);
68+
}
6069
foreach (\array_chunk(\explode(PHP_EOL, $html), 1000) as $lines) {
6170
$pdf->WriteHTML(\implode(PHP_EOL, $lines));
6271
}

0 commit comments

Comments
 (0)