@@ -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,21 @@ 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+ // Clear unsorted cache
169+ $ this ->indexKeysCache = null ;
170+ $ this ->indexValuesCache = null ;
171+ }
137172
138- return array_keys ($ this ->index );
173+ // Build or rebuild index keys cache
174+ if ($ this ->indexKeysCache === null ) {
175+ $ this ->indexKeysCache = array_keys ($ this ->index );
176+ }
177+
178+ return $ this ->indexKeysCache ;
139179 }
140180
141181 /**
@@ -145,9 +185,19 @@ public function getSortedCoordinates(): array
145185 */
146186 public function getSortedCoordinatesInt (): array
147187 {
148- asort ($ this ->index );
188+ if (!$ this ->indexSorted ) {
189+ asort ($ this ->index );
190+ $ this ->indexSorted = true ;
191+ // Clear unsorted cache
192+ $ this ->indexKeysCache = null ;
193+ $ this ->indexValuesCache = null ;
194+ }
149195
150- return array_values ($ this ->index );
196+ if ($ this ->indexValuesCache === null ) {
197+ $ this ->indexValuesCache = array_values ($ this ->index );
198+ }
199+
200+ return $ this ->indexValuesCache ;
151201 }
152202
153203 /**
@@ -300,6 +350,11 @@ public function cloneCellCollection(Worksheet $worksheet): static
300350 }
301351 }
302352
353+ // Clear index sorted flag and index caches
354+ $ newCollection ->indexSorted = false ;
355+ $ newCollection ->indexKeysCache = null ;
356+ $ newCollection ->indexValuesCache = null ;
357+
303358 return $ newCollection ;
304359 }
305360
@@ -390,6 +445,11 @@ public function add(string $cellCoordinate, Cell $cell): Cell
390445 /** @var int $row */
391446 $ this ->index [$ cellCoordinate ] = (--$ row * self ::MAX_COLUMN_ID ) + Coordinate::columnIndexFromString ((string ) $ column );
392447
448+ // Clear index sorted flag and index caches
449+ $ this ->indexSorted = false ;
450+ $ this ->indexKeysCache = null ;
451+ $ this ->indexValuesCache = null ;
452+
393453 $ this ->currentCoordinate = $ cellCoordinate ;
394454 $ this ->currentCell = $ cell ;
395455 $ this ->currentCellIsDirty = true ;
@@ -444,6 +504,11 @@ public function unsetWorksheetCells(): void
444504
445505 $ this ->index = [];
446506
507+ // Clear index sorted flag and index caches
508+ $ this ->indexSorted = false ;
509+ $ this ->indexKeysCache = null ;
510+ $ this ->indexValuesCache = null ;
511+
447512 // detach ourself from the worksheet, so that it can then delete this object successfully
448513 $ this ->parent = null ;
449514 }
0 commit comments