diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a112635..d5c36a31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [Unreleased] + +### Fixed + +- Ranges across Z and AA columns incorrectly threw an exception - [#545](https://github.com/PHPOffice/PhpSpreadsheet/issues/545) + ## [1.3.0] - 2018-06-10 ### Added diff --git a/src/PhpSpreadsheet/Cell/Coordinate.php b/src/PhpSpreadsheet/Cell/Coordinate.php index 077e8d06..366ec492 100644 --- a/src/PhpSpreadsheet/Cell/Coordinate.php +++ b/src/PhpSpreadsheet/Cell/Coordinate.php @@ -340,7 +340,7 @@ abstract class Coordinate // Explode spaces $cellBlocks = self::getCellBlocksFromRangeString($pRange); foreach ($cellBlocks as $cellBlock) { - $returnValue = array_merge($returnValue, static::getReferencesForCellBlock($cellBlock)); + $returnValue = array_merge($returnValue, self::getReferencesForCellBlock($cellBlock)); } // Sort the result by column and row @@ -360,8 +360,6 @@ abstract class Coordinate * * @param string $cellBlock A cell range e.g. A4:B5 * - * @throws Exception - * * @return array All individual cells in that range */ private static function getReferencesForCellBlock($cellBlock) @@ -385,23 +383,25 @@ abstract class Coordinate // Range... list($rangeStart, $rangeEnd) = $range; - list($startCol, $startRow) = static::extractColumnAndRow($rangeStart); - list($endCol, $endRow) = static::extractColumnAndRow($rangeEnd); - ++$endCol; + list($startColumn, $startRow) = self::coordinateFromString($rangeStart); + list($endColumn, $endRow) = self::coordinateFromString($rangeEnd); + $startColumnIndex = self::columnIndexFromString($startColumn); + $endColumnIndex = self::columnIndexFromString($endColumn); + ++$endColumnIndex; // Current data - $currentCol = $startCol; + $currentColumnIndex = $startColumnIndex; $currentRow = $startRow; - static::validateRange($cellBlock, $startCol, $endCol, $currentRow, $endRow); + self::validateRange($cellBlock, $startColumnIndex, $endColumnIndex, $currentRow, $endRow); // Loop cells - while ($currentCol < $endCol) { + while ($currentColumnIndex < $endColumnIndex) { while ($currentRow <= $endRow) { - $returnValue[] = $currentCol . $currentRow; + $returnValue[] = self::stringFromColumnIndex($currentColumnIndex) . $currentRow; ++$currentRow; } - ++$currentCol; + ++$currentColumnIndex; $currentRow = $startRow; } } @@ -409,18 +409,6 @@ abstract class Coordinate return $returnValue; } - /** - * Extract the column and row from a cell reference in the format [$column, $row]. - * - * @param string $cell - * - * @return array - */ - private static function extractColumnAndRow($cell) - { - return sscanf($cell, '%[A-Z]%d'); - } - /** * Convert an associative array of single cell coordinates to values to an associative array * of cell ranges to values. Only adjacent cell coordinates with the same @@ -524,16 +512,14 @@ abstract class Coordinate * row. * * @param string $cellBlock The original range, for displaying a meaningful error message - * @param string $startCol - * @param string $endCol + * @param int $startColumnIndex + * @param int $endColumnIndex * @param int $currentRow * @param int $endRow - * - * @throws Exception */ - private static function validateRange($cellBlock, $startCol, $endCol, $currentRow, $endRow) + private static function validateRange($cellBlock, $startColumnIndex, $endColumnIndex, $currentRow, $endRow) { - if ($startCol >= $endCol || $currentRow > $endRow) { + if ($startColumnIndex >= $endColumnIndex || $currentRow > $endRow) { throw new Exception('Invalid range: "' . $cellBlock . '"'); } } diff --git a/tests/data/CellExtractAllCellReferencesInRange.php b/tests/data/CellExtractAllCellReferencesInRange.php index 678fe512..cf093289 100644 --- a/tests/data/CellExtractAllCellReferencesInRange.php +++ b/tests/data/CellExtractAllCellReferencesInRange.php @@ -140,4 +140,13 @@ return [ ], 'B4:B6 B8', ], + [ + [ + 'Z2', + 'Z3', + 'AA2', + 'AA3', + ], + 'Z2:AA3', + ], ];