1313 */
1414class SheetHelper
1515{
16- /** Extension for XML files */
17- const XML_EXTENSION = '.xml ' ;
18-
1916 /** Paths of XML files relative to the XLSX file root */
2017 const CONTENT_TYPES_XML_FILE_PATH = '[Content_Types].xml ' ;
2118 const WORKBOOK_XML_RELS_FILE_PATH = 'xl/_rels/workbook.xml.rels ' ;
@@ -79,9 +76,15 @@ public function getSheets()
7976 $ sheetNode = $ sheetNodes [$ i ];
8077 $ sheetDataXMLFilePath = $ sheetNode ->getAttribute ('PartName ' );
8178
82- $ sheets [] = $ this ->getSheetFromXML ($ sheetDataXMLFilePath, $ i );
79+ $ sheets [] = $ this ->getSheetFromXML ($ sheetDataXMLFilePath );
8380 }
8481
82+ // make sure the sheets are sorted by index
83+ // (as the sheets are not necessarily in this order in the XML file)
84+ usort ($ sheets , function ($ sheet1 , $ sheet2 ) {
85+ return ($ sheet1 ->getIndex () - $ sheet2 ->getIndex ());
86+ });
87+
8588 return $ sheets ;
8689 }
8790
@@ -91,60 +94,37 @@ public function getSheets()
9194 * Then we look at "xl/worbook.xml" to find the sheet entry associated to the found ID.
9295 * The entry contains the ID and name of the sheet.
9396 *
94- * If this piece of data can't be found by parsing the different XML files, the ID will default
95- * to the sheet index, based on order in [Content_Types].xml. Similarly, the sheet's name will
96- * default to the data sheet XML file name ("xl/worksheets/sheet2.xml" => "sheet2").
97- *
9897 * @param string $sheetDataXMLFilePath Path of the sheet data XML file as in [Content_Types].xml
99- * @param int $sheetIndexZeroBased Index of the sheet, based on order in [Content_Types].xml (zero-based)
10098 * @return \Box\Spout\Reader\XLSX\Sheet Sheet instance
10199 */
102- protected function getSheetFromXML ($ sheetDataXMLFilePath, $ sheetIndexZeroBased )
100+ protected function getSheetFromXML ($ sheetDataXMLFilePath )
103101 {
104- $ sheetName = $ this ->getDefaultSheetName ($ sheetDataXMLFilePath );
105-
106- /*
107- * In [Content_Types].xml, the path is "/xl/worksheets/sheet1.xml"
108- * In workbook.xml.rels, it is only "worksheets/sheet1.xml"
109- */
102+ // In [Content_Types].xml, the path is "/xl/worksheets/sheet1.xml"
103+ // In workbook.xml.rels, it is only "worksheets/sheet1.xml"
110104 $ sheetDataXMLFilePathInWorkbookXMLRels = ltrim ($ sheetDataXMLFilePath , '/xl/ ' );
111105
112106 // find the node associated to the given file path
113107 $ workbookXMLResElement = $ this ->getWorkbookXMLRelsAsXMLElement ();
114108 $ relationshipNodes = $ workbookXMLResElement ->xpath ('//ns:Relationship[@Target=" ' . $ sheetDataXMLFilePathInWorkbookXMLRels . '"] ' );
109+ $ relationshipNode = $ relationshipNodes [0 ];
115110
116- if (count ($ relationshipNodes ) === 1 ) {
117- $ relationshipNode = $ relationshipNodes [0 ];
118- $ sheetId = $ relationshipNode ->getAttribute ('Id ' );
111+ $ relationshipSheetId = $ relationshipNode ->getAttribute ('Id ' );
119112
120- $ workbookXMLElement = $ this ->getWorkbookXMLAsXMLElement ();
121- $ sheetNodes = $ workbookXMLElement ->xpath ('//ns:sheet[@r:id=" ' . $ sheetId . '"] ' );
113+ $ workbookXMLElement = $ this ->getWorkbookXMLAsXMLElement ();
114+ $ sheetNodes = $ workbookXMLElement ->xpath ('//ns:sheet[@r:id=" ' . $ relationshipSheetId . '"] ' );
115+ $ sheetNode = $ sheetNodes [0 ];
122116
123- if ( count ( $ sheetNodes ) === 1 ) {
124- $ sheetNode = $ sheetNodes [ 0 ] ;
125- $ escapedSheetName = $ sheetNode -> getAttribute ( ' name ' ) ;
117+ $ escapedSheetName = $ sheetNode -> getAttribute ( ' name ' );
118+ $ sheetIdOneBased = $ sheetNode -> getAttribute ( ' sheetId ' ) ;
119+ $ sheetIndexZeroBased = $ sheetIdOneBased - 1 ;
126120
127- /** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
128- $ escaper = new \Box \Spout \Common \Escaper \XLSX ();
129- $ sheetName = $ escaper ->unescape ($ escapedSheetName );
130- }
131- }
121+ /** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
122+ $ escaper = new \Box \Spout \Common \Escaper \XLSX ();
123+ $ sheetName = $ escaper ->unescape ($ escapedSheetName );
132124
133125 return new Sheet ($ this ->filePath , $ sheetDataXMLFilePath , $ this ->sharedStringsHelper , $ sheetIndexZeroBased , $ sheetName );
134126 }
135127
136- /**
137- * Returns the default name of the sheet whose data is located
138- * at the given path.
139- *
140- * @param string $sheetDataXMLFilePath Path of the sheet data XML file
141- * @return string The default sheet name
142- */
143- protected function getDefaultSheetName ($ sheetDataXMLFilePath )
144- {
145- return $ this ->globalFunctionsHelper ->basename ($ sheetDataXMLFilePath , self ::XML_EXTENSION );
146- }
147-
148128 /**
149129 * Returns a representation of the workbook.xml.rels file, ready to be parsed.
150130 * The returned value is cached.
0 commit comments