Add sheetState to ListWorksheetInfo Data

Fix #4345. Add a new item to the output array. Although the output is changed, this does not seem like a breaking change to me.
This commit is contained in:
oleibman
2025-02-14 23:40:50 -08:00
parent 9d1ad14a48
commit 9b07be9a0f
23 changed files with 224 additions and 59 deletions
+1
View File
@@ -252,6 +252,7 @@ class Csv extends BaseReader
$worksheetInfo[0]['lastColumnLetter'] = Coordinate::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex'] + 1); $worksheetInfo[0]['lastColumnLetter'] = Coordinate::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex'] + 1);
$worksheetInfo[0]['totalColumns'] = $worksheetInfo[0]['lastColumnIndex'] + 1; $worksheetInfo[0]['totalColumns'] = $worksheetInfo[0]['lastColumnIndex'] + 1;
$worksheetInfo[0]['sheetState'] = Worksheet::SHEETSTATE_VISIBLE;
// Close file // Close file
fclose($fileHandle); fclose($fileHandle);
+10 -2
View File
@@ -33,6 +33,9 @@ class Gnumeric extends BaseReader
const NAMESPACE_OOO = 'http://openoffice.org/2004/office'; const NAMESPACE_OOO = 'http://openoffice.org/2004/office';
const GNM_SHEET_VISIBILITY_VISIBLE = 'GNM_SHEET_VISIBILITY_VISIBLE';
const GNM_SHEET_VISIBILITY_HIDDEN = 'GNM_SHEET_VISIBILITY_HIDDEN';
/** /**
* Shared Expressions. * Shared Expressions.
*/ */
@@ -144,7 +147,12 @@ class Gnumeric extends BaseReader
'lastColumnIndex' => 0, 'lastColumnIndex' => 0,
'totalRows' => 0, 'totalRows' => 0,
'totalColumns' => 0, 'totalColumns' => 0,
'sheetState' => Worksheet::SHEETSTATE_VISIBLE,
]; ];
$visibility = $xml->getAttribute('Visibility');
if ((string) $visibility === self::GNM_SHEET_VISIBILITY_HIDDEN) {
$tmpInfo['sheetState'] = Worksheet::SHEETSTATE_HIDDEN;
}
while ($xml->read()) { while ($xml->read()) {
if (self::matchXml($xml, 'Name')) { if (self::matchXml($xml, 'Name')) {
@@ -271,8 +279,8 @@ class Gnumeric extends BaseReader
// name in line with the formula, not the reverse // name in line with the formula, not the reverse
$this->spreadsheet->getActiveSheet()->setTitle($worksheetName, false, false); $this->spreadsheet->getActiveSheet()->setTitle($worksheetName, false, false);
$visibility = $sheet->attributes()['Visibility'] ?? 'GNM_SHEET_VISIBILITY_VISIBLE'; $visibility = $sheet->attributes()['Visibility'] ?? self::GNM_SHEET_VISIBILITY_VISIBLE;
if ((string) $visibility !== 'GNM_SHEET_VISIBILITY_VISIBLE') { if ((string) $visibility !== self::GNM_SHEET_VISIBILITY_VISIBLE) {
$this->spreadsheet->getActiveSheet()->setSheetState(Worksheet::SHEETSTATE_HIDDEN); $this->spreadsheet->getActiveSheet()->setSheetState(Worksheet::SHEETSTATE_HIDDEN);
} }
+1
View File
@@ -1232,6 +1232,7 @@ class Html extends BaseReader
$newEntry['lastColumnIndex'] = Coordinate::columnIndexFromString($sheet->getHighestDataColumn()) - 1; $newEntry['lastColumnIndex'] = Coordinate::columnIndexFromString($sheet->getHighestDataColumn()) - 1;
$newEntry['totalRows'] = $sheet->getHighestDataRow(); $newEntry['totalRows'] = $sheet->getHighestDataRow();
$newEntry['totalColumns'] = $newEntry['lastColumnIndex'] + 1; $newEntry['totalColumns'] = $newEntry['lastColumnIndex'] + 1;
$newEntry['sheetState'] = Worksheet::SHEETSTATE_VISIBLE;
$info[] = $newEntry; $info[] = $newEntry;
} }
$spreadsheet->disconnectWorksheets(); $spreadsheet->disconnectWorksheets();
+56 -53
View File
@@ -157,64 +157,67 @@ class Ods extends BaseReader
// Step into the first level of content of the XML // Step into the first level of content of the XML
$xml->read(); $xml->read();
$tableVisibility = [];
$lastTableStyle = '';
while ($xml->read()) { while ($xml->read()) {
// Quickly jump through to the office:body node if (self::getXmlName($xml) === 'style:style') {
while (self::getXmlName($xml) !== 'office:body') { $styleType = $xml->getAttribute('style:family');
if ($xml->isEmptyElement) { if ($styleType === 'table') {
$lastTableStyle = $xml->getAttribute('style:name');
}
} elseif (self::getXmlName($xml) === 'style:table-properties') {
$visibility = $xml->getAttribute('table:display');
$tableVisibility[$lastTableStyle] = ($visibility === 'false') ? Worksheet::SHEETSTATE_HIDDEN : Worksheet::SHEETSTATE_VISIBLE;
} elseif (self::getXmlName($xml) == 'table:table' && $xml->nodeType == XMLReader::ELEMENT) {
$worksheetNames[] = $xml->getAttribute('table:name');
$styleName = $xml->getAttribute('table:style-name') ?? '';
$visibility = $tableVisibility[$styleName] ?? '';
$tmpInfo = [
'worksheetName' => $xml->getAttribute('table:name'),
'lastColumnLetter' => 'A',
'lastColumnIndex' => 0,
'totalRows' => 0,
'totalColumns' => 0,
'sheetState' => $visibility,
];
// Loop through each child node of the table:table element reading
$currCells = 0;
do {
$xml->read(); $xml->read();
} else { if (self::getXmlName($xml) == 'table:table-row' && $xml->nodeType == XMLReader::ELEMENT) {
$xml->next(); $rowspan = $xml->getAttribute('table:number-rows-repeated');
} $rowspan = empty($rowspan) ? 1 : $rowspan;
} $tmpInfo['totalRows'] += $rowspan;
// Now read each node until we find our first table:table node $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells);
while ($xml->read()) { $currCells = 0;
if (self::getXmlName($xml) == 'table:table' && $xml->nodeType == XMLReader::ELEMENT) { // Step into the row
$worksheetNames[] = $xml->getAttribute('table:name');
$tmpInfo = [
'worksheetName' => $xml->getAttribute('table:name'),
'lastColumnLetter' => 'A',
'lastColumnIndex' => 0,
'totalRows' => 0,
'totalColumns' => 0,
];
// Loop through each child node of the table:table element reading
$currCells = 0;
do {
$xml->read(); $xml->read();
if (self::getXmlName($xml) == 'table:table-row' && $xml->nodeType == XMLReader::ELEMENT) { do {
$rowspan = $xml->getAttribute('table:number-rows-repeated'); $doread = true;
$rowspan = empty($rowspan) ? 1 : $rowspan; if (self::getXmlName($xml) == 'table:table-cell' && $xml->nodeType == XMLReader::ELEMENT) {
$tmpInfo['totalRows'] += $rowspan; if (!$xml->isEmptyElement) {
$tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells); ++$currCells;
$currCells = 0; $xml->next();
// Step into the row $doread = false;
$xml->read();
do {
$doread = true;
if (self::getXmlName($xml) == 'table:table-cell' && $xml->nodeType == XMLReader::ELEMENT) {
if (!$xml->isEmptyElement) {
++$currCells;
$xml->next();
$doread = false;
}
} elseif (self::getXmlName($xml) == 'table:covered-table-cell' && $xml->nodeType == XMLReader::ELEMENT) {
$mergeSize = $xml->getAttribute('table:number-columns-repeated');
$currCells += (int) $mergeSize;
} }
if ($doread) { } elseif (self::getXmlName($xml) == 'table:covered-table-cell' && $xml->nodeType == XMLReader::ELEMENT) {
$xml->read(); $mergeSize = $xml->getAttribute('table:number-columns-repeated');
} $currCells += (int) $mergeSize;
} while (self::getXmlName($xml) != 'table:table-row'); }
} if ($doread) {
} while (self::getXmlName($xml) != 'table:table'); $xml->read();
}
} while (self::getXmlName($xml) != 'table:table-row');
}
} while (self::getXmlName($xml) != 'table:table');
$tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells); $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells);
$tmpInfo['lastColumnIndex'] = $tmpInfo['totalColumns'] - 1; $tmpInfo['lastColumnIndex'] = $tmpInfo['totalColumns'] - 1;
$tmpInfo['lastColumnLetter'] = Coordinate::stringFromColumnIndex($tmpInfo['lastColumnIndex'] + 1); $tmpInfo['lastColumnLetter'] = Coordinate::stringFromColumnIndex($tmpInfo['lastColumnIndex'] + 1);
$worksheetInfo[] = $tmpInfo; $worksheetInfo[] = $tmpInfo;
}
} }
} }
+1
View File
@@ -131,6 +131,7 @@ class Slk extends BaseReader
$worksheetInfo[0]['totalRows'] = $rowIndex; $worksheetInfo[0]['totalRows'] = $rowIndex;
$worksheetInfo[0]['lastColumnLetter'] = Coordinate::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex'] + 1); $worksheetInfo[0]['lastColumnLetter'] = Coordinate::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex'] + 1);
$worksheetInfo[0]['totalColumns'] = $worksheetInfo[0]['lastColumnIndex'] + 1; $worksheetInfo[0]['totalColumns'] = $worksheetInfo[0]['lastColumnIndex'] + 1;
$worksheetInfo[0]['sheetState'] = Worksheet::SHEETSTATE_VISIBLE;
// Close file // Close file
fclose($fileHandle); fclose($fileHandle);
@@ -5,6 +5,7 @@ namespace PhpOffice\PhpSpreadsheet\Reader\Xls;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Reader\Xls; use PhpOffice\PhpSpreadsheet\Reader\Xls;
use PhpOffice\PhpSpreadsheet\Shared\File; use PhpOffice\PhpSpreadsheet\Shared\File;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
class ListFunctions extends Xls class ListFunctions extends Xls
{ {
@@ -104,6 +105,7 @@ class ListFunctions extends Xls
$tmpInfo['lastColumnIndex'] = 0; $tmpInfo['lastColumnIndex'] = 0;
$tmpInfo['totalRows'] = 0; $tmpInfo['totalRows'] = 0;
$tmpInfo['totalColumns'] = 0; $tmpInfo['totalColumns'] = 0;
$tmpInfo['sheetState'] = $sheet['sheetState'];
$xls->pos = $sheet['offset']; $xls->pos = $sheet['offset'];
+3 -1
View File
@@ -238,6 +238,8 @@ class Xlsx extends BaseReader
'totalRows' => 0, 'totalRows' => 0,
'totalColumns' => 0, 'totalColumns' => 0,
]; ];
$sheetState = (string) (self::getAttributes($eleSheet)['state'] ?? Worksheet::SHEETSTATE_VISIBLE);
$tmpInfo['sheetState'] = $sheetState;
$fileWorksheet = (string) $worksheets[self::getArrayItemString(self::getAttributes($eleSheet, $namespace), 'id')]; $fileWorksheet = (string) $worksheets[self::getArrayItemString(self::getAttributes($eleSheet, $namespace), 'id')];
$fileWorksheetPath = str_starts_with($fileWorksheet, '/') ? substr($fileWorksheet, 1) : "$dir/$fileWorksheet"; $fileWorksheetPath = str_starts_with($fileWorksheet, '/') ? substr($fileWorksheet, 1) : "$dir/$fileWorksheet";
@@ -257,7 +259,7 @@ class Xlsx extends BaseReader
$currCells = 0; $currCells = 0;
while ($xml->read()) { while ($xml->read()) {
if ($xml->localName == 'row' && $xml->nodeType == XMLReader::ELEMENT && $xml->namespaceURI === $mainNS) { if ($xml->localName == 'row' && $xml->nodeType == XMLReader::ELEMENT && $xml->namespaceURI === $mainNS) {
$row = $xml->getAttribute('r'); $row = (int) $xml->getAttribute('r');
$tmpInfo['totalRows'] = $row; $tmpInfo['totalRows'] = $row;
$tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells); $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells);
$currCells = 0; $currCells = 0;
+1
View File
@@ -229,6 +229,7 @@ class Xml extends BaseReader
$tmpInfo['lastColumnLetter'] = Coordinate::stringFromColumnIndex($tmpInfo['lastColumnIndex'] + 1); $tmpInfo['lastColumnLetter'] = Coordinate::stringFromColumnIndex($tmpInfo['lastColumnIndex'] + 1);
$tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1; $tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1;
$tmpInfo['sheetState'] = Worksheet::SHEETSTATE_VISIBLE;
$worksheetInfo[] = $tmpInfo; $worksheetInfo[] = $tmpInfo;
++$worksheetID; ++$worksheetID;
@@ -32,6 +32,7 @@ class GnumericInfoTest extends TestCase
'lastColumnIndex' => 13, 'lastColumnIndex' => 13,
'totalRows' => 31, 'totalRows' => 31,
'totalColumns' => 14, 'totalColumns' => 14,
'sheetState' => 'visible',
], ],
[ [
'worksheetName' => 'Report Data', 'worksheetName' => 'Report Data',
@@ -39,6 +40,7 @@ class GnumericInfoTest extends TestCase
'lastColumnIndex' => 10, 'lastColumnIndex' => 10,
'totalRows' => 65535, 'totalRows' => 65535,
'totalColumns' => 11, 'totalColumns' => 11,
'sheetState' => 'visible',
], ],
]; ];
self::assertEquals($expected, $info); self::assertEquals($expected, $info);
@@ -49,4 +49,29 @@ class HiddenWorksheetTest extends TestCase
], ],
]; ];
} }
public function testListWorksheetInfo(): void
{
$filename = 'tests/data/Reader/Gnumeric/HiddenSheet.gnumeric';
$reader = new Gnumeric();
$expected = [
[
'worksheetName' => 'Sheet1',
'lastColumnLetter' => 'A',
'lastColumnIndex' => 0,
'totalRows' => 1,
'totalColumns' => 1,
'sheetState' => 'visible',
],
[
'worksheetName' => 'Sheet2',
'lastColumnLetter' => 'A',
'lastColumnIndex' => 0,
'totalRows' => 1,
'totalColumns' => 1,
'sheetState' => 'hidden',
],
];
self::assertSame($expected, $reader->listWorksheetInfo($filename));
}
} }
@@ -12,7 +12,7 @@ class HiddenWorksheetTest extends TestCase
{ {
public function testPageSetup(): void public function testPageSetup(): void
{ {
$filename = 'tests/data/Reader/Ods/HiddenSheet.ods'; $filename = 'tests/data/Reader/Ods/HiddenSheet2.ods';
$reader = new Ods(); $reader = new Ods();
$spreadsheet = $reader->load($filename); $spreadsheet = $reader->load($filename);
$assertions = $this->worksheetAssertions(); $assertions = $this->worksheetAssertions();
@@ -49,4 +49,29 @@ class HiddenWorksheetTest extends TestCase
], ],
]; ];
} }
public function testListWorksheetInfo(): void
{
$filename = 'tests/data/Reader/Ods/HiddenSheet2.ods';
$reader = new Ods();
$expected = [
[
'worksheetName' => 'Sheet1',
'lastColumnLetter' => 'A',
'lastColumnIndex' => 0,
'totalRows' => 1,
'totalColumns' => 1,
'sheetState' => 'visible',
],
[
'worksheetName' => 'Sheet2',
'lastColumnLetter' => 'A',
'lastColumnIndex' => 0,
'totalRows' => 1,
'totalColumns' => 1,
'sheetState' => 'hidden',
],
];
self::assertSame($expected, $reader->listWorksheetInfo($filename));
}
} }
@@ -70,6 +70,7 @@ class OdsInfoTest extends TestCase
'lastColumnIndex' => 2, 'lastColumnIndex' => 2,
'totalRows' => 12, 'totalRows' => 12,
'totalColumns' => 3, 'totalColumns' => 3,
'sheetState' => 'visible',
], ],
[ [
'worksheetName' => 'Second Sheet', 'worksheetName' => 'Second Sheet',
@@ -77,6 +78,7 @@ class OdsInfoTest extends TestCase
'lastColumnIndex' => 0, 'lastColumnIndex' => 0,
'totalRows' => 2, 'totalRows' => 2,
'totalColumns' => 1, 'totalColumns' => 1,
'sheetState' => 'visible',
], ],
], $wsinfo); ], $wsinfo);
} }
@@ -49,4 +49,45 @@ class HiddenWorksheetTest extends TestCase
], ],
]; ];
} }
public function testListWorksheetInfo(): void
{
$filename = 'tests/data/Reader/XLS/visibility.xls';
$reader = new Xls();
$expected = [
[
'worksheetName' => 'Sheet1',
'lastColumnLetter' => 'A',
'lastColumnIndex' => 0,
'totalRows' => 1,
'totalColumns' => 1,
'sheetState' => 'visible',
],
[
'worksheetName' => 'Sheet2',
'lastColumnLetter' => 'A',
'lastColumnIndex' => 0,
'totalRows' => 1,
'totalColumns' => 1,
'sheetState' => 'hidden',
],
[
'worksheetName' => 'Sheet3',
'lastColumnLetter' => 'A',
'lastColumnIndex' => 0,
'totalRows' => 1,
'totalColumns' => 1,
'sheetState' => 'visible',
],
[
'worksheetName' => 'Sheet4',
'lastColumnLetter' => 'A',
'lastColumnIndex' => 0,
'totalRows' => 2,
'totalColumns' => 1,
'sheetState' => 'veryHidden',
],
];
self::assertSame($expected, $reader->listWorksheetInfo($filename));
}
} }
@@ -31,6 +31,7 @@ class InfoNamesTest extends TestCase
'lastColumnIndex' => 4, 'lastColumnIndex' => 4,
'totalRows' => 19, 'totalRows' => 19,
'totalColumns' => 5, 'totalColumns' => 5,
'sheetState' => 'visible',
], ],
[ [
'worksheetName' => 'Terms and conditions', 'worksheetName' => 'Terms and conditions',
@@ -38,6 +39,7 @@ class InfoNamesTest extends TestCase
'lastColumnIndex' => 1, 'lastColumnIndex' => 1,
'totalRows' => 3, 'totalRows' => 3,
'totalColumns' => 2, 'totalColumns' => 2,
'sheetState' => 'visible',
], ],
]; ];
self::assertSame($expected, $info); self::assertSame($expected, $info);
@@ -66,6 +68,7 @@ class InfoNamesTest extends TestCase
'lastColumnIndex' => 1, 'lastColumnIndex' => 1,
'totalRows' => 1, 'totalRows' => 1,
'totalColumns' => 2, 'totalColumns' => 2,
'sheetState' => 'visible',
], ],
]; ];
self::assertSame($expected, $info); self::assertSame($expected, $info);
@@ -106,6 +109,7 @@ class InfoNamesTest extends TestCase
'lastColumnIndex' => 15, 'lastColumnIndex' => 15,
'totalRows' => 3, 'totalRows' => 3,
'totalColumns' => 16, 'totalColumns' => 16,
'sheetState' => 'visible',
], ],
]; ];
self::assertSame($expected, $info); self::assertSame($expected, $info);
@@ -46,4 +46,45 @@ class HiddenWorksheetTest extends TestCase
], ],
]; ];
} }
public function testListWorksheetInfo(): void
{
$filename = 'tests/data/Reader/XLSX/visibility.xlsx';
$reader = new Xlsx();
$expected = [
[
'worksheetName' => 'Sheet1',
'lastColumnLetter' => 'A',
'lastColumnIndex' => 0,
'totalRows' => 1,
'totalColumns' => 1,
'sheetState' => 'visible',
],
[
'worksheetName' => 'Sheet2',
'lastColumnLetter' => 'A',
'lastColumnIndex' => 0,
'totalRows' => 1,
'totalColumns' => 1,
'sheetState' => 'hidden',
],
[
'worksheetName' => 'Sheet3',
'lastColumnLetter' => 'A',
'lastColumnIndex' => 0,
'totalRows' => 1,
'totalColumns' => 1,
'sheetState' => 'visible',
],
[
'worksheetName' => 'Sheet4',
'lastColumnLetter' => 'B',
'lastColumnIndex' => 1,
'totalRows' => 1,
'totalColumns' => 2,
'sheetState' => 'veryHidden',
],
];
self::assertSame($expected, $reader->listWorksheetInfo($filename));
}
} }
@@ -52,8 +52,9 @@ class Issue2516Test extends TestCase
'worksheetName' => 'Sheet1', 'worksheetName' => 'Sheet1',
'lastColumnLetter' => 'B', 'lastColumnLetter' => 'B',
'lastColumnIndex' => 1, 'lastColumnIndex' => 1,
'totalRows' => '6', 'totalRows' => 6,
'totalColumns' => 2, 'totalColumns' => 2,
'sheetState' => 'visible',
], ],
]; ];
self::assertSame($expected, $infos); self::assertSame($expected, $infos);
@@ -40,8 +40,9 @@ class NamespacePurlTest extends \PHPUnit\Framework\TestCase
'worksheetName' => 'ml_out', 'worksheetName' => 'ml_out',
'lastColumnLetter' => 'R', 'lastColumnLetter' => 'R',
'lastColumnIndex' => 17, 'lastColumnIndex' => 17,
'totalRows' => '76', 'totalRows' => 76,
'totalColumns' => 18, 'totalColumns' => 18,
'sheetState' => 'visible',
], ],
]; ];
@@ -22,6 +22,7 @@ class WorksheetInfoNamesTest extends TestCase
'lastColumnIndex' => 5, 'lastColumnIndex' => 5,
'totalRows' => '6', 'totalRows' => '6',
'totalColumns' => 6, 'totalColumns' => 6,
'sheetState' => 'visible',
], ],
]; ];
@@ -51,6 +52,7 @@ class WorksheetInfoNamesTest extends TestCase
'lastColumnIndex' => 10, 'lastColumnIndex' => 10,
'totalRows' => 2, 'totalRows' => 2,
'totalColumns' => 11, 'totalColumns' => 11,
'sheetState' => 'visible',
], ],
]; ];
@@ -52,6 +52,7 @@ class XmlInfoTest extends TestCase
'lastColumnIndex' => 9, 'lastColumnIndex' => 9,
'totalRows' => 31, 'totalRows' => 31,
'totalColumns' => 10, 'totalColumns' => 10,
'sheetState' => 'visible',
], ],
[ [
'worksheetName' => 'Report Data', 'worksheetName' => 'Report Data',
@@ -59,6 +60,7 @@ class XmlInfoTest extends TestCase
'lastColumnIndex' => 8, 'lastColumnIndex' => 8,
'totalRows' => 15, 'totalRows' => 15,
'totalColumns' => 9, 'totalColumns' => 9,
'sheetState' => 'visible',
], ],
]; ];
self::assertEquals($expected, $info); self::assertEquals($expected, $info);
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.