3
3
namespace PhpOffice \PhpSpreadsheet \Cell ;
4
4
5
5
use PhpOffice \PhpSpreadsheet \Exception ;
6
+ use PhpOffice \PhpSpreadsheet \Shared \StringHelper ;
6
7
use PhpOffice \PhpSpreadsheet \Worksheet \Validations ;
7
8
use PhpOffice \PhpSpreadsheet \Worksheet \Worksheet ;
8
9
@@ -162,7 +163,7 @@ public static function splitRange(string $range): array
162
163
/**
163
164
* Build range from coordinate strings.
164
165
*
165
- * @param array $range Array containing one or more arrays containing one or two coordinate strings
166
+ * @param mixed[] $range Array containing one or more arrays containing one or two coordinate strings
166
167
*
167
168
* @return string String representation of $pRange
168
169
*/
@@ -187,7 +188,7 @@ public static function buildRange(array $range): string
187
188
*
188
189
* @param string $range Cell range, Single Cell, Row/Column Range (e.g. A1:A1, B2, B:C, 2:3)
189
190
*
190
- * @return array Range coordinates [Start Cell, End Cell]
191
+ * @return array{array{int, int}, array{int, int}} Range coordinates [Start Cell, End Cell]
191
192
* where Start Cell and End Cell are arrays (Column Number, Row Number)
192
193
*/
193
194
public static function rangeBoundaries (string $ range ): array
@@ -224,6 +225,8 @@ public static function rangeBoundaries(string $range): array
224
225
// Translate column into index
225
226
$ rangeStart [0 ] = self ::columnIndexFromString ($ rangeStart [0 ]);
226
227
$ rangeEnd [0 ] = self ::columnIndexFromString ($ rangeEnd [0 ]);
228
+ $ rangeStart [1 ] = (int ) $ rangeStart [1 ];
229
+ $ rangeEnd [1 ] = (int ) $ rangeEnd [1 ];
227
230
228
231
return [$ rangeStart , $ rangeEnd ];
229
232
}
@@ -233,7 +236,7 @@ public static function rangeBoundaries(string $range): array
233
236
*
234
237
* @param string $range Cell range, Single Cell, Row/Column Range (e.g. A1:A1, B2, B:C, 2:3)
235
238
*
236
- * @return array Range dimension (width, height)
239
+ * @return array{int, int} Range dimension (width, height)
237
240
*/
238
241
public static function rangeDimension (string $ range ): array
239
242
{
@@ -248,7 +251,7 @@ public static function rangeDimension(string $range): array
248
251
*
249
252
* @param string $range Cell range, Single Cell, Row/Column Range (e.g. A1:A1, B2, B:C, 2:3)
250
253
*
251
- * @return array Range coordinates [Start Cell, End Cell]
254
+ * @return array{array{string, int}, array{string, int}} Range coordinates [Start Cell, End Cell]
252
255
* where Start Cell and End Cell are arrays [Column ID, Row Number]
253
256
*/
254
257
public static function getRangeBoundaries (string $ range ): array
@@ -267,7 +270,7 @@ public static function getRangeBoundaries(string $range): array
267
270
*
268
271
* @param string $reference Coordinate or Range (e.g. A1:A1, B2, B:C, 2:3)
269
272
*
270
- * @return array reference data
273
+ * @return array{type: string, firstCoordinate?: string, secondCoordinate?: string, coordinate?: string, worksheet?: string, localReference?: string} reference data
271
274
*/
272
275
private static function validateReferenceAndGetData ($ reference ): array
273
276
{
@@ -331,7 +334,13 @@ public static function coordinateIsInsideRange(string $range, string $coordinate
331
334
}
332
335
}
333
336
337
+ if (!isset ($ rangeData ['localReference ' ])) {
338
+ return false ;
339
+ }
334
340
$ boundaries = self ::rangeBoundaries ($ rangeData ['localReference ' ]);
341
+ if (!isset ($ coordinateData ['localReference ' ])) {
342
+ return false ;
343
+ }
335
344
$ coordinates = self ::indexesFromString ($ coordinateData ['localReference ' ]);
336
345
337
346
$ columnIsInside = $ boundaries [0 ][0 ] <= $ coordinates [0 ] && $ coordinates [0 ] <= $ boundaries [1 ][0 ];
@@ -358,6 +367,7 @@ public static function columnIndexFromString(?string $columnAddress): int
358
367
// Using a lookup cache adds a slight memory overhead, but boosts speed
359
368
// caching using a static within the method is faster than a class static,
360
369
// though it's additional memory overhead
370
+ /** @var int[] */
361
371
static $ indexCache = [];
362
372
$ columnAddress = $ columnAddress ?? '' ;
363
373
@@ -367,6 +377,7 @@ public static function columnIndexFromString(?string $columnAddress): int
367
377
// It's surprising how costly the strtoupper() and ord() calls actually are, so we use a lookup array
368
378
// rather than use ord() and make it case insensitive to get rid of the strtoupper() as well.
369
379
// Because it's a static, there's no significant memory overhead either.
380
+ /** @var array<string, int> */
370
381
static $ columnLookup = [
371
382
'A ' => 1 , 'B ' => 2 , 'C ' => 3 , 'D ' => 4 , 'E ' => 5 , 'F ' => 6 , 'G ' => 7 , 'H ' => 8 , 'I ' => 9 , 'J ' => 10 ,
372
383
'K ' => 11 , 'L ' => 12 , 'M ' => 13 , 'N ' => 14 , 'O ' => 15 , 'P ' => 16 , 'Q ' => 17 , 'R ' => 18 , 'S ' => 19 ,
@@ -402,23 +413,25 @@ public static function columnIndexFromString(?string $columnAddress): int
402
413
);
403
414
}
404
415
416
+ private const LOOKUP_CACHE = ' ABCDEFGHIJKLMNOPQRSTUVWXYZ ' ;
417
+
405
418
/**
406
419
* String from column index.
407
420
*
408
421
* @param int|numeric-string $columnIndex Column index (A = 1)
409
422
*/
410
423
public static function stringFromColumnIndex (int |string $ columnIndex ): string
411
424
{
425
+ /** @var string[] */
412
426
static $ indexCache = [];
413
- static $ lookupCache = ' ABCDEFGHIJKLMNOPQRSTUVWXYZ ' ;
414
427
415
428
if (!isset ($ indexCache [$ columnIndex ])) {
416
429
$ indexValue = $ columnIndex ;
417
430
$ base26 = '' ;
418
431
do {
419
432
$ characterValue = ($ indexValue % 26 ) ?: 26 ;
420
433
$ indexValue = ($ indexValue - $ characterValue ) / 26 ;
421
- $ base26 = $ lookupCache [$ characterValue ] . $ base26 ;
434
+ $ base26 = self :: LOOKUP_CACHE [$ characterValue ] . $ base26 ;
422
435
} while ($ indexValue > 0 );
423
436
$ indexCache [$ columnIndex ] = $ base26 ;
424
437
}
@@ -431,7 +444,7 @@ public static function stringFromColumnIndex(int|string $columnIndex): string
431
444
*
432
445
* @param string $cellRange Range: e.g. 'A1' or 'A1:C10' or 'A1:E10,A20:E25' or 'A1:E5 C3:G7' or 'A1:C1,A3:C3 B1:C3'
433
446
*
434
- * @return array Array containing single cell references
447
+ * @return string[] Array containing single cell references
435
448
*/
436
449
public static function extractAllCellReferencesInRange (string $ cellRange ): array
437
450
{
@@ -452,23 +465,35 @@ public static function extractAllCellReferencesInRange(string $cellRange): array
452
465
453
466
$ cells = [];
454
467
foreach ($ ranges as $ range ) {
468
+ /** @var string $range */
455
469
$ cells [] = self ::getReferencesForCellBlock ($ range );
456
470
}
457
471
472
+ /** @var mixed[] */
458
473
$ cells = self ::processRangeSetOperators ($ operators , $ cells );
459
474
460
475
if (empty ($ cells )) {
461
476
return [];
462
477
}
463
478
464
- $ cellList = array_merge (...$ cells );
479
+ /** @var string[] */
480
+ $ cellList = array_merge (...$ cells ); //* @phpstan-ignore-line
481
+ // Unsure how to satisfy phpstan in line above
465
482
466
- return array_map (
467
- fn ($ cellAddress ) => ($ worksheet !== '' ) ? "{$ quoted }{$ worksheet }{$ quoted }! {$ cellAddress }" : $ cellAddress ,
483
+ $ retVal = array_map (
484
+ fn (string $ cellAddress ) => ($ worksheet !== '' ) ? "{$ quoted }{$ worksheet }{$ quoted }! {$ cellAddress }" : $ cellAddress ,
468
485
self ::sortCellReferenceArray ($ cellList )
469
486
);
487
+
488
+ return $ retVal ;
470
489
}
471
490
491
+ /**
492
+ * @param mixed[] $operators
493
+ * @param mixed[][] $cells
494
+ *
495
+ * @return mixed[]
496
+ */
472
497
private static function processRangeSetOperators (array $ operators , array $ cells ): array
473
498
{
474
499
$ operatorCount = count ($ operators );
@@ -489,6 +514,11 @@ private static function processRangeSetOperators(array $operators, array $cells)
489
514
return $ cells ;
490
515
}
491
516
517
+ /**
518
+ * @param string[] $cellList
519
+ *
520
+ * @return string[]
521
+ */
492
522
private static function sortCellReferenceArray (array $ cellList ): array
493
523
{
494
524
// Sort the result by column and row
@@ -497,6 +527,7 @@ private static function sortCellReferenceArray(array $cellList): array
497
527
$ column = '' ;
498
528
$ row = 0 ;
499
529
sscanf ($ coordinate , '%[A-Z]%d ' , $ column , $ row );
530
+ /** @var int $row */
500
531
$ key = (--$ row * 16384 ) + self ::columnIndexFromString ((string ) $ column );
501
532
$ sortKeys [$ key ] = $ coordinate ;
502
533
}
@@ -548,7 +579,7 @@ public static function resolveUnionAndIntersection(string $cellBlock, string $im
548
579
*
549
580
* @param string $cellBlock A cell range e.g. A4:B5
550
581
*
551
- * @return array All individual cells in that range
582
+ * @return string[] All individual cells in that range
552
583
*/
553
584
private static function getReferencesForCellBlock (string $ cellBlock ): array
554
585
{
@@ -585,6 +616,8 @@ private static function getReferencesForCellBlock(string $cellBlock): array
585
616
586
617
// Loop cells
587
618
while ($ currentColumnIndex < $ endColumnIndex ) {
619
+ /** @var int $currentRow */
620
+ /** @var int $endRow */
588
621
while ($ currentRow <= $ endRow ) {
589
622
$ returnValue [] = self ::stringFromColumnIndex ($ currentColumnIndex ) . $ currentRow ;
590
623
++$ currentRow ;
@@ -610,9 +643,9 @@ private static function getReferencesForCellBlock(string $cellBlock): array
610
643
*
611
644
* [ 'A1:A3' => 'x', 'A4' => 'y' ]
612
645
*
613
- * @param array $coordinateCollection associative array mapping coordinates to values
646
+ * @param array<string, mixed> $coordinateCollection associative array mapping coordinates to values
614
647
*
615
- * @return array associative array mapping coordinate ranges to valuea
648
+ * @return array<string, mixed> associative array mapping coordinate ranges to valuea
616
649
*/
617
650
public static function mergeRangesInCollection (array $ coordinateCollection ): array
618
651
{
@@ -628,7 +661,7 @@ public static function mergeRangesInCollection(array $coordinateCollection): arr
628
661
629
662
[$ column , $ row ] = self ::coordinateFromString ($ coord );
630
663
$ row = (int ) (ltrim ($ row , '$ ' ));
631
- $ hashCode = $ column . '- ' . ((is_object ($ value ) && method_exists ($ value , 'getHashCode ' )) ? $ value ->getHashCode () : $ value );
664
+ $ hashCode = $ column . '- ' . StringHelper:: convertToString ((is_object ($ value ) && method_exists ($ value , 'getHashCode ' )) ? $ value ->getHashCode () : $ value );
632
665
633
666
if (!isset ($ hashedValues [$ hashCode ])) {
634
667
$ hashedValues [$ hashCode ] = (object ) [
@@ -687,7 +720,7 @@ public static function mergeRangesInCollection(array $coordinateCollection): arr
687
720
* Get the individual cell blocks from a range string, removing any $ characters.
688
721
* then splitting by operators and returning an array with ranges and operators.
689
722
*
690
- * @return array []
723
+ * @return mixed[] []
691
724
*/
692
725
private static function getCellBlocksFromRangeString (string $ rangeString ): array
693
726
{
0 commit comments