Skip to content

Commit 42f4d7c

Browse files
committed
Minor Changes to Writer/Mpdf and Writer/Html
Changed a sample to illustrate how to add header/footer in Mpdf using setHtmlEditCallback. This uses custom Html tags, and, like body, it appears that these must be defined in the first writeHtml. Adjust writeMpdf to permit this by using a new constant `SIMULATED_BODY_START`, defined as an Html comment, as a delimiter. Sample 21c_Pdf, to which the header/footer code is added, had been introduced with PR PHPOffice#2434 to ensure that the body tag was always in the first chunk. However, PR PHPOffice#3016 accidentally invalidated that test by reducing the number of style lines so that the sample now included the body tag in its first 1000 records rather than afterwards. This change puts it past record 1000 again. Inspecting the results of all the Html/Pdf samples after this change, it turns out that sample 25_In_memory_image was accidentally broken by PR PHPOffice#3535 - the combination of `max-width:100%` (already present before that change) with `position:absolute` (introduced with that change) made the memory drawing disappear from the rendered html when the image occurs in a column after the last column with data in it. It appears that there is no need for max-width (drawings which are not memory drawings do not use it), so it is dropped. The sample is changed to add a second page with a memory drawing, one page with the memory drawing after the last data column, and one with it before. The Html results now reflect the Xlsx result, as they should.
1 parent ea4f0a2 commit 42f4d7c

File tree

4 files changed

+109
-17
lines changed

4 files changed

+109
-17
lines changed

samples/Basic/25_In_memory_image.php

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@
22

33
use PhpOffice\PhpSpreadsheet\Spreadsheet;
44
use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;
5+
use PhpOffice\PhpSpreadsheet\Writer\Html as HtmlWriter;
6+
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
57

68
require __DIR__ . '/../Header.php';
79

810
// Create new Spreadsheet object
911
$helper->log('Create new Spreadsheet object');
1012
$spreadsheet = new Spreadsheet();
13+
$sheet1 = $spreadsheet->getActiveSheet();
14+
$sheet1->setTitle('SheetWithData');
15+
$sheet1->getCell('G1')->setValue('X');
16+
$sheet1->getCell('E5')->setValue('Y');
17+
$sheet1->getCell('A8')->setValue('Z');
1118

1219
// Set document properties
1320
$helper->log('Set document properties');
@@ -38,8 +45,39 @@
3845
$drawing->setRenderingFunction(MemoryDrawing::RENDERING_JPEG);
3946
$drawing->setMimeType(MemoryDrawing::MIMETYPE_DEFAULT);
4047
$drawing->setHeight(36);
41-
$drawing->setWorksheet($spreadsheet->getActiveSheet());
48+
$drawing->setWorksheet($sheet1);
4249
$drawing->setCoordinates('C5');
4350

51+
$helper->log('Create new sheet');
52+
$sheet2 = $spreadsheet->createSheet();
53+
$sheet2->setTitle('SheetWithoutData');
54+
55+
// Add a drawing to the new worksheet
56+
$helper->log('Add a drawing to the new worksheet');
57+
$drawing = new MemoryDrawing();
58+
$drawing->setName('Sample image');
59+
$drawing->setDescription('Sample image');
60+
$drawing->setImageResource($gdImage);
61+
$drawing->setRenderingFunction(MemoryDrawing::RENDERING_JPEG);
62+
$drawing->setMimeType(MemoryDrawing::MIMETYPE_DEFAULT);
63+
$drawing->setHeight(36);
64+
$drawing->setWorksheet($sheet2);
65+
$drawing->setCoordinates('C5');
66+
67+
/** @param HtmlWriter|XlsxWriter $writer */
68+
function setAllSheetsForHtml($writer): void
69+
{
70+
if (method_exists($writer, 'writeAllSheets')) {
71+
$writer->writeAllSheets();
72+
}
73+
}
74+
4475
// Save
45-
$helper->write($spreadsheet, __FILE__, ['Xlsx', 'Html']);
76+
$helper->write(
77+
$spreadsheet,
78+
__FILE__,
79+
['Xlsx', 'Html'],
80+
false,
81+
'setAllSheetsForHtml'
82+
);
83+
$spreadsheet->disconnectWorksheets();

samples/Pdf/21c_Pdf.php

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,52 @@
22

33
use PhpOffice\PhpSpreadsheet\IOFactory;
44
use PhpOffice\PhpSpreadsheet\Spreadsheet;
5+
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf;
56

67
require __DIR__ . '/../Header.php';
78

89
// Issue 2432 - styles were too large to fit in first Mpdf chunk, causing problems.
10+
11+
function addHeadersFootersMpdf2000(string $html): string
12+
{
13+
$pagerepl = <<<EOF
14+
@page page0 {
15+
odd-header-name: html_myHeader1;
16+
odd-footer-name: html_myFooter2;
17+
18+
EOF;
19+
$html = preg_replace('/@page page0 {/', $pagerepl, $html);
20+
$bodystring = '/<body>/';
21+
$simulatedBodyStart = Mpdf::SIMULATED_BODY_START;
22+
$bodyrepl = <<<EOF
23+
<body>
24+
<htmlpageheader name="myHeader1" style="display:none">
25+
<div style="text-align: right; border-bottom: 1px solid #000000; font-weight: bold; font-size: 10pt;">
26+
My document header
27+
</div>
28+
</htmlpageheader>
29+
30+
<htmlpagefooter name="myFooter2" style="display:none">
31+
<table width="100%">
32+
<tr>
33+
<td width="33%">My document</td>
34+
<td width="33%" align="center">Page {PAGENO} of {nbpg}</td>
35+
<td width="33%" style="text-align: right;">{DATE Y-m-j}</td>
36+
</tr>
37+
</table>
38+
</htmlpagefooter>
39+
$simulatedBodyStart
40+
41+
EOF;
42+
43+
return preg_replace($bodystring, $bodyrepl, $html);
44+
}
45+
946
$spreadsheet = new Spreadsheet();
1047
$sheet = $spreadsheet->getActiveSheet();
1148
$counter = 0;
1249
$helper->log('Populate spreadsheet');
13-
for ($row = 1; $row < 501; ++$row) {
50+
for ($row = 1; $row < 1001; ++$row) {
1451
$sheet->getCell("A$row")->setValue(++$counter);
1552
// Add many styles by using slight variations of font color for each.
1653
$sheet->getCell("A$row")->getStyle()->getFont()->getColor()->setRgb(sprintf('%06x', $counter));
@@ -21,4 +58,13 @@
2158
$helper->log('Write to Mpdf');
2259
IOFactory::registerWriter('Pdf', \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf::class);
2360
$helper->write($spreadsheet, __FILE__, ['Pdf']);
61+
$helper->write(
62+
$spreadsheet,
63+
__FILE__,
64+
['Pdf'],
65+
false,
66+
function (Mpdf $writer): void {
67+
$writer->setEditHtmlCallback('addHeadersFootersMpdf2000');
68+
}
69+
);
2470
$spreadsheet->disconnectWorksheets();

src/PhpSpreadsheet/Writer/Html.php

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,8 @@ public function generateSheetData()
504504
$html .= $startTag;
505505

506506
// Write row if there are HTML table cells in it
507-
if (!isset($this->isSpannedRow[$sheet->getParent()->getIndex($sheet)][$row])) {
507+
$mpdfInvisible = $this->isMPdf && $sheet->getRowDimension($row)->getVisible() === false;
508+
if (!$mpdfInvisible && !isset($this->isSpannedRow[$sheet->getParent()->getIndex($sheet)][$row])) {
508509
// Start a new rowData
509510
$rowData = [];
510511
// Loop through columns
@@ -732,9 +733,14 @@ private function writeImageInCell(Worksheet $worksheet, $coordinates)
732733

733734
// Because of the nature of tables, width is more important than height.
734735
// max-width: 100% ensures that image doesnt overflow containing cell
736+
// However, PR #3535 broke test
737+
// 25_In_memory_image, apparently because
738+
// of the use of max-with. In addition,
739+
// non-memory-drawings don't use max-width.
740+
// Its use here is suspect and is being eliminated.
735741
// width: X sets width of supplied image.
736742
// As a result, images bigger than cell will be contained and images smaller will not get stretched
737-
$html .= '<img alt="' . $filedesc . '" src="' . $dataUri . '" style="max-width:100%;width:' . $drawing->getWidth() . 'px;left: ' .
743+
$html .= '<img alt="' . $filedesc . '" src="' . $dataUri . '" style="width:' . $drawing->getWidth() . 'px;left: ' .
738744
$drawing->getOffsetX() . 'px; top: ' . $drawing->getOffsetY() . 'px;position: absolute; z-index: 1;" />';
739745
}
740746
}
@@ -1498,10 +1504,6 @@ private function generateRow(Worksheet $worksheet, array $values, $row, $cellTyp
14981504
// Sheet index
14991505
$sheetIndex = $worksheet->getParentOrThrow()->getIndex($worksheet);
15001506
$html = $this->generateRowStart($worksheet, $sheetIndex, $row);
1501-
$generateDiv = $this->isMPdf && $worksheet->getRowDimension($row + 1)->getVisible() === false;
1502-
if ($generateDiv) {
1503-
$html .= '<div style="visibility:hidden; display:none;">' . PHP_EOL;
1504-
}
15051507

15061508
// Write cells
15071509
$colNum = 0;
@@ -1546,9 +1548,6 @@ private function generateRow(Worksheet $worksheet, array $values, $row, $cellTyp
15461548
}
15471549

15481550
// Write row end
1549-
if ($generateDiv) {
1550-
$html .= '</div>' . PHP_EOL;
1551-
}
15521551
$html .= ' </tr>' . PHP_EOL;
15531552

15541553
// Return

src/PhpSpreadsheet/Writer/Pdf/Mpdf.php

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
namespace PhpOffice\PhpSpreadsheet\Writer\Pdf;
44

55
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
6-
use PhpOffice\PhpSpreadsheet\Writer\Html;
76
use PhpOffice\PhpSpreadsheet\Writer\Pdf;
87

98
class Mpdf extends Pdf
109
{
10+
public const SIMULATED_BODY_START = '<!-- simulated body start -->';
11+
private const BODY_TAG = '<body>';
12+
1113
/** @var bool */
1214
protected $isMPdf = true;
1315

@@ -61,16 +63,23 @@ public function save($filename, int $flags = 0): void
6163
$pdf->SetCreator($this->spreadsheet->getProperties()->getCreator());
6264

6365
$html = $this->generateHTMLAll();
64-
$bodyLocation = strpos($html, Html::BODY_LINE);
66+
$bodyLocation = strpos($html, self::SIMULATED_BODY_START);
67+
if ($bodyLocation === false) {
68+
$bodyLocation = strpos($html, self::BODY_TAG);
69+
if ($bodyLocation !== false) {
70+
$bodyLocation += strlen(self::BODY_TAG);
71+
}
72+
}
6573
// Make sure first data presented to Mpdf includes body tag
74+
// (and any htmlpageheader/htmlpagefooter tags)
6675
// so that Mpdf doesn't parse it as content. Issue 2432.
6776
if ($bodyLocation !== false) {
68-
$bodyLocation += strlen(Html::BODY_LINE);
6977
$pdf->WriteHTML(substr($html, 0, $bodyLocation));
7078
$html = substr($html, $bodyLocation);
7179
}
72-
foreach (\array_chunk(\explode(PHP_EOL, $html), 1000) as $lines) {
73-
$pdf->WriteHTML(\implode(PHP_EOL, $lines));
80+
$lines = explode("\n", $html);
81+
foreach ($lines as $line) {
82+
$pdf->WriteHTML("$line\n");
7483
}
7584

7685
// Write to file

0 commit comments

Comments
 (0)