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.
This commit is contained in:
oleibman 2021-12-07 10:46:21 -08:00 committed by GitHub
parent 5174a4ab15
commit 81dd743d3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 1 deletions

25
samples/Pdf/21c_Pdf.php Normal file
View File

@ -0,0 +1,25 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf;
require __DIR__ . '/../Header.php';
// Issue 2432 - styles were too large to fit in first Mpdf chunk, causing problems.
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->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");

View File

@ -354,6 +354,8 @@ class Html extends BaseWriter
: '';
}
public const BODY_LINE = ' <body>' . PHP_EOL;
/**
* Generate HTML header.
*
@ -384,7 +386,7 @@ class Html extends BaseWriter
$html .= ' </head>' . PHP_EOL;
$html .= '' . PHP_EOL;
$html .= ' <body>' . PHP_EOL;
$html .= self::BODY_LINE;
return $html;
}

View File

@ -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));
}