@@ -43,6 +43,25 @@ class Cells
4343 */
4444 private array $ index = [];
4545
46+ /**
47+ * Flag to avoid sorting the index every time.
48+ */
49+ private bool $ indexSorted = false ;
50+
51+ /**
52+ * Index keys cache to avoid recalculating on large arrays.
53+ *
54+ * @var null|string[]
55+ */
56+ private ?array $ indexKeysCache = null ;
57+
58+ /**
59+ * Index values cache to avoid recalculating on large arrays.
60+ *
61+ * @var null|int[]
62+ */
63+ private ?array $ indexValuesCache = null ;
64+
4665 /**
4766 * Prefix used to uniquely identify cache data for this worksheet.
4867 */
@@ -112,6 +131,10 @@ public function delete(string $cellCoordinate): void
112131
113132 unset($ this ->index [$ cellCoordinate ]);
114133
134+ // Clear index caches
135+ $ this ->indexKeysCache = null ;
136+ $ this ->indexValuesCache = null ;
137+
115138 // Delete the entry from cache
116139 $ this ->cache ->delete ($ this ->cachePrefix . $ cellCoordinate );
117140 }
@@ -123,7 +146,12 @@ public function delete(string $cellCoordinate): void
123146 */
124147 public function getCoordinates (): array
125148 {
126- return array_keys ($ this ->index );
149+ // Build or rebuild index keys cache
150+ if ($ this ->indexKeysCache === null ) {
151+ $ this ->indexKeysCache = array_keys ($ this ->index );
152+ }
153+
154+ return $ this ->indexKeysCache ;
127155 }
128156
129157 /**
@@ -133,9 +161,18 @@ public function getCoordinates(): array
133161 */
134162 public function getSortedCoordinates (): array
135163 {
136- asort ($ this ->index );
164+ // Sort only when required
165+ if (!$ this ->indexSorted ) {
166+ asort ($ this ->index );
167+ $ this ->indexSorted = true ;
168+ }
137169
138- return array_keys ($ this ->index );
170+ // Build or rebuild index keys cache
171+ if ($ this ->indexKeysCache === null ) {
172+ $ this ->indexKeysCache = array_keys ($ this ->index );
173+ }
174+
175+ return $ this ->indexKeysCache ;
139176 }
140177
141178 /**
@@ -145,9 +182,16 @@ public function getSortedCoordinates(): array
145182 */
146183 public function getSortedCoordinatesInt (): array
147184 {
148- asort ($ this ->index );
185+ if (!$ this ->indexSorted ) {
186+ asort ($ this ->index );
187+ $ this ->indexSorted = true ;
188+ }
149189
150- return array_values ($ this ->index );
190+ if ($ this ->indexValuesCache === null ) {
191+ $ this ->indexValuesCache = array_values ($ this ->index );
192+ }
193+
194+ return $ this ->indexValuesCache ;
151195 }
152196
153197 /**
@@ -300,6 +344,11 @@ public function cloneCellCollection(Worksheet $worksheet): static
300344 }
301345 }
302346
347+ // Clear index sorted flag and index caches
348+ $ newCollection ->indexSorted = false ;
349+ $ newCollection ->indexKeysCache = null ;
350+ $ newCollection ->indexValuesCache = null ;
351+
303352 return $ newCollection ;
304353 }
305354
@@ -390,6 +439,11 @@ public function add(string $cellCoordinate, Cell $cell): Cell
390439 /** @var int $row */
391440 $ this ->index [$ cellCoordinate ] = (--$ row * self ::MAX_COLUMN_ID ) + Coordinate::columnIndexFromString ((string ) $ column );
392441
442+ // Clear index sorted flag and index caches
443+ $ this ->indexSorted = false ;
444+ $ this ->indexKeysCache = null ;
445+ $ this ->indexValuesCache = null ;
446+
393447 $ this ->currentCoordinate = $ cellCoordinate ;
394448 $ this ->currentCell = $ cell ;
395449 $ this ->currentCellIsDirty = true ;
@@ -444,6 +498,11 @@ public function unsetWorksheetCells(): void
444498
445499 $ this ->index = [];
446500
501+ // Clear index sorted flag and index caches
502+ $ this ->indexSorted = false ;
503+ $ this ->indexKeysCache = null ;
504+ $ this ->indexValuesCache = null ;
505+
447506 // detach ourself from the worksheet, so that it can then delete this object successfully
448507 $ this ->parent = null ;
449508 }
0 commit comments