Skip to content

Commit 4a2b731

Browse files
committed
Pdf Charts and Drawings
Fix #4129. Fix #4168. Html Writer, which all the Pdf writers use, defines its charts and drawings (henceforth I will just use charts for this discussion) using position:absolute and z-index. Browsers handle this correctly, but none of the Pdf writers do, and I can't think of an alternative method of styling them. The result is that the charts take up too much or too little room on the Pdf. I suggested in the two discussions that treating the areas covered by the charts as merged cells might mitigate the problem. I think there are too many unknowns to do so automatically (and see next paragraph). However, adding to Spreadsheet new methods `mergeChartCellsForPdf` and `mergeDrawingCellsForPdf` allows the end user to do this if desired. The new methods are exercised for charts in samples/Chart/32_Chart_read_write_PDF, the results of which are much improved as a result. New samples/Pdf/21f_Drawing_mpdf does likewise for drawings. The new methods alter the spreadsheet they are working on, which could be a problem if you still wish to work with the spreadsheet after writing it to Pdf. In that case, making a copy of the spreadsheet, then calling the new methods on the copy, and writing the copy to Pdf is probably best.
1 parent fb757cf commit 4a2b731

File tree

3 files changed

+101
-0
lines changed

3 files changed

+101
-0
lines changed

samples/Chart/32_Chart_read_write_PDF.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
$reader->setIncludeCharts(true);
3838
$spreadsheet = $reader->load($inputFileName);
3939

40+
$helper->log('Merge chart cells (needed only for Pdf)');
41+
$spreadsheet->mergeChartCellsForPdf();
42+
4043
$helper->log('Iterate worksheets looking at the charts');
4144
foreach ($spreadsheet->getWorksheetIterator() as $worksheet) {
4245
$sheetName = $worksheet->getTitle();

samples/Pdf/21f_Drawing_mpdf.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
4+
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
5+
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf;
6+
7+
require __DIR__ . '/../Header.php';
8+
require_once __DIR__ . '/Mpdf2.php';
9+
10+
$spreadsheet = new Spreadsheet();
11+
$sheet = $spreadsheet->getActiveSheet();
12+
13+
$sheet->getCell('A1')->setValue('A1');
14+
$sheet->getCell('B1')->setValue('B');
15+
$sheet->getCell('C1')->setValue('C');
16+
$sheet->getCell('D1')->setValue('D');
17+
$sheet->getCell('E1')->setValue('E');
18+
$sheet->getCell('F1')->setValue('F');
19+
$sheet->getCell('G1')->setValue('G');
20+
$sheet->getCell('A2')->setValue('A2');
21+
$sheet->getCell('A3')->setValue('A3');
22+
$sheet->getCell('A4')->setValue('A4');
23+
$sheet->getCell('A5')->setValue('A5');
24+
$sheet->getCell('A6')->setValue('A6');
25+
$sheet->getCell('A7')->setValue('A7');
26+
$sheet->getCell('A8')->setValue('A8');
27+
28+
$helper->log('Add drawing to worksheet');
29+
$drawing = new Drawing();
30+
$drawing->setName('Blue Square');
31+
$path = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'images/blue_square.png';
32+
$drawing->setPath($path);
33+
$drawing->setResizeProportional(false);
34+
$drawing->setWidth(320);
35+
$drawing->setCoordinates('B2');
36+
$drawing->setCoordinates2('G6');
37+
$drawing->setWorksheet($sheet, true);
38+
39+
$helper->log('Merge drawing cells for Pdf');
40+
$spreadsheet->mergeDrawingCellsForPdf();
41+
42+
$helper->log('Write to Mpdf');
43+
$writer = new Mpdf($spreadsheet);
44+
$filename = $helper->getFileName(__FILE__, 'pdf');
45+
$writer->save($filename);
46+
$helper->log("Saved $filename");
47+
if (PHP_SAPI !== 'cli') {
48+
echo '<a href="/download.php?type=pdf&name=' . basename($filename) . '">Download ' . basename($filename) . '</a><br />';
49+
}
50+
$spreadsheet->disconnectWorksheets();

src/PhpSpreadsheet/Spreadsheet.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,4 +1610,52 @@ public function setValueBinder(?IValueBinder $valueBinder): self
16101610

16111611
return $this;
16121612
}
1613+
1614+
/**
1615+
* All the PDF writers treat charts as if they occupy a single cell.
1616+
* This will be better most of the time.
1617+
* It is not needed for any other output type.
1618+
* It changes the contents of the spreadsheet, so you might
1619+
* be better off cloning the spreadsheet and then using
1620+
* this method on, and then writing, the clone.
1621+
*/
1622+
public function mergeChartCellsForPdf(): void
1623+
{
1624+
foreach ($this->workSheetCollection as $worksheet) {
1625+
foreach ($worksheet->getChartCollection() as $chart) {
1626+
$br = $chart->getBottomRightCell();
1627+
$tl = $chart->getTopLeftCell();
1628+
if ($br !== '' && $br !== $tl) {
1629+
if (!$worksheet->cellExists($br)) {
1630+
$worksheet->getCell($br)->setValue(' ');
1631+
}
1632+
$worksheet->mergeCells("$tl:$br");
1633+
}
1634+
}
1635+
}
1636+
}
1637+
1638+
/**
1639+
* All the PDF writers do better with drawings than charts.
1640+
* This will be better some of the time.
1641+
* It is not needed for any other output type.
1642+
* It changes the contents of the spreadsheet, so you might
1643+
* be better off cloning the spreadsheet and then using
1644+
* this method on, and then writing, the clone.
1645+
*/
1646+
public function mergeDrawingCellsForPdf(): void
1647+
{
1648+
foreach ($this->workSheetCollection as $worksheet) {
1649+
foreach ($worksheet->getDrawingCollection() as $drawing) {
1650+
$br = $drawing->getCoordinates2();
1651+
$tl = $drawing->getCoordinates();
1652+
if ($br !== '' && $br !== $tl) {
1653+
if (!$worksheet->cellExists($br)) {
1654+
$worksheet->getCell($br)->setValue(' ');
1655+
}
1656+
$worksheet->mergeCells("$tl:$br");
1657+
}
1658+
}
1659+
}
1660+
}
16131661
}

0 commit comments

Comments
 (0)