Skip to content

Commit 9b07be9

Browse files
committed
Add sheetState to ListWorksheetInfo Data
Fix PHPOffice#4345. Add a new item to the output array. Although the output is changed, this does not seem like a breaking change to me.
1 parent 9d1ad14 commit 9b07be9

23 files changed

+224
-59
lines changed

src/PhpSpreadsheet/Reader/Csv.php

+1
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ public function listWorksheetInfo(string $filename): array
252252

253253
$worksheetInfo[0]['lastColumnLetter'] = Coordinate::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex'] + 1);
254254
$worksheetInfo[0]['totalColumns'] = $worksheetInfo[0]['lastColumnIndex'] + 1;
255+
$worksheetInfo[0]['sheetState'] = Worksheet::SHEETSTATE_VISIBLE;
255256

256257
// Close file
257258
fclose($fileHandle);

src/PhpSpreadsheet/Reader/Gnumeric.php

+10-2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ class Gnumeric extends BaseReader
3333

3434
const NAMESPACE_OOO = 'http://openoffice.org/2004/office';
3535

36+
const GNM_SHEET_VISIBILITY_VISIBLE = 'GNM_SHEET_VISIBILITY_VISIBLE';
37+
const GNM_SHEET_VISIBILITY_HIDDEN = 'GNM_SHEET_VISIBILITY_HIDDEN';
38+
3639
/**
3740
* Shared Expressions.
3841
*/
@@ -144,7 +147,12 @@ public function listWorksheetInfo(string $filename): array
144147
'lastColumnIndex' => 0,
145148
'totalRows' => 0,
146149
'totalColumns' => 0,
150+
'sheetState' => Worksheet::SHEETSTATE_VISIBLE,
147151
];
152+
$visibility = $xml->getAttribute('Visibility');
153+
if ((string) $visibility === self::GNM_SHEET_VISIBILITY_HIDDEN) {
154+
$tmpInfo['sheetState'] = Worksheet::SHEETSTATE_HIDDEN;
155+
}
148156

149157
while ($xml->read()) {
150158
if (self::matchXml($xml, 'Name')) {
@@ -271,8 +279,8 @@ public function loadIntoExisting(string $filename, Spreadsheet $spreadsheet): Sp
271279
// name in line with the formula, not the reverse
272280
$this->spreadsheet->getActiveSheet()->setTitle($worksheetName, false, false);
273281

274-
$visibility = $sheet->attributes()['Visibility'] ?? 'GNM_SHEET_VISIBILITY_VISIBLE';
275-
if ((string) $visibility !== 'GNM_SHEET_VISIBILITY_VISIBLE') {
282+
$visibility = $sheet->attributes()['Visibility'] ?? self::GNM_SHEET_VISIBILITY_VISIBLE;
283+
if ((string) $visibility !== self::GNM_SHEET_VISIBILITY_VISIBLE) {
276284
$this->spreadsheet->getActiveSheet()->setSheetState(Worksheet::SHEETSTATE_HIDDEN);
277285
}
278286

src/PhpSpreadsheet/Reader/Html.php

+1
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,7 @@ public function listWorksheetInfo(string $filename): array
12321232
$newEntry['lastColumnIndex'] = Coordinate::columnIndexFromString($sheet->getHighestDataColumn()) - 1;
12331233
$newEntry['totalRows'] = $sheet->getHighestDataRow();
12341234
$newEntry['totalColumns'] = $newEntry['lastColumnIndex'] + 1;
1235+
$newEntry['sheetState'] = Worksheet::SHEETSTATE_VISIBLE;
12351236
$info[] = $newEntry;
12361237
}
12371238
$spreadsheet->disconnectWorksheets();

src/PhpSpreadsheet/Reader/Ods.php

+56-53
Original file line numberDiff line numberDiff line change
@@ -157,64 +157,67 @@ public function listWorksheetInfo(string $filename): array
157157

158158
// Step into the first level of content of the XML
159159
$xml->read();
160+
$tableVisibility = [];
161+
$lastTableStyle = '';
162+
160163
while ($xml->read()) {
161-
// Quickly jump through to the office:body node
162-
while (self::getXmlName($xml) !== 'office:body') {
163-
if ($xml->isEmptyElement) {
164-
$xml->read();
165-
} else {
166-
$xml->next();
164+
if (self::getXmlName($xml) === 'style:style') {
165+
$styleType = $xml->getAttribute('style:family');
166+
if ($styleType === 'table') {
167+
$lastTableStyle = $xml->getAttribute('style:name');
167168
}
168-
}
169-
// Now read each node until we find our first table:table node
170-
while ($xml->read()) {
171-
if (self::getXmlName($xml) == 'table:table' && $xml->nodeType == XMLReader::ELEMENT) {
172-
$worksheetNames[] = $xml->getAttribute('table:name');
173-
174-
$tmpInfo = [
175-
'worksheetName' => $xml->getAttribute('table:name'),
176-
'lastColumnLetter' => 'A',
177-
'lastColumnIndex' => 0,
178-
'totalRows' => 0,
179-
'totalColumns' => 0,
180-
];
181-
182-
// Loop through each child node of the table:table element reading
183-
$currCells = 0;
184-
do {
169+
} elseif (self::getXmlName($xml) === 'style:table-properties') {
170+
$visibility = $xml->getAttribute('table:display');
171+
$tableVisibility[$lastTableStyle] = ($visibility === 'false') ? Worksheet::SHEETSTATE_HIDDEN : Worksheet::SHEETSTATE_VISIBLE;
172+
} elseif (self::getXmlName($xml) == 'table:table' && $xml->nodeType == XMLReader::ELEMENT) {
173+
$worksheetNames[] = $xml->getAttribute('table:name');
174+
175+
$styleName = $xml->getAttribute('table:style-name') ?? '';
176+
$visibility = $tableVisibility[$styleName] ?? '';
177+
$tmpInfo = [
178+
'worksheetName' => $xml->getAttribute('table:name'),
179+
'lastColumnLetter' => 'A',
180+
'lastColumnIndex' => 0,
181+
'totalRows' => 0,
182+
'totalColumns' => 0,
183+
'sheetState' => $visibility,
184+
];
185+
186+
// Loop through each child node of the table:table element reading
187+
$currCells = 0;
188+
do {
189+
$xml->read();
190+
if (self::getXmlName($xml) == 'table:table-row' && $xml->nodeType == XMLReader::ELEMENT) {
191+
$rowspan = $xml->getAttribute('table:number-rows-repeated');
192+
$rowspan = empty($rowspan) ? 1 : $rowspan;
193+
$tmpInfo['totalRows'] += $rowspan;
194+
$tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells);
195+
$currCells = 0;
196+
// Step into the row
185197
$xml->read();
186-
if (self::getXmlName($xml) == 'table:table-row' && $xml->nodeType == XMLReader::ELEMENT) {
187-
$rowspan = $xml->getAttribute('table:number-rows-repeated');
188-
$rowspan = empty($rowspan) ? 1 : $rowspan;
189-
$tmpInfo['totalRows'] += $rowspan;
190-
$tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells);
191-
$currCells = 0;
192-
// Step into the row
193-
$xml->read();
194-
do {
195-
$doread = true;
196-
if (self::getXmlName($xml) == 'table:table-cell' && $xml->nodeType == XMLReader::ELEMENT) {
197-
if (!$xml->isEmptyElement) {
198-
++$currCells;
199-
$xml->next();
200-
$doread = false;
201-
}
202-
} elseif (self::getXmlName($xml) == 'table:covered-table-cell' && $xml->nodeType == XMLReader::ELEMENT) {
203-
$mergeSize = $xml->getAttribute('table:number-columns-repeated');
204-
$currCells += (int) $mergeSize;
198+
do {
199+
$doread = true;
200+
if (self::getXmlName($xml) == 'table:table-cell' && $xml->nodeType == XMLReader::ELEMENT) {
201+
if (!$xml->isEmptyElement) {
202+
++$currCells;
203+
$xml->next();
204+
$doread = false;
205205
}
206-
if ($doread) {
207-
$xml->read();
208-
}
209-
} while (self::getXmlName($xml) != 'table:table-row');
210-
}
211-
} while (self::getXmlName($xml) != 'table:table');
206+
} elseif (self::getXmlName($xml) == 'table:covered-table-cell' && $xml->nodeType == XMLReader::ELEMENT) {
207+
$mergeSize = $xml->getAttribute('table:number-columns-repeated');
208+
$currCells += (int) $mergeSize;
209+
}
210+
if ($doread) {
211+
$xml->read();
212+
}
213+
} while (self::getXmlName($xml) != 'table:table-row');
214+
}
215+
} while (self::getXmlName($xml) != 'table:table');
212216

213-
$tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells);
214-
$tmpInfo['lastColumnIndex'] = $tmpInfo['totalColumns'] - 1;
215-
$tmpInfo['lastColumnLetter'] = Coordinate::stringFromColumnIndex($tmpInfo['lastColumnIndex'] + 1);
216-
$worksheetInfo[] = $tmpInfo;
217-
}
217+
$tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells);
218+
$tmpInfo['lastColumnIndex'] = $tmpInfo['totalColumns'] - 1;
219+
$tmpInfo['lastColumnLetter'] = Coordinate::stringFromColumnIndex($tmpInfo['lastColumnIndex'] + 1);
220+
$worksheetInfo[] = $tmpInfo;
218221
}
219222
}
220223

src/PhpSpreadsheet/Reader/Slk.php

+1
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ public function listWorksheetInfo(string $filename): array
131131
$worksheetInfo[0]['totalRows'] = $rowIndex;
132132
$worksheetInfo[0]['lastColumnLetter'] = Coordinate::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex'] + 1);
133133
$worksheetInfo[0]['totalColumns'] = $worksheetInfo[0]['lastColumnIndex'] + 1;
134+
$worksheetInfo[0]['sheetState'] = Worksheet::SHEETSTATE_VISIBLE;
134135

135136
// Close file
136137
fclose($fileHandle);

src/PhpSpreadsheet/Reader/Xls/ListFunctions.php

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
66
use PhpOffice\PhpSpreadsheet\Reader\Xls;
77
use PhpOffice\PhpSpreadsheet\Shared\File;
8+
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
89

910
class ListFunctions extends Xls
1011
{
@@ -104,6 +105,7 @@ protected function listWorksheetInfo2(string $filename, Xls $xls): array
104105
$tmpInfo['lastColumnIndex'] = 0;
105106
$tmpInfo['totalRows'] = 0;
106107
$tmpInfo['totalColumns'] = 0;
108+
$tmpInfo['sheetState'] = $sheet['sheetState'];
107109

108110
$xls->pos = $sheet['offset'];
109111

src/PhpSpreadsheet/Reader/Xlsx.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ public function listWorksheetInfo(string $filename): array
238238
'totalRows' => 0,
239239
'totalColumns' => 0,
240240
];
241+
$sheetState = (string) (self::getAttributes($eleSheet)['state'] ?? Worksheet::SHEETSTATE_VISIBLE);
242+
$tmpInfo['sheetState'] = $sheetState;
241243

242244
$fileWorksheet = (string) $worksheets[self::getArrayItemString(self::getAttributes($eleSheet, $namespace), 'id')];
243245
$fileWorksheetPath = str_starts_with($fileWorksheet, '/') ? substr($fileWorksheet, 1) : "$dir/$fileWorksheet";
@@ -257,7 +259,7 @@ public function listWorksheetInfo(string $filename): array
257259
$currCells = 0;
258260
while ($xml->read()) {
259261
if ($xml->localName == 'row' && $xml->nodeType == XMLReader::ELEMENT && $xml->namespaceURI === $mainNS) {
260-
$row = $xml->getAttribute('r');
262+
$row = (int) $xml->getAttribute('r');
261263
$tmpInfo['totalRows'] = $row;
262264
$tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells);
263265
$currCells = 0;

src/PhpSpreadsheet/Reader/Xml.php

+1
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ public function listWorksheetInfo(string $filename): array
229229

230230
$tmpInfo['lastColumnLetter'] = Coordinate::stringFromColumnIndex($tmpInfo['lastColumnIndex'] + 1);
231231
$tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1;
232+
$tmpInfo['sheetState'] = Worksheet::SHEETSTATE_VISIBLE;
232233

233234
$worksheetInfo[] = $tmpInfo;
234235
++$worksheetID;

tests/PhpSpreadsheetTests/Reader/Gnumeric/GnumericInfoTest.php

+2
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,15 @@ public function testListInfo(): void
3232
'lastColumnIndex' => 13,
3333
'totalRows' => 31,
3434
'totalColumns' => 14,
35+
'sheetState' => 'visible',
3536
],
3637
[
3738
'worksheetName' => 'Report Data',
3839
'lastColumnLetter' => 'K',
3940
'lastColumnIndex' => 10,
4041
'totalRows' => 65535,
4142
'totalColumns' => 11,
43+
'sheetState' => 'visible',
4244
],
4345
];
4446
self::assertEquals($expected, $info);

tests/PhpSpreadsheetTests/Reader/Gnumeric/HiddenWorksheetTest.php

+25
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,29 @@ private function worksheetAssertions(): array
4949
],
5050
];
5151
}
52+
53+
public function testListWorksheetInfo(): void
54+
{
55+
$filename = 'tests/data/Reader/Gnumeric/HiddenSheet.gnumeric';
56+
$reader = new Gnumeric();
57+
$expected = [
58+
[
59+
'worksheetName' => 'Sheet1',
60+
'lastColumnLetter' => 'A',
61+
'lastColumnIndex' => 0,
62+
'totalRows' => 1,
63+
'totalColumns' => 1,
64+
'sheetState' => 'visible',
65+
],
66+
[
67+
'worksheetName' => 'Sheet2',
68+
'lastColumnLetter' => 'A',
69+
'lastColumnIndex' => 0,
70+
'totalRows' => 1,
71+
'totalColumns' => 1,
72+
'sheetState' => 'hidden',
73+
],
74+
];
75+
self::assertSame($expected, $reader->listWorksheetInfo($filename));
76+
}
5277
}

tests/PhpSpreadsheetTests/Reader/Ods/HiddenWorksheetTest.php

+26-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class HiddenWorksheetTest extends TestCase
1212
{
1313
public function testPageSetup(): void
1414
{
15-
$filename = 'tests/data/Reader/Ods/HiddenSheet.ods';
15+
$filename = 'tests/data/Reader/Ods/HiddenSheet2.ods';
1616
$reader = new Ods();
1717
$spreadsheet = $reader->load($filename);
1818
$assertions = $this->worksheetAssertions();
@@ -49,4 +49,29 @@ private function worksheetAssertions(): array
4949
],
5050
];
5151
}
52+
53+
public function testListWorksheetInfo(): void
54+
{
55+
$filename = 'tests/data/Reader/Ods/HiddenSheet2.ods';
56+
$reader = new Ods();
57+
$expected = [
58+
[
59+
'worksheetName' => 'Sheet1',
60+
'lastColumnLetter' => 'A',
61+
'lastColumnIndex' => 0,
62+
'totalRows' => 1,
63+
'totalColumns' => 1,
64+
'sheetState' => 'visible',
65+
],
66+
[
67+
'worksheetName' => 'Sheet2',
68+
'lastColumnLetter' => 'A',
69+
'lastColumnIndex' => 0,
70+
'totalRows' => 1,
71+
'totalColumns' => 1,
72+
'sheetState' => 'hidden',
73+
],
74+
];
75+
self::assertSame($expected, $reader->listWorksheetInfo($filename));
76+
}
5277
}

tests/PhpSpreadsheetTests/Reader/Ods/OdsInfoTest.php

+2
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,15 @@ public function testReadFileInfo(): void
7070
'lastColumnIndex' => 2,
7171
'totalRows' => 12,
7272
'totalColumns' => 3,
73+
'sheetState' => 'visible',
7374
],
7475
[
7576
'worksheetName' => 'Second Sheet',
7677
'lastColumnLetter' => 'A',
7778
'lastColumnIndex' => 0,
7879
'totalRows' => 2,
7980
'totalColumns' => 1,
81+
'sheetState' => 'visible',
8082
],
8183
], $wsinfo);
8284
}

tests/PhpSpreadsheetTests/Reader/Xls/HiddenWorksheetTest.php

+41
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,45 @@ private function worksheetAssertions(): array
4949
],
5050
];
5151
}
52+
53+
public function testListWorksheetInfo(): void
54+
{
55+
$filename = 'tests/data/Reader/XLS/visibility.xls';
56+
$reader = new Xls();
57+
$expected = [
58+
[
59+
'worksheetName' => 'Sheet1',
60+
'lastColumnLetter' => 'A',
61+
'lastColumnIndex' => 0,
62+
'totalRows' => 1,
63+
'totalColumns' => 1,
64+
'sheetState' => 'visible',
65+
],
66+
[
67+
'worksheetName' => 'Sheet2',
68+
'lastColumnLetter' => 'A',
69+
'lastColumnIndex' => 0,
70+
'totalRows' => 1,
71+
'totalColumns' => 1,
72+
'sheetState' => 'hidden',
73+
],
74+
[
75+
'worksheetName' => 'Sheet3',
76+
'lastColumnLetter' => 'A',
77+
'lastColumnIndex' => 0,
78+
'totalRows' => 1,
79+
'totalColumns' => 1,
80+
'sheetState' => 'visible',
81+
],
82+
[
83+
'worksheetName' => 'Sheet4',
84+
'lastColumnLetter' => 'A',
85+
'lastColumnIndex' => 0,
86+
'totalRows' => 2,
87+
'totalColumns' => 1,
88+
'sheetState' => 'veryHidden',
89+
],
90+
];
91+
self::assertSame($expected, $reader->listWorksheetInfo($filename));
92+
}
5293
}

tests/PhpSpreadsheetTests/Reader/Xls/InfoNamesTest.php

+4
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,15 @@ public function testWorksheetInfoBiff5(): void
3131
'lastColumnIndex' => 4,
3232
'totalRows' => 19,
3333
'totalColumns' => 5,
34+
'sheetState' => 'visible',
3435
],
3536
[
3637
'worksheetName' => 'Terms and conditions',
3738
'lastColumnLetter' => 'B',
3839
'lastColumnIndex' => 1,
3940
'totalRows' => 3,
4041
'totalColumns' => 2,
42+
'sheetState' => 'visible',
4143
],
4244
];
4345
self::assertSame($expected, $info);
@@ -66,6 +68,7 @@ public function testWorksheetInfoBiff8(): void
6668
'lastColumnIndex' => 1,
6769
'totalRows' => 1,
6870
'totalColumns' => 2,
71+
'sheetState' => 'visible',
6972
],
7073
];
7174
self::assertSame($expected, $info);
@@ -106,6 +109,7 @@ public function testWorksheetInfoBiff5Mac(): void
106109
'lastColumnIndex' => 15,
107110
'totalRows' => 3,
108111
'totalColumns' => 16,
112+
'sheetState' => 'visible',
109113
],
110114
];
111115
self::assertSame($expected, $info);

0 commit comments

Comments
 (0)