From ad15232fc7942627dbbedbe0cc74324e0530b166 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 6 Jul 2022 03:13:09 +0200 Subject: [PATCH 1/2] Modify rangeBoundaries(), rangeDimension() and getRangeBoundaries() methods to work with row/column ranges as well as with cell ranges and cells --- src/PhpSpreadsheet/Cell/Coordinate.php | 38 +++++++++---------- tests/data/CellGetRangeBoundaries.php | 52 +++++++++++++++++--------- tests/data/CellRangeBoundaries.php | 52 +++++++++++++++++--------- 3 files changed, 87 insertions(+), 55 deletions(-) diff --git a/src/PhpSpreadsheet/Cell/Coordinate.php b/src/PhpSpreadsheet/Cell/Coordinate.php index 9aa879c3..50678397 100644 --- a/src/PhpSpreadsheet/Cell/Coordinate.php +++ b/src/PhpSpreadsheet/Cell/Coordinate.php @@ -183,12 +183,12 @@ abstract class Coordinate /** * Calculate range boundaries. * - * @param string $range Cell range (e.g. A1:A1) + * @param string $range Cell range, Single Cell, Row/Column Range (e.g. A1:A1, B2, B:C, 2:3) * * @return array Range coordinates [Start Cell, End Cell] * where Start Cell and End Cell are arrays (Column Number, Row Number) */ - public static function rangeBoundaries($range) + public static function rangeBoundaries(string $range): array { // Ensure $pRange is a valid range if (empty($range)) { @@ -205,6 +205,16 @@ abstract class Coordinate [$rangeA, $rangeB] = explode(':', $range); } + if (is_numeric($rangeA) && is_numeric($rangeB)) { + $rangeA = 'A' . $rangeA; + $rangeB = AddressRange::MAX_COLUMN . $rangeB; + } + + if (ctype_alpha($rangeA) && ctype_alpha($rangeB)) { + $rangeA = $rangeA . '1'; + $rangeB = $rangeB . AddressRange::MAX_ROW; + } + // Calculate range outer borders $rangeStart = self::coordinateFromString($rangeA); $rangeEnd = self::coordinateFromString($rangeB); @@ -219,7 +229,7 @@ abstract class Coordinate /** * Calculate range dimension. * - * @param string $range Cell range (e.g. A1:A1) + * @param string $range Cell range, Single Cell, Row/Column Range (e.g. A1:A1, B2, B:C, 2:3) * * @return array Range dimension (width, height) */ @@ -234,29 +244,19 @@ abstract class Coordinate /** * Calculate range boundaries. * - * @param string $range Cell range (e.g. A1:A1) + * @param string $range Cell range, Single Cell, Row/Column Range (e.g. A1:A1, B2, B:C, 2:3) * * @return array Range coordinates [Start Cell, End Cell] * where Start Cell and End Cell are arrays [Column ID, Row Number] */ public static function getRangeBoundaries($range) { - // Ensure $pRange is a valid range - if (empty($range)) { - $range = self::DEFAULT_RANGE; - } + [$rangeA, $rangeB] = self::rangeBoundaries($range); - // Uppercase coordinate - $range = strtoupper($range); - - // Extract range - if (strpos($range, ':') === false) { - $rangeA = $rangeB = $range; - } else { - [$rangeA, $rangeB] = explode(':', $range); - } - - return [self::coordinateFromString($rangeA), self::coordinateFromString($rangeB)]; + return [ + [self::stringFromColumnIndex($rangeA[0]), $rangeA[1]], + [self::stringFromColumnIndex($rangeB[0]), $rangeB[1]], + ]; } /** diff --git a/tests/data/CellGetRangeBoundaries.php b/tests/data/CellGetRangeBoundaries.php index ff434796..7a56b4c0 100644 --- a/tests/data/CellGetRangeBoundaries.php +++ b/tests/data/CellGetRangeBoundaries.php @@ -2,29 +2,45 @@ return [ [ - [ - [ - 'B', - 4, - ], - [ - 'E', - 9, - ], + 'Cell Range' => [ + ['B', 4], + ['E', 9], ], 'B4:E9', ], - [ + 'Single Cell' => [ [ - [ - 'B', - 4, - ], - [ - 'B', - 4, - ], + ['B', 4], + ['B', 4], ], 'B4', ], + 'Column Range' => [ + [ + ['B', 1], + ['C', 1048576], + ], + 'B:C', + ], + 'Single Column Range' => [ + [ + ['B', 1], + ['B', 1048576], + ], + 'B:B', + ], + 'Row Range' => [ + [ + ['A', 2], + ['XFD', 3], + ], + '2:3', + ], + 'Single Row Range' => [ + [ + ['A', 2], + ['XFD', 2], + ], + '2:2', + ], ]; diff --git a/tests/data/CellRangeBoundaries.php b/tests/data/CellRangeBoundaries.php index 9e856ced..882f437c 100644 --- a/tests/data/CellRangeBoundaries.php +++ b/tests/data/CellRangeBoundaries.php @@ -1,30 +1,46 @@ [ [ - [ - 2, - 4, - ], - [ - 5, - 9, - ], + [2, 4], + [5, 9], ], 'B4:E9', ], - [ + 'Single Cell' => [ [ - [ - 2, - 4, - ], - [ - 2, - 4, - ], + [2, 4], + [2, 4], ], 'B4', ], + 'Column Range' => [ + [ + [2, 1], + [3, 1048576], + ], + 'B:C', + ], + 'Single Column Range' => [ + [ + [2, 1], + [2, 1048576], + ], + 'B:B', + ], + 'Row Range' => [ + [ + [1, 2], + [16384, 3], + ], + '2:3', + ], + 'Single Row Range' => [ + [ + [1, 2], + [16384, 2], + ], + '2:2', + ], ]; From e050b3ba8a4be661eb741933c8f77b65b0385247 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Fri, 8 Jul 2022 18:22:17 +0200 Subject: [PATCH 2/2] Update Change Log --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e3a4db1..3418c04a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,7 +26,8 @@ and this project adheres to [Semantic Versioning](https://semver.org). ### Changed -- Better enforcement of value modification to match specified datatype when using setValueExplicit() +- Modify `rangeBoundaries()`, `rangeDimension()` and `getRangeBoundaries()` Coordinate methods to work with row/column ranges as well as with cell ranges and cells [PR #2926](https://github.com/PHPOffice/PhpSpreadsheet/pull/2926) +- Better enforcement of value modification to match specified datatype when using `setValueExplicit()` - Relax validation of merge cells to allow merge for a single cell reference [Issue #2776](https://github.com/PHPOffice/PhpSpreadsheet/issues/2776) - Memory and speed improvements, particularly for the Cell Collection, and the Writers.