diff --git a/src/Spout/Reader/XLSX/RowIterator.php b/src/Spout/Reader/XLSX/RowIterator.php index c7491ac..a7c70e6 100644 --- a/src/Spout/Reader/XLSX/RowIterator.php +++ b/src/Spout/Reader/XLSX/RowIterator.php @@ -55,6 +55,9 @@ class RowIterator implements IteratorInterface /** @var int The number of columns the sheet has (0 meaning undefined) */ protected $numColumns = 0; + /** @var int Last column index processed (zero-based) */ + protected $lastColumnIndexProcessed = -1; + /** * @param string $filePath Path of the XLSX file being read * @param string $sheetDataXMLFilePath Path of the sheet data XML file as in [Content_Types].xml @@ -144,6 +147,9 @@ class RowIterator implements IteratorInterface } else if ($this->xmlReader->isPositionedOnStartingNode(self::XML_NODE_ROW)) { // Start of the row description + // Reset index of the last processed column + $this->lastColumnIndexProcessed = -1; + // Read spans info if present $numberOfColumnsForRow = $this->numColumns; $spans = $this->xmlReader->getAttribute(self::XML_ATTRIBUTE_SPANS); // returns '1:5' for instance @@ -155,12 +161,13 @@ class RowIterator implements IteratorInterface } else if ($this->xmlReader->isPositionedOnStartingNode(self::XML_NODE_CELL)) { // Start of a cell description - $currentCellIndex = $this->xmlReader->getAttribute(self::XML_ATTRIBUTE_CELL_INDEX); - $currentColumnIndex = CellHelper::getColumnIndexFromCellIndex($currentCellIndex); + $currentColumnIndex = $this->getCellIndex($this->xmlReader); $node = $this->xmlReader->expand(); $rowData[$currentColumnIndex] = $this->getCellValue($node); + $this->lastColumnIndexProcessed = $currentColumnIndex; + } else if ($this->xmlReader->isPositionedOnEndingNode(self::XML_NODE_ROW)) { // End of the row description // If needed, we fill the empty cells @@ -182,6 +189,21 @@ class RowIterator implements IteratorInterface $this->rowDataBuffer = $rowData; } + /** + * @param \Box\Spout\Reader\Wrapper\XMLReader $xmlReader XMLReader object, positioned on a "" tag + * @return int + * @throws \Box\Spout\Common\Exception\InvalidArgumentException When the given cell index is invalid + */ + protected function getCellIndex($xmlReader) + { + // Get "r" attribute if present (from something like + $currentCellIndex = $xmlReader->getAttribute(self::XML_ATTRIBUTE_CELL_INDEX); + + return ($currentCellIndex !== null) ? + CellHelper::getColumnIndexFromCellIndex($currentCellIndex) : + $this->lastColumnIndexProcessed + 1; + } + /** * Returns the (unescaped) correctly marshalled, cell value associated to the given XML node. * diff --git a/tests/Spout/Reader/XLSX/ReaderTest.php b/tests/Spout/Reader/XLSX/ReaderTest.php index c705f2f..3fa6ec1 100644 --- a/tests/Spout/Reader/XLSX/ReaderTest.php +++ b/tests/Spout/Reader/XLSX/ReaderTest.php @@ -140,6 +140,21 @@ class ReaderTest extends \PHPUnit_Framework_TestCase $this->assertEquals($expectedRows, $allRows); } + /** + * @return void + */ + public function testReadShouldSupportFilesWithoutCellReference() + { + // file where the cell definition does not have a "r" attribute + // as in ... + $allRows = $this->getAllRowsForFile('sheet_with_missing_cell_reference.xlsx'); + + $expectedRows = [ + ['s1--A1'], + ]; + $this->assertEquals($expectedRows, $allRows); + } + /** * @return void */ diff --git a/tests/resources/xlsx/sheet_with_missing_cell_reference.xlsx b/tests/resources/xlsx/sheet_with_missing_cell_reference.xlsx new file mode 100644 index 0000000..4e86cda Binary files /dev/null and b/tests/resources/xlsx/sheet_with_missing_cell_reference.xlsx differ