Skip to content

Commit b208c52

Browse files
author
MarkBaker
committed
Fix for setting Active Sheet to the first loaded worksheet when bookViews element isn't defined (e.g. when file is created from Google Sheets)
1 parent 1801f58 commit b208c52

File tree

3 files changed

+156
-79
lines changed

3 files changed

+156
-79
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
3939

4040
### Fixed
4141

42+
- Fix for setting Active Sheet to the first loaded worksheet when bookViews element isn't defined [Issue #2666](https://github.com/PHPOffice/PhpSpreadsheet/issues/2666) [PR #2669](https://github.com/PHPOffice/PhpSpreadsheet/pull/2669)
4243
- Fixed behaviour of XLSX font style vertical align settings.
4344
- Resolved formula translations to handle separators (row and column) for array functions as well as for function argument separators; and cleanly handle nesting levels.
4445

src/PhpSpreadsheet/Reader/Xlsx.php

Lines changed: 2 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\SheetViews;
2121
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Styles;
2222
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Theme;
23+
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\WorkbookView;
2324
use PhpOffice\PhpSpreadsheet\ReferenceHelper;
2425
use PhpOffice\PhpSpreadsheet\RichText\RichText;
2526
use PhpOffice\PhpSpreadsheet\Settings;
@@ -1564,62 +1565,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
15641565
}
15651566
}
15661567

1567-
$workbookView = $xmlWorkbook->children($mainNS)->bookViews->workbookView;
1568-
if ((!$this->readDataOnly || !empty($this->loadSheetsOnly)) && !empty($workbookView)) {
1569-
$workbookViewAttributes = self::testSimpleXml(self::getAttributes($workbookView));
1570-
// active sheet index
1571-
$activeTab = (int) $workbookViewAttributes->activeTab; // refers to old sheet index
1572-
1573-
// keep active sheet index if sheet is still loaded, else first sheet is set as the active
1574-
if (isset($mapSheetId[$activeTab]) && $mapSheetId[$activeTab] !== null) {
1575-
$excel->setActiveSheetIndex($mapSheetId[$activeTab]);
1576-
} else {
1577-
if ($excel->getSheetCount() == 0) {
1578-
$excel->createSheet();
1579-
}
1580-
$excel->setActiveSheetIndex(0);
1581-
}
1582-
1583-
if (isset($workbookViewAttributes->showHorizontalScroll)) {
1584-
$showHorizontalScroll = (string) $workbookViewAttributes->showHorizontalScroll;
1585-
$excel->setShowHorizontalScroll($this->castXsdBooleanToBool($showHorizontalScroll));
1586-
}
1587-
1588-
if (isset($workbookViewAttributes->showVerticalScroll)) {
1589-
$showVerticalScroll = (string) $workbookViewAttributes->showVerticalScroll;
1590-
$excel->setShowVerticalScroll($this->castXsdBooleanToBool($showVerticalScroll));
1591-
}
1592-
1593-
if (isset($workbookViewAttributes->showSheetTabs)) {
1594-
$showSheetTabs = (string) $workbookViewAttributes->showSheetTabs;
1595-
$excel->setShowSheetTabs($this->castXsdBooleanToBool($showSheetTabs));
1596-
}
1597-
1598-
if (isset($workbookViewAttributes->minimized)) {
1599-
$minimized = (string) $workbookViewAttributes->minimized;
1600-
$excel->setMinimized($this->castXsdBooleanToBool($minimized));
1601-
}
1602-
1603-
if (isset($workbookViewAttributes->autoFilterDateGrouping)) {
1604-
$autoFilterDateGrouping = (string) $workbookViewAttributes->autoFilterDateGrouping;
1605-
$excel->setAutoFilterDateGrouping($this->castXsdBooleanToBool($autoFilterDateGrouping));
1606-
}
1607-
1608-
if (isset($workbookViewAttributes->firstSheet)) {
1609-
$firstSheet = (string) $workbookViewAttributes->firstSheet;
1610-
$excel->setFirstSheetIndex((int) $firstSheet);
1611-
}
1612-
1613-
if (isset($workbookViewAttributes->visibility)) {
1614-
$visibility = (string) $workbookViewAttributes->visibility;
1615-
$excel->setVisibility($visibility);
1616-
}
1617-
1618-
if (isset($workbookViewAttributes->tabRatio)) {
1619-
$tabRatio = (string) $workbookViewAttributes->tabRatio;
1620-
$excel->setTabRatio((int) $tabRatio);
1621-
}
1622-
}
1568+
(new WorkbookView($excel))->viewSettings($xmlWorkbook, $mainNS, $mapSheetId, $this->readDataOnly);
16231569

16241570
break;
16251571
}
@@ -1978,29 +1924,6 @@ private function readPrinterSettings(Spreadsheet $excel, $dir, $fileWorksheet, $
19781924
unset($unparsedPrinterSettings);
19791925
}
19801926

1981-
/**
1982-
* Convert an 'xsd:boolean' XML value to a PHP boolean value.
1983-
* A valid 'xsd:boolean' XML value can be one of the following
1984-
* four values: 'true', 'false', '1', '0'. It is case sensitive.
1985-
*
1986-
* Note that just doing '(bool) $xsdBoolean' is not safe,
1987-
* since '(bool) "false"' returns true.
1988-
*
1989-
* @see https://www.w3.org/TR/xmlschema11-2/#boolean
1990-
*
1991-
* @param string $xsdBoolean An XML string value of type 'xsd:boolean'
1992-
*
1993-
* @return bool Boolean value
1994-
*/
1995-
private function castXsdBooleanToBool($xsdBoolean)
1996-
{
1997-
if ($xsdBoolean === 'false') {
1998-
return false;
1999-
}
2000-
2001-
return (bool) $xsdBoolean;
2002-
}
2003-
20041927
private function getWorkbookBaseName(): array
20051928
{
20061929
$workbookBasename = '';
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
<?php
2+
3+
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
4+
5+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
6+
use SimpleXMLElement;
7+
8+
class WorkbookView
9+
{
10+
/**
11+
* @var Spreadsheet
12+
*/
13+
private $spreadsheet;
14+
15+
public function __construct(Spreadsheet $spreadsheet)
16+
{
17+
$this->spreadsheet = $spreadsheet;
18+
}
19+
20+
/**
21+
* @param mixed $mainNS
22+
*/
23+
public function viewSettings(SimpleXMLElement $xmlWorkbook, $mainNS, array $mapSheetId, bool $readDataOnly): void
24+
{
25+
if ($this->spreadsheet->getSheetCount() == 0) {
26+
$this->spreadsheet->createSheet();
27+
}
28+
// Default active sheet index to the first loaded worksheet from the file
29+
$this->spreadsheet->setActiveSheetIndex(0);
30+
31+
$workbookView = $xmlWorkbook->children($mainNS)->bookViews->workbookView;
32+
if (($readDataOnly !== true || !empty($this->loadSheetsOnly)) && !empty($workbookView)) {
33+
$workbookViewAttributes = self::testSimpleXml(self::getAttributes($workbookView));
34+
// active sheet index
35+
$activeTab = (int) $workbookViewAttributes->activeTab; // refers to old sheet index
36+
// keep active sheet index if sheet is still loaded, else first sheet is set as the active worksheet
37+
if (isset($mapSheetId[$activeTab]) && $mapSheetId[$activeTab] !== null) {
38+
$this->spreadsheet->setActiveSheetIndex($mapSheetId[$activeTab]);
39+
}
40+
41+
$this->horizontalScroll($workbookViewAttributes);
42+
$this->verticalScroll($workbookViewAttributes);
43+
$this->sheetTabs($workbookViewAttributes);
44+
$this->minimized($workbookViewAttributes);
45+
$this->autoFilterDateGrouping($workbookViewAttributes);
46+
$this->firstSheet($workbookViewAttributes);
47+
$this->visibility($workbookViewAttributes);
48+
$this->tabRatio($workbookViewAttributes);
49+
}
50+
}
51+
52+
/**
53+
* @param mixed $value
54+
*/
55+
public static function testSimpleXml($value): SimpleXMLElement
56+
{
57+
return ($value instanceof SimpleXMLElement)
58+
? $value
59+
: new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><root></root>');
60+
}
61+
62+
public static function getAttributes(?SimpleXMLElement $value, string $ns = ''): SimpleXMLElement
63+
{
64+
return self::testSimpleXml($value === null ? $value : $value->attributes($ns));
65+
}
66+
67+
/**
68+
* Convert an 'xsd:boolean' XML value to a PHP boolean value.
69+
* A valid 'xsd:boolean' XML value can be one of the following
70+
* four values: 'true', 'false', '1', '0'. It is case sensitive.
71+
*
72+
* Note that just doing '(bool) $xsdBoolean' is not safe,
73+
* since '(bool) "false"' returns true.
74+
*
75+
* @see https://www.w3.org/TR/xmlschema11-2/#boolean
76+
*
77+
* @param string $xsdBoolean An XML string value of type 'xsd:boolean'
78+
*
79+
* @return bool Boolean value
80+
*/
81+
private function castXsdBooleanToBool(string $xsdBoolean): bool
82+
{
83+
if ($xsdBoolean === 'false') {
84+
return false;
85+
}
86+
87+
return (bool) $xsdBoolean;
88+
}
89+
90+
private function horizontalScroll(SimpleXMLElement $workbookViewAttributes): void
91+
{
92+
if (isset($workbookViewAttributes->showHorizontalScroll)) {
93+
$showHorizontalScroll = (string) $workbookViewAttributes->showHorizontalScroll;
94+
$this->spreadsheet->setShowHorizontalScroll($this->castXsdBooleanToBool($showHorizontalScroll));
95+
}
96+
}
97+
98+
private function verticalScroll(SimpleXMLElement $workbookViewAttributes): void
99+
{
100+
if (isset($workbookViewAttributes->showVerticalScroll)) {
101+
$showVerticalScroll = (string) $workbookViewAttributes->showVerticalScroll;
102+
$this->spreadsheet->setShowVerticalScroll($this->castXsdBooleanToBool($showVerticalScroll));
103+
}
104+
}
105+
106+
private function sheetTabs(SimpleXMLElement $workbookViewAttributes): void
107+
{
108+
if (isset($workbookViewAttributes->showSheetTabs)) {
109+
$showSheetTabs = (string) $workbookViewAttributes->showSheetTabs;
110+
$this->spreadsheet->setShowSheetTabs($this->castXsdBooleanToBool($showSheetTabs));
111+
}
112+
}
113+
114+
private function minimized(SimpleXMLElement $workbookViewAttributes): void
115+
{
116+
if (isset($workbookViewAttributes->minimized)) {
117+
$minimized = (string) $workbookViewAttributes->minimized;
118+
$this->spreadsheet->setMinimized($this->castXsdBooleanToBool($minimized));
119+
}
120+
}
121+
122+
private function autoFilterDateGrouping(SimpleXMLElement $workbookViewAttributes): void
123+
{
124+
if (isset($workbookViewAttributes->autoFilterDateGrouping)) {
125+
$autoFilterDateGrouping = (string) $workbookViewAttributes->autoFilterDateGrouping;
126+
$this->spreadsheet->setAutoFilterDateGrouping($this->castXsdBooleanToBool($autoFilterDateGrouping));
127+
}
128+
}
129+
130+
private function firstSheet(SimpleXMLElement $workbookViewAttributes): void
131+
{
132+
if (isset($workbookViewAttributes->firstSheet)) {
133+
$firstSheet = (string) $workbookViewAttributes->firstSheet;
134+
$this->spreadsheet->setFirstSheetIndex((int) $firstSheet);
135+
}
136+
}
137+
138+
private function visibility(SimpleXMLElement $workbookViewAttributes): void
139+
{
140+
if (isset($workbookViewAttributes->visibility)) {
141+
$visibility = (string) $workbookViewAttributes->visibility;
142+
$this->spreadsheet->setVisibility($visibility);
143+
}
144+
}
145+
146+
private function tabRatio(SimpleXMLElement $workbookViewAttributes): void
147+
{
148+
if (isset($workbookViewAttributes->tabRatio)) {
149+
$tabRatio = (string) $workbookViewAttributes->tabRatio;
150+
$this->spreadsheet->setTabRatio((int) $tabRatio);
151+
}
152+
}
153+
}

0 commit comments

Comments
 (0)