Skip to content

Commit 39df9c3

Browse files
authored
Fix Some Pdf Problems (#2960)
* Fix Some Pdf Problems Fix #1747. No support for text rotation in Pdf. That issue actually has a decent workaround, but PhpSpreadsheet should handle it on its own. Mpdf requires the proprietary text-rotate css attribute; Html and Dompdf will use the CSS3 attribute transform:rotate. Fix #1713. Some paper-size values in PhpSpreadsheet are strings, some are 2-element float arrays. Dompdf accepts strings or 4-element float arrays, where the first 2 elements are always 0. Convert the PhpSpreadsheet array accordingly before passing it to Dompdf. Some tests had been disabled when Dompdf and Tcpdf were slow to achieve PHP8 compliance. They achieved it some time ago. Re-enable the tests. * Remove Tcpdf From One Test No problem with the other tests I added it in for.
1 parent e748ac7 commit 39df9c3

File tree

10 files changed

+174
-21
lines changed

10 files changed

+174
-21
lines changed

samples/Basic/26_Utf8.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,10 @@
1212
// at this point, we could do some manipulations with the template, but we skip this step
1313
$helper->write($spreadsheet, __FILE__, ['Xlsx', 'Xls', 'Html']);
1414

15-
if (\PHP_VERSION_ID < 80000) {
16-
// Export to PDF (.pdf)
17-
$helper->log('Write to PDF format');
18-
IOFactory::registerWriter('Pdf', \PhpOffice\PhpSpreadsheet\Writer\Pdf\Dompdf::class);
19-
$helper->write($spreadsheet, __FILE__, ['Pdf']);
20-
}
15+
// Export to PDF (.pdf)
16+
$helper->log('Write to PDF format');
17+
IOFactory::registerWriter('Pdf', \PhpOffice\PhpSpreadsheet\Writer\Pdf\Dompdf::class);
18+
$helper->write($spreadsheet, __FILE__, ['Pdf']);
2119

2220
// Remove first two rows with field headers before exporting to CSV
2321
$helper->log('Removing first two heading rows for CSV export');

samples/Pdf/21b_Pdf.php

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,24 +32,20 @@ function replaceBody(string $html): string
3232
$helper->log('Set orientation to landscape');
3333
$spreadsheet->getActiveSheet()->getPageSetup()->setOrientation(PageSetup::ORIENTATION_LANDSCAPE);
3434

35-
if (\PHP_VERSION_ID < 80000) {
36-
$helper->log('Write to Dompdf');
37-
$writer = new Dompdf($spreadsheet);
38-
$filename = $helper->getFileName('21b_Pdf_dompdf.xlsx', 'pdf');
39-
$writer->setEditHtmlCallback('replaceBody');
40-
$writer->save($filename);
41-
}
35+
$helper->log('Write to Dompdf');
36+
$writer = new Dompdf($spreadsheet);
37+
$filename = $helper->getFileName('21b_Pdf_dompdf.xlsx', 'pdf');
38+
$writer->setEditHtmlCallback('replaceBody');
39+
$writer->save($filename);
4240

4341
$helper->log('Write to Mpdf');
4442
$writer = new Mpdf($spreadsheet);
4543
$filename = $helper->getFileName('21b_Pdf_mpdf.xlsx', 'pdf');
4644
$writer->setEditHtmlCallback('replaceBody');
4745
$writer->save($filename);
4846

49-
if (\PHP_VERSION_ID < 80000) {
50-
$helper->log('Write to Tcpdf');
51-
$writer = new Tcpdf($spreadsheet);
52-
$filename = $helper->getFileName('21b_Pdf_tcpdf.xlsx', 'pdf');
53-
$writer->setEditHtmlCallback('replaceBody');
54-
$writer->save($filename);
55-
}
47+
$helper->log('Write to Tcpdf');
48+
$writer = new Tcpdf($spreadsheet);
49+
$filename = $helper->getFileName('21b_Pdf_tcpdf.xlsx', 'pdf');
50+
$writer->setEditHtmlCallback('replaceBody');
51+
$writer->save($filename);

src/PhpSpreadsheet/Writer/Html.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,13 @@ class Html extends BaseWriter
126126
*/
127127
protected $isPdf = false;
128128

129+
/**
130+
* Is the current writer creating mPDF?
131+
*
132+
* @var bool
133+
*/
134+
protected $isMPdf = false;
135+
129136
/**
130137
* Generate the Navigation block.
131138
*
@@ -1003,6 +1010,14 @@ private function createCSSStyleAlignment(Alignment $alignment)
10031010
$css['padding-' . $textAlign] = (string) ((int) $alignment->getIndent() * 9) . 'px';
10041011
}
10051012
}
1013+
$rotation = $alignment->getTextRotation();
1014+
if ($rotation !== 0 && $rotation !== Alignment::TEXTROTATION_STACK_PHPSPREADSHEET) {
1015+
if ($this->isMPdf) {
1016+
$css['text-rotate'] = "$rotation";
1017+
} else {
1018+
$css['transform'] = "rotate({$rotation}deg)";
1019+
}
1020+
}
10061021

10071022
return $css;
10081023
}

src/PhpSpreadsheet/Writer/Pdf/Dompdf.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ public function save($filename, int $flags = 0): void
3535
$orientation = ($orientation === PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P';
3636
$printPaperSize = $this->getPaperSize() ?? $setup->getPaperSize();
3737
$paperSize = self::$paperSizes[$printPaperSize] ?? PageSetup::getPaperSizeDefault();
38+
if (is_array($paperSize) && count($paperSize) === 2) {
39+
$paperSize = [0.0, 0.0, $paperSize[0], $paperSize[1]];
40+
}
3841

3942
$orientation = ($orientation == 'L') ? 'landscape' : 'portrait';
4043

src/PhpSpreadsheet/Writer/Pdf/Mpdf.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
class Mpdf extends Pdf
1010
{
11+
/** @var bool */
12+
protected $isMPdf = true;
13+
1114
/**
1215
* Gets the implementation of external PDF library that should be used.
1316
*

tests/PhpSpreadsheetTests/Functional/StreamTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@ public function providerFormats(): array
1717
['Csv'],
1818
['Html'],
1919
['Mpdf'],
20+
['Dompdf'],
2021
];
2122

2223
if (\PHP_VERSION_ID < 80000) {
2324
$providerFormats = array_merge(
2425
$providerFormats,
25-
[['Tcpdf'], ['Dompdf']]
26+
[['Tcpdf']]
2627
);
2728
}
2829

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
namespace PhpOffice\PhpSpreadsheetTests\Writer\Dompdf;
4+
5+
use PhpOffice\PhpSpreadsheet\Shared\File;
6+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
7+
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
8+
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Dompdf;
9+
use PHPUnit\Framework\TestCase;
10+
11+
class PaperSizeArrayTest extends TestCase
12+
{
13+
/** @var string */
14+
private $outfile = '';
15+
16+
protected function tearDown(): void
17+
{
18+
if ($this->outfile !== '') {
19+
unlink($this->outfile);
20+
$this->outfile = '';
21+
}
22+
}
23+
24+
public function testPaperSizeArray(): void
25+
{
26+
// Issue 1713 - array in PhpSpreadsheet is 2 elements,
27+
// but in Dompdf it is 4 elements, first 2 are zero.
28+
$spreadsheet = new Spreadsheet();
29+
$sheet = $spreadsheet->getActiveSheet();
30+
// TABLOID is a 2-element array in Writer/Pdf.php $paperSizes
31+
$size = PageSetup::PAPERSIZE_TABLOID;
32+
$sheet->getPageSetup()->setPaperSize($size);
33+
$sheet->setPrintGridlines(true);
34+
$sheet->getStyle('A7')->getAlignment()->setTextRotation(90);
35+
$sheet->setCellValue('A7', 'Lorem Ipsum');
36+
$writer = new Dompdf($spreadsheet);
37+
$this->outfile = File::temporaryFilename();
38+
$writer->save($this->outfile);
39+
$spreadsheet->disconnectWorksheets();
40+
unset($spreadsheet);
41+
$contents = file_get_contents($this->outfile);
42+
self::assertNotFalse($contents);
43+
self::assertStringContainsString('/MediaBox [0.000 0.000 792.000 1224.000]', $contents);
44+
}
45+
46+
public function testPaperSizeNotArray(): void
47+
{
48+
$spreadsheet = new Spreadsheet();
49+
$sheet = $spreadsheet->getActiveSheet();
50+
// LETTER is a string in Writer/Pdf.php $paperSizes
51+
$size = PageSetup::PAPERSIZE_LETTER;
52+
$sheet->getPageSetup()->setPaperSize($size);
53+
$sheet->setPrintGridlines(true);
54+
$sheet->getStyle('A7')->getAlignment()->setTextRotation(90);
55+
$sheet->setCellValue('A7', 'Lorem Ipsum');
56+
$writer = new Dompdf($spreadsheet);
57+
$this->outfile = File::temporaryFilename();
58+
$writer->save($this->outfile);
59+
$spreadsheet->disconnectWorksheets();
60+
unset($spreadsheet);
61+
$contents = file_get_contents($this->outfile);
62+
self::assertNotFalse($contents);
63+
self::assertStringContainsString('/MediaBox [0.000 0.000 612.000 792.000]', $contents);
64+
}
65+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace PhpOffice\PhpSpreadsheetTests\Writer\Dompdf;
4+
5+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
6+
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Dompdf;
7+
use PHPUnit\Framework\TestCase;
8+
9+
class TextRotationTest extends TestCase
10+
{
11+
public function testTextRotation(): void
12+
{
13+
$spreadsheet = new Spreadsheet();
14+
$sheet = $spreadsheet->getActiveSheet();
15+
$sheet->setPrintGridlines(true);
16+
$sheet->getStyle('A7')->getAlignment()->setTextRotation(90);
17+
$sheet->setCellValue('A7', 'Lorem Ipsum');
18+
$writer = new Dompdf($spreadsheet);
19+
$html = $writer->generateHtmlAll();
20+
self::assertStringContainsString(' transform:rotate(90deg);', $html);
21+
$spreadsheet->disconnectWorksheets();
22+
unset($spreadsheet);
23+
}
24+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace PhpOffice\PhpSpreadsheetTests\Writer\Html;
4+
5+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
6+
use PhpOffice\PhpSpreadsheet\Writer\Html;
7+
use PHPUnit\Framework\TestCase;
8+
9+
class TextRotationTest extends TestCase
10+
{
11+
public function testTextRotation(): void
12+
{
13+
$spreadsheet = new Spreadsheet();
14+
$sheet = $spreadsheet->getActiveSheet();
15+
$sheet->setPrintGridlines(true);
16+
$sheet->getStyle('A7')->getAlignment()->setTextRotation(90);
17+
$sheet->setCellValue('A7', 'Lorem Ipsum');
18+
$writer = new Html($spreadsheet);
19+
$html = $writer->generateHtmlAll();
20+
self::assertStringContainsString(' transform:rotate(90deg);', $html);
21+
$spreadsheet->disconnectWorksheets();
22+
unset($spreadsheet);
23+
}
24+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace PhpOffice\PhpSpreadsheetTests\Writer\Mpdf;
4+
5+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
6+
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf;
7+
use PHPUnit\Framework\TestCase;
8+
9+
class TextRotationTest extends TestCase
10+
{
11+
public function testTextRotation(): void
12+
{
13+
$spreadsheet = new Spreadsheet();
14+
$sheet = $spreadsheet->getActiveSheet();
15+
$sheet->setPrintGridlines(true);
16+
$sheet->getStyle('A7')->getAlignment()->setTextRotation(90);
17+
$sheet->setCellValue('A7', 'Lorem Ipsum');
18+
$writer = new Mpdf($spreadsheet);
19+
$html = $writer->generateHtmlAll();
20+
self::assertStringContainsString(' text-rotate:90;', $html);
21+
$spreadsheet->disconnectWorksheets();
22+
unset($spreadsheet);
23+
}
24+
}

0 commit comments

Comments
 (0)