Skip to content

Commit

Permalink
Improve PDF Support for Page Size and Orientation (PHPOffice#2410)
Browse files Browse the repository at this point in the history
Fix PHPOffice#1691. PhpSpreadsheet allows the setting of different page size and orientation on each worksheet. It also allows the setting of page size and orientation on the PDF writer. It isn't clear which is supposed to prevail when the two are in conflict. In the cited issue, the user expects the PDF writer setting to prevail, and I tend to agree. Code is changed to do this, and handling things in this manner is now explicitly documented.

PhpSpreadsheet uses a default paper size of Letter, and a default orientation of Default (which Excel treats as Portrait). New static routines are added to change the default for sheets created subsequent to such calls. This could allow users to configure these defaults better for their environments. The new functions are added to the documentation.
  • Loading branch information
oleibman authored Dec 2, 2021
1 parent d5825a6 commit 580c741
Show file tree
Hide file tree
Showing 11 changed files with 234 additions and 121 deletions.
10 changes: 10 additions & 0 deletions docs/topics/reading-and-writing-to-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,16 @@ which sheet to write to PDF:
$writer->setSheetIndex(0);
```

#### Setting Orientation and PaperSize

PhpSpreadsheet will attempt to honor the orientation and paper size specified
in the worksheet for each page it prints, if the renderer supports that. However, you can set all pages
to have the same orientation and paper size, e.g.

```php
$writer->setOrientation(\PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE);
```

#### Formula pre-calculation

By default, this writer pre-calculates all formulas in the spreadsheet.
Expand Down
15 changes: 15 additions & 0 deletions docs/topics/recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,21 @@ $spreadsheet->getActiveSheet()->getPageSetup()
Note that there are additional page settings available. Please refer to
the [API documentation](https://phpoffice.github.io/PhpSpreadsheet) for all possible options.

The default papersize is initially PAPERSIZE_LETTER. However, this default
can be changed for new sheets with the following call:
```php
\PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::setPaperSizeDefault(
\PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::PAPERSIZE_A4
);
```

The default orientation is ORIENTATION_DEFAULT, which will be treated as Portrait in Excel. However, this default can be changed for new sheets with the following call:
```php
\PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::setOrientationDefault(
\PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE
);
```

### Page Setup: Scaling options

The page setup scaling options in PhpSpreadsheet relate directly to the
Expand Down
25 changes: 0 additions & 25 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -6530,11 +6530,6 @@ parameters:
count: 1
path: src/PhpSpreadsheet/Writer/Html.php

-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Html\\:\\:getSheetIndex\\(\\) should return int but returns int\\|null\\.$#"
count: 1
path: src/PhpSpreadsheet/Writer/Html.php

-
message: "#^Parameter \\#1 \\$borderStyle of method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Html\\:\\:mapBorderStyle\\(\\) expects int, string given\\.$#"
count: 1
Expand Down Expand Up @@ -6650,26 +6645,6 @@ parameters:
count: 2
path: src/PhpSpreadsheet/Writer/Ods/Settings.php

-
message: "#^Parameter \\#2 \\$str of function fwrite expects string, string\\|null given\\.$#"
count: 1
path: src/PhpSpreadsheet/Writer/Pdf/Dompdf.php

-
message: "#^Strict comparison using \\=\\=\\= between int and null will always evaluate to false\\.$#"
count: 1
path: src/PhpSpreadsheet/Writer/Pdf/Dompdf.php

-
message: "#^Strict comparison using \\=\\=\\= between null and int will always evaluate to false\\.$#"
count: 1
path: src/PhpSpreadsheet/Writer/Pdf/Mpdf.php

-
message: "#^Strict comparison using \\=\\=\\= between int and null will always evaluate to false\\.$#"
count: 1
path: src/PhpSpreadsheet/Writer/Pdf/Tcpdf.php

-
message: "#^Cannot call method getHashCode\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
count: 1
Expand Down
55 changes: 50 additions & 5 deletions src/PhpSpreadsheet/Worksheet/PageSetup.php
Original file line number Diff line number Diff line change
Expand Up @@ -160,18 +160,32 @@ class PageSetup
const PAGEORDER_DOWN_THEN_OVER = 'downThenOver';

/**
* Paper size.
* Paper size default.
*
* @var int
*/
private $paperSize = self::PAPERSIZE_LETTER;
private static $paperSizeDefault = self::PAPERSIZE_LETTER;

/**
* Paper size.
*
* @var ?int
*/
private $paperSize;

/**
* Orientation default.
*
* @var string
*/
private static $orientationDefault = self::ORIENTATION_DEFAULT;

/**
* Orientation.
*
* @var string
*/
private $orientation = self::ORIENTATION_DEFAULT;
private $orientation;

/**
* Scale (Print Scale).
Expand Down Expand Up @@ -256,6 +270,7 @@ class PageSetup
*/
public function __construct()
{
$this->orientation = self::$orientationDefault;
}

/**
Expand All @@ -265,7 +280,7 @@ public function __construct()
*/
public function getPaperSize()
{
return $this->paperSize;
return $this->paperSize ?? self::$paperSizeDefault;
}

/**
Expand All @@ -282,6 +297,22 @@ public function setPaperSize($paperSize)
return $this;
}

/**
* Get Paper Size default.
*/
public static function getPaperSizeDefault(): int
{
return self::$paperSizeDefault;
}

/**
* Set Paper Size Default.
*/
public static function setPaperSizeDefault(int $paperSize): void
{
self::$paperSizeDefault = $paperSize;
}

/**
* Get Orientation.
*
Expand All @@ -301,11 +332,25 @@ public function getOrientation()
*/
public function setOrientation($orientation)
{
$this->orientation = $orientation;
if ($orientation === self::ORIENTATION_LANDSCAPE || $orientation === self::ORIENTATION_PORTRAIT || $orientation === self::ORIENTATION_DEFAULT) {
$this->orientation = $orientation;
}

return $this;
}

public static function getOrientationDefault(): string
{
return self::$orientationDefault;
}

public static function setOrientationDefault(string $orientation): void
{
if ($orientation === self::ORIENTATION_LANDSCAPE || $orientation === self::ORIENTATION_PORTRAIT || $orientation === self::ORIENTATION_DEFAULT) {
self::$orientationDefault = $orientation;
}
}

/**
* Get Scale.
*
Expand Down
11 changes: 7 additions & 4 deletions src/PhpSpreadsheet/Writer/Html.php
Original file line number Diff line number Diff line change
Expand Up @@ -291,10 +291,8 @@ private function mapBorderStyle($borderStyle)

/**
* Get sheet index.
*
* @return int
*/
public function getSheetIndex()
public function getSheetIndex(): ?int
{
return $this->sheetIndex;
}
Expand Down Expand Up @@ -1784,6 +1782,11 @@ private function writeComment(Worksheet $worksheet, $coordinate)
return $result;
}

public function getOrientation(): ?string
{
return null;
}

/**
* Generate @page declarations.
*
Expand Down Expand Up @@ -1819,7 +1822,7 @@ private function generatePageDeclarations($generateSurroundingHTML)
$htmlPage .= 'margin-top: ' . $top;
$bottom = StringHelper::FormatNumber($worksheet->getPageMargins()->getBottom()) . 'in; ';
$htmlPage .= 'margin-bottom: ' . $bottom;
$orientation = $worksheet->getPageSetup()->getOrientation();
$orientation = $this->getOrientation() ?? $worksheet->getPageSetup()->getOrientation();
if ($orientation === \PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE) {
$htmlPage .= 'size: landscape; ';
} elseif ($orientation === \PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_PORTRAIT) {
Expand Down
10 changes: 4 additions & 6 deletions src/PhpSpreadsheet/Writer/Pdf.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ abstract class Pdf extends Html
/**
* Orientation (Over-ride).
*
* @var string
* @var ?string
*/
protected $orientation;

/**
* Paper size (Over-ride).
*
* @var int
* @var ?int
*/
protected $paperSize;

Expand Down Expand Up @@ -155,7 +155,7 @@ public function setFont($fontName)
/**
* Get Paper Size.
*
* @return int
* @return ?int
*/
public function getPaperSize()
{
Expand All @@ -178,10 +178,8 @@ public function setPaperSize($paperSize)

/**
* Get Orientation.
*
* @return string
*/
public function getOrientation()
public function getOrientation(): ?string
{
return $this->orientation;
}
Expand Down
31 changes: 6 additions & 25 deletions src/PhpSpreadsheet/Writer/Pdf/Dompdf.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,33 +30,14 @@ public function save($filename, int $flags = 0): void
$paperSize = 'LETTER'; // Letter (8.5 in. by 11 in.)

// Check for paper size and page orientation
if ($this->getSheetIndex() === null) {
$orientation = ($this->spreadsheet->getSheet(0)->getPageSetup()->getOrientation()
== PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P';
$printPaperSize = $this->spreadsheet->getSheet(0)->getPageSetup()->getPaperSize();
} else {
$orientation = ($this->spreadsheet->getSheet($this->getSheetIndex())->getPageSetup()->getOrientation()
== PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P';
$printPaperSize = $this->spreadsheet->getSheet($this->getSheetIndex())->getPageSetup()->getPaperSize();
}
$setup = $this->spreadsheet->getSheet($this->getSheetIndex() ?? 0)->getPageSetup();
$orientation = $this->getOrientation() ?? $setup->getOrientation();
$orientation = ($orientation === PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P';
$printPaperSize = $this->getPaperSize() ?? $setup->getPaperSize();
$paperSize = self::$paperSizes[$printPaperSize] ?? PageSetup::getPaperSizeDefault();

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

// Override Page Orientation
if ($this->getOrientation() !== null) {
$orientation = ($this->getOrientation() == PageSetup::ORIENTATION_DEFAULT)
? PageSetup::ORIENTATION_PORTRAIT
: $this->getOrientation();
}
// Override Paper Size
if ($this->getPaperSize() !== null) {
$printPaperSize = $this->getPaperSize();
}

if (isset(self::$paperSizes[$printPaperSize])) {
$paperSize = self::$paperSizes[$printPaperSize];
}

// Create PDF
$pdf = $this->createExternalWriterInstance();
$pdf->setPaper($paperSize, $orientation);
Expand All @@ -65,7 +46,7 @@ public function save($filename, int $flags = 0): void
$pdf->render();

// Write to file
fwrite($fileHandle, $pdf->output());
fwrite($fileHandle, $pdf->output() ?? '');

parent::restoreStateAfterSave();
}
Expand Down
35 changes: 5 additions & 30 deletions src/PhpSpreadsheet/Writer/Pdf/Mpdf.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,37 +28,12 @@ public function save($filename, int $flags = 0): void
{
$fileHandle = parent::prepareForSave($filename);

// Default PDF paper size
$paperSize = 'LETTER'; // Letter (8.5 in. by 11 in.)

// Check for paper size and page orientation
if (null === $this->getSheetIndex()) {
$orientation = ($this->spreadsheet->getSheet(0)->getPageSetup()->getOrientation()
== PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P';
$printPaperSize = $this->spreadsheet->getSheet(0)->getPageSetup()->getPaperSize();
} else {
$orientation = ($this->spreadsheet->getSheet($this->getSheetIndex())->getPageSetup()->getOrientation()
== PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P';
$printPaperSize = $this->spreadsheet->getSheet($this->getSheetIndex())->getPageSetup()->getPaperSize();
}
$this->setOrientation($orientation);

// Override Page Orientation
if (null !== $this->getOrientation()) {
$orientation = ($this->getOrientation() == PageSetup::ORIENTATION_DEFAULT)
? PageSetup::ORIENTATION_PORTRAIT
: $this->getOrientation();
}
$orientation = strtoupper($orientation);

// Override Paper Size
if (null !== $this->getPaperSize()) {
$printPaperSize = $this->getPaperSize();
}

if (isset(self::$paperSizes[$printPaperSize])) {
$paperSize = self::$paperSizes[$printPaperSize];
}
$setup = $this->spreadsheet->getSheet($this->getSheetIndex() ?? 0)->getPageSetup();
$orientation = $this->getOrientation() ?? $setup->getOrientation();
$orientation = ($orientation === PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P';
$printPaperSize = $this->getPaperSize() ?? $setup->getPaperSize();
$paperSize = self::$paperSizes[$printPaperSize] ?? PageSetup::getPaperSizeDefault();

// Create PDF
$config = ['tempDir' => $this->tempDir . '/mpdf'];
Expand Down
32 changes: 6 additions & 26 deletions src/PhpSpreadsheet/Writer/Pdf/Tcpdf.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,32 +46,12 @@ public function save($filename, int $flags = 0): void
$paperSize = 'LETTER'; // Letter (8.5 in. by 11 in.)

// Check for paper size and page orientation
if ($this->getSheetIndex() === null) {
$orientation = ($this->spreadsheet->getSheet(0)->getPageSetup()->getOrientation()
== PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P';
$printPaperSize = $this->spreadsheet->getSheet(0)->getPageSetup()->getPaperSize();
$printMargins = $this->spreadsheet->getSheet(0)->getPageMargins();
} else {
$orientation = ($this->spreadsheet->getSheet($this->getSheetIndex())->getPageSetup()->getOrientation()
== PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P';
$printPaperSize = $this->spreadsheet->getSheet($this->getSheetIndex())->getPageSetup()->getPaperSize();
$printMargins = $this->spreadsheet->getSheet($this->getSheetIndex())->getPageMargins();
}

// Override Page Orientation
if ($this->getOrientation() !== null) {
$orientation = ($this->getOrientation() == PageSetup::ORIENTATION_LANDSCAPE)
? 'L'
: 'P';
}
// Override Paper Size
if ($this->getPaperSize() !== null) {
$printPaperSize = $this->getPaperSize();
}

if (isset(self::$paperSizes[$printPaperSize])) {
$paperSize = self::$paperSizes[$printPaperSize];
}
$setup = $this->spreadsheet->getSheet($this->getSheetIndex() ?? 0)->getPageSetup();
$orientation = $this->getOrientation() ?? $setup->getOrientation();
$orientation = ($orientation === PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P';
$printPaperSize = $this->getPaperSize() ?? $setup->getPaperSize();
$paperSize = self::$paperSizes[$printPaperSize] ?? PageSetup::getPaperSizeDefault();
$printMargins = $this->spreadsheet->getSheet($this->getSheetIndex() ?? 0)->getPageMargins();

// Create PDF
$pdf = $this->createExternalWriterInstance($orientation, 'pt', $paperSize);
Expand Down
Loading

0 comments on commit 580c741

Please sign in to comment.