diff --git a/CHANGELOG.md b/CHANGELOG.md index fd1a6eb5..74773e34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org). Note that a ChartSheet is still only written as a normal Worksheet containing a single chart, not as an actual ChartSheet. +- Added Worksheet visibility in Ods Reader [PR #2851](https://github.com/PHPOffice/PhpSpreadsheet/pull/2851) - Added Worksheet visibility in Ods Writer [PR #2850](https://github.com/PHPOffice/PhpSpreadsheet/pull/2850) ### Changed @@ -34,7 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org). - Xls Reader resolving absolute named ranges to relative ranges [Issue #2826](https://github.com/PHPOffice/PhpSpreadsheet/issues/2826) [PR #2827](https://github.com/PHPOffice/PhpSpreadsheet/pull/2827) - Null value handling in the Excel Math/Trig PRODUCT() function [Issue #2833](https://github.com/PHPOffice/PhpSpreadsheet/issues/2833) [PR #2834](https://github.com/PHPOffice/PhpSpreadsheet/pull/2834) - +- Invalid Print Area defined in Xlsx corrupts internal storage of print area [Issue #2848](https://github.com/PHPOffice/PhpSpreadsheet/issues/2848) [PR #2849](https://github.com/PHPOffice/PhpSpreadsheet/pull/2849) ## 1.23.0 - 2022-04-24 diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index eabedcc8..ad2777a0 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1945,36 +1945,11 @@ parameters: count: 6 path: src/PhpSpreadsheet/Reader/Ods/PageSettings.php - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\\\PageSettings\\:\\:\\$masterPrintStylesCrossReference has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods/PageSettings.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\\\PageSettings\\:\\:\\$masterStylesCrossReference has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods/PageSettings.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\\\PageSettings\\:\\:\\$officeNs has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods/PageSettings.php - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\\\PageSettings\\:\\:\\$pageLayoutStyles has no type specified\\.$#" count: 1 path: src/PhpSpreadsheet/Reader/Ods/PageSettings.php - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\\\PageSettings\\:\\:\\$stylesFo has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods/PageSettings.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\\\PageSettings\\:\\:\\$stylesNs has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods/PageSettings.php - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\\\Properties\\:\\:load\\(\\) has parameter \\$namespacesMeta with no type specified\\.$#" count: 1 diff --git a/src/PhpSpreadsheet/Reader/Ods.php b/src/PhpSpreadsheet/Reader/Ods.php index 27c58edb..7e776ab7 100644 --- a/src/PhpSpreadsheet/Reader/Ods.php +++ b/src/PhpSpreadsheet/Reader/Ods.php @@ -588,6 +588,7 @@ class Ods extends BaseReader break; } } + $pageSettings->setVisibilityForWorksheet($spreadsheet->getActiveSheet(), $worksheetStyleName); $pageSettings->setPrintSettingsForWorksheet($spreadsheet->getActiveSheet(), $worksheetStyleName); ++$worksheetID; } diff --git a/src/PhpSpreadsheet/Reader/Ods/PageSettings.php b/src/PhpSpreadsheet/Reader/Ods/PageSettings.php index 8d24fd0c..4d2fd992 100644 --- a/src/PhpSpreadsheet/Reader/Ods/PageSettings.php +++ b/src/PhpSpreadsheet/Reader/Ods/PageSettings.php @@ -8,16 +8,41 @@ use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; class PageSettings { + /** + * @var string + */ private $officeNs; + /** + * @var string + */ private $stylesNs; + /** + * @var string + */ private $stylesFo; + /** + * @var string + */ + private $tableNs; + + /** + * @var string[] + */ + private $tableStylesCrossReference = []; + private $pageLayoutStyles = []; + /** + * @var string[] + */ private $masterStylesCrossReference = []; + /** + * @var string[] + */ private $masterPrintStylesCrossReference = []; public function __construct(DOMDocument $styleDom) @@ -32,6 +57,7 @@ class PageSettings $this->officeNs = $styleDom->lookupNamespaceUri('office'); $this->stylesNs = $styleDom->lookupNamespaceUri('style'); $this->stylesFo = $styleDom->lookupNamespaceUri('fo'); + $this->tableNs = $styleDom->lookupNamespaceUri('table'); } private function readPageSettingStyles(DOMDocument $styleDom): void @@ -98,12 +124,33 @@ class PageSettings foreach ($styleXReferences as $styleXreferenceSet) { $styleXRefName = $styleXreferenceSet->getAttributeNS($this->stylesNs, 'name'); $stylePageLayoutName = $styleXreferenceSet->getAttributeNS($this->stylesNs, 'master-page-name'); + $styleFamilyName = $styleXreferenceSet->getAttributeNS($this->stylesNs, 'family'); + if (!empty($styleFamilyName) && $styleFamilyName === 'table') { + $styleVisibility = 'true'; + foreach ($styleXreferenceSet->getElementsByTagNameNS($this->stylesNs, 'table-properties') as $tableProperties) { + $styleVisibility = $tableProperties->getAttributeNS($this->tableNs, 'display'); + } + $this->tableStylesCrossReference[$styleXRefName] = $styleVisibility; + } if (!empty($stylePageLayoutName)) { $this->masterStylesCrossReference[$styleXRefName] = $stylePageLayoutName; } } } + public function setVisibilityForWorksheet(Worksheet $worksheet, string $styleName): void + { + if (!array_key_exists($styleName, $this->tableStylesCrossReference)) { + return; + } + + $worksheet->setSheetState( + $this->tableStylesCrossReference[$styleName] === 'false' + ? Worksheet::SHEETSTATE_HIDDEN + : Worksheet::SHEETSTATE_VISIBLE + ); + } + public function setPrintSettingsForWorksheet(Worksheet $worksheet, string $styleName): void { if (!array_key_exists($styleName, $this->masterStylesCrossReference)) { diff --git a/src/PhpSpreadsheet/Reader/Xlsx.php b/src/PhpSpreadsheet/Reader/Xlsx.php index ecae5ad7..8eadb39c 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx.php +++ b/src/PhpSpreadsheet/Reader/Xlsx.php @@ -1530,13 +1530,18 @@ class Xlsx extends BaseReader $rangeSets = preg_split("/('?(?:.*?)'?(?:![A-Z0-9]+:[A-Z0-9]+)),?/", $extractedRange, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); $newRangeSets = []; foreach ($rangeSets as $rangeSet) { - [$sheetName, $rangeSet] = Worksheet::extractSheetTitle($rangeSet, true); + [, $rangeSet] = Worksheet::extractSheetTitle($rangeSet, true); + if (empty($rangeSet)) { + continue; + } if (strpos($rangeSet, ':') === false) { $rangeSet = $rangeSet . ':' . $rangeSet; } $newRangeSets[] = str_replace('$', '', $rangeSet); } - $docSheet->getPageSetup()->setPrintArea(implode(',', $newRangeSets)); + if (count($newRangeSets) > 0) { + $docSheet->getPageSetup()->setPrintArea(implode(',', $newRangeSets)); + } break; default: diff --git a/tests/PhpSpreadsheetTests/Reader/Ods/HiddenWorksheetTest.php b/tests/PhpSpreadsheetTests/Reader/Ods/HiddenWorksheetTest.php new file mode 100644 index 00000000..9edaa9b7 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Reader/Ods/HiddenWorksheetTest.php @@ -0,0 +1,57 @@ +spreadsheet = $reader->load($filename); + } + + public function testPageSetup(): void + { + $assertions = $this->worksheetAssertions(); + + foreach ($this->spreadsheet->getAllSheets() as $worksheet) { + if (!array_key_exists($worksheet->getTitle(), $assertions)) { + continue; + } + + $sheetAssertions = $assertions[$worksheet->getTitle()]; + foreach ($sheetAssertions as $test => $expectedResult) { + $testMethodName = 'get' . ucfirst($test); + $actualResult = $worksheet->getSheetState(); + self::assertSame( + $expectedResult, + $actualResult, + "Failed asserting sheet state {$expectedResult} for Worksheet '{$worksheet->getTitle()}' {$test}" + ); + } + } + } + + private function worksheetAssertions(): array + { + return [ + 'Sheet1' => [ + 'sheetState' => Worksheet::SHEETSTATE_VISIBLE, + ], + 'Sheet2' => [ + 'sheetState' => Worksheet::SHEETSTATE_HIDDEN, + ], + ]; + } +} diff --git a/tests/data/Reader/Ods/HiddenSheet.ods b/tests/data/Reader/Ods/HiddenSheet.ods new file mode 100644 index 00000000..9b1d01a6 Binary files /dev/null and b/tests/data/Reader/Ods/HiddenSheet.ods differ