diff --git a/src/Spout/Reader/XLSX.php b/src/Spout/Reader/XLSX.php index bbe9ce61..db467077 100644 --- a/src/Spout/Reader/XLSX.php +++ b/src/Spout/Reader/XLSX.php @@ -190,9 +190,11 @@ protected function read() while ($this->xmlReader->read()) { if ($this->xmlReader->nodeType == \XMLReader::ELEMENT && $this->xmlReader->name === 'dimension') { // Read dimensions of the worksheet - $dimensionRef = $this->xmlReader->getAttribute('ref'); // returns 'A1:M13' for instance - list(, $lastCellIndex) = explode(':', $dimensionRef); - $this->numberOfColumns = CellHelper::getColumnIndexFromCellIndex($lastCellIndex) + 1; + $dimensionRef = $this->xmlReader->getAttribute('ref'); // returns 'A1:M13' for instance (or 'A1' for empty sheet) + if (preg_match('/[A-Z\d]+:([A-Z\d]+)/', $dimensionRef, $matches)) { + $lastCellIndex = $matches[1]; + $this->numberOfColumns = CellHelper::getColumnIndexFromCellIndex($lastCellIndex) + 1; + } } else if ($this->xmlReader->nodeType == \XMLReader::ELEMENT && $this->xmlReader->name === 'row') { // Start of the row description $isInsideRowTag = true; diff --git a/tests/Spout/Reader/XLSXTest.php b/tests/Spout/Reader/XLSXTest.php index e1cf9940..823490bd 100644 --- a/tests/Spout/Reader/XLSXTest.php +++ b/tests/Spout/Reader/XLSXTest.php @@ -165,6 +165,15 @@ public function testReadShouldBeProtectedAgainstBillionLaughsAttack() $this->assertEquals($expectedFirstRow, $allRows[0], 'Entities should be ignored when reading XML files.'); } + /** + * @return void + */ + public function testReadShouldBeAbleToProcessEmptySheets() + { + $allRows = $this->getAllRowsForFile('sheet_with_no_cells.xlsx'); + $this->assertEquals([], $allRows, 'Sheet with no cells should be correctly processed.'); + } + /** * @param string $fileName * @return array All the read rows the given file diff --git a/tests/resources/xlsx/sheet_with_no_cells.xlsx b/tests/resources/xlsx/sheet_with_no_cells.xlsx new file mode 100644 index 00000000..c41e892d Binary files /dev/null and b/tests/resources/xlsx/sheet_with_no_cells.xlsx differ