5
5
use PhpOffice \PhpSpreadsheet \Calculation \Calculation ;
6
6
use PhpOffice \PhpSpreadsheet \Cell \Coordinate ;
7
7
use PhpOffice \PhpSpreadsheet \Cell \DataType ;
8
+ use PhpOffice \PhpSpreadsheet \Style \Conditional ;
8
9
use PhpOffice \PhpSpreadsheet \Worksheet \AutoFilter ;
9
10
use PhpOffice \PhpSpreadsheet \Worksheet \Worksheet ;
10
11
@@ -198,6 +199,45 @@ protected function adjustHyperlinks($worksheet, $numberOfColumns, $numberOfRows)
198
199
}
199
200
}
200
201
202
+ /**
203
+ * Update conditional formatting styles when inserting/deleting rows/columns.
204
+ *
205
+ * @param Worksheet $worksheet The worksheet that we're editing
206
+ * @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion)
207
+ * @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion)
208
+ */
209
+ protected function adjustConditionalFormatting ($ worksheet , $ numberOfColumns , $ numberOfRows ): void
210
+ {
211
+ $ aStyles = $ worksheet ->getConditionalStylesCollection ();
212
+ ($ numberOfColumns > 0 || $ numberOfRows > 0 )
213
+ ? uksort ($ aStyles , [self ::class, 'cellReverseSort ' ])
214
+ : uksort ($ aStyles , [self ::class, 'cellSort ' ]);
215
+
216
+ foreach ($ aStyles as $ cellAddress => $ cfRules ) {
217
+ $ worksheet ->removeConditionalStyles ($ cellAddress );
218
+ $ newReference = $ this ->updateCellReference ($ cellAddress );
219
+
220
+ foreach ($ cfRules as &$ cfRule ) {
221
+ /** @var Conditional $cfRule */
222
+ $ conditions = $ cfRule ->getConditions ();
223
+ foreach ($ conditions as &$ condition ) {
224
+ if (is_string ($ condition )) {
225
+ $ condition = $ this ->updateFormulaReferences (
226
+ $ condition ,
227
+ $ this ->cellReferenceHelper ->beforeCellAddress (),
228
+ $ numberOfColumns ,
229
+ $ numberOfRows ,
230
+ $ worksheet ->getTitle (),
231
+ true
232
+ );
233
+ }
234
+ }
235
+ $ cfRule ->setConditions ($ conditions );
236
+ }
237
+ $ worksheet ->setConditionalStyles ($ newReference , $ cfRules );
238
+ }
239
+ }
240
+
201
241
/**
202
242
* Update data validations when inserting/deleting rows/columns.
203
243
*
@@ -442,6 +482,9 @@ function ($coordinate) use ($allCoordinates) {
442
482
// Update worksheet: hyperlinks
443
483
$ this ->adjustHyperlinks ($ worksheet , $ numberOfColumns , $ numberOfRows );
444
484
485
+ // Update worksheet: conditional formatting styles
486
+ $ this ->adjustConditionalFormatting ($ worksheet , $ numberOfColumns , $ numberOfRows );
487
+
445
488
// Update worksheet: data validations
446
489
$ this ->adjustDataValidations ($ worksheet , $ numberOfColumns , $ numberOfRows );
447
490
@@ -505,8 +548,14 @@ function ($coordinate) use ($allCoordinates) {
505
548
*
506
549
* @return string Updated formula
507
550
*/
508
- public function updateFormulaReferences ($ formula = '' , $ beforeCellAddress = 'A1 ' , $ numberOfColumns = 0 , $ numberOfRows = 0 , $ worksheetName = '' )
509
- {
551
+ public function updateFormulaReferences (
552
+ $ formula = '' ,
553
+ $ beforeCellAddress = 'A1 ' ,
554
+ $ numberOfColumns = 0 ,
555
+ $ numberOfRows = 0 ,
556
+ $ worksheetName = '' ,
557
+ bool $ includeAbsoluteReferences = false
558
+ ) {
510
559
if (
511
560
$ this ->cellReferenceHelper === null ||
512
561
$ this ->cellReferenceHelper ->refreshRequired ($ beforeCellAddress , $ numberOfColumns , $ numberOfRows )
@@ -528,8 +577,8 @@ public function updateFormulaReferences($formula = '', $beforeCellAddress = 'A1'
528
577
foreach ($ matches as $ match ) {
529
578
$ fromString = ($ match [2 ] > '' ) ? $ match [2 ] . '! ' : '' ;
530
579
$ fromString .= $ match [3 ] . ': ' . $ match [4 ];
531
- $ modified3 = substr ($ this ->updateCellReference ('$A ' . $ match [3 ]), 2 );
532
- $ modified4 = substr ($ this ->updateCellReference ('$A ' . $ match [4 ]), 2 );
580
+ $ modified3 = substr ($ this ->updateCellReference ('$A ' . $ match [3 ], $ includeAbsoluteReferences ), 2 );
581
+ $ modified4 = substr ($ this ->updateCellReference ('$A ' . $ match [4 ], $ includeAbsoluteReferences ), 2 );
533
582
534
583
if ($ match [3 ] . ': ' . $ match [4 ] !== $ modified3 . ': ' . $ modified4 ) {
535
584
if (($ match [2 ] == '' ) || (trim ($ match [2 ], "' " ) == $ worksheetName )) {
@@ -553,8 +602,8 @@ public function updateFormulaReferences($formula = '', $beforeCellAddress = 'A1'
553
602
foreach ($ matches as $ match ) {
554
603
$ fromString = ($ match [2 ] > '' ) ? $ match [2 ] . '! ' : '' ;
555
604
$ fromString .= $ match [3 ] . ': ' . $ match [4 ];
556
- $ modified3 = substr ($ this ->updateCellReference ($ match [3 ] . '$1 ' ), 0 , -2 );
557
- $ modified4 = substr ($ this ->updateCellReference ($ match [4 ] . '$1 ' ), 0 , -2 );
605
+ $ modified3 = substr ($ this ->updateCellReference ($ match [3 ] . '$1 ' , $ includeAbsoluteReferences ), 0 , -2 );
606
+ $ modified4 = substr ($ this ->updateCellReference ($ match [4 ] . '$1 ' , $ includeAbsoluteReferences ), 0 , -2 );
558
607
559
608
if ($ match [3 ] . ': ' . $ match [4 ] !== $ modified3 . ': ' . $ modified4 ) {
560
609
if (($ match [2 ] == '' ) || (trim ($ match [2 ], "' " ) == $ worksheetName )) {
@@ -578,8 +627,8 @@ public function updateFormulaReferences($formula = '', $beforeCellAddress = 'A1'
578
627
foreach ($ matches as $ match ) {
579
628
$ fromString = ($ match [2 ] > '' ) ? $ match [2 ] . '! ' : '' ;
580
629
$ fromString .= $ match [3 ] . ': ' . $ match [4 ];
581
- $ modified3 = $ this ->updateCellReference ($ match [3 ]);
582
- $ modified4 = $ this ->updateCellReference ($ match [4 ]);
630
+ $ modified3 = $ this ->updateCellReference ($ match [3 ], $ includeAbsoluteReferences );
631
+ $ modified4 = $ this ->updateCellReference ($ match [4 ], $ includeAbsoluteReferences );
583
632
584
633
if ($ match [3 ] . $ match [4 ] !== $ modified3 . $ modified4 ) {
585
634
if (($ match [2 ] == '' ) || (trim ($ match [2 ], "' " ) == $ worksheetName )) {
@@ -606,7 +655,7 @@ public function updateFormulaReferences($formula = '', $beforeCellAddress = 'A1'
606
655
$ fromString = ($ match [2 ] > '' ) ? $ match [2 ] . '! ' : '' ;
607
656
$ fromString .= $ match [3 ];
608
657
609
- $ modified3 = $ this ->updateCellReference ($ match [3 ]);
658
+ $ modified3 = $ this ->updateCellReference ($ match [3 ], $ includeAbsoluteReferences );
610
659
if ($ match [3 ] !== $ modified3 ) {
611
660
if (($ match [2 ] == '' ) || (trim ($ match [2 ], "' " ) == $ worksheetName )) {
612
661
$ toString = ($ match [2 ] > '' ) ? $ match [2 ] . '! ' : '' ;
@@ -786,18 +835,18 @@ private function updateRowRangesAllWorksheets(string $formula, int $numberOfRows
786
835
*
787
836
* @return string Updated cell range
788
837
*/
789
- private function updateCellReference ($ cellReference = 'A1 ' )
838
+ private function updateCellReference ($ cellReference = 'A1 ' , bool $ includeAbsoluteReferences = false )
790
839
{
791
840
// Is it in another worksheet? Will not have to update anything.
792
841
if (strpos ($ cellReference , '! ' ) !== false ) {
793
842
return $ cellReference ;
794
843
// Is it a range or a single cell?
795
844
} elseif (!Coordinate::coordinateIsRange ($ cellReference )) {
796
845
// Single cell
797
- return $ this ->cellReferenceHelper ->updateCellReference ($ cellReference );
846
+ return $ this ->cellReferenceHelper ->updateCellReference ($ cellReference, $ includeAbsoluteReferences );
798
847
} elseif (Coordinate::coordinateIsRange ($ cellReference )) {
799
848
// Range
800
- return $ this ->updateCellRange ($ cellReference );
849
+ return $ this ->updateCellRange ($ cellReference, $ includeAbsoluteReferences );
801
850
}
802
851
803
852
// Return original
@@ -839,7 +888,7 @@ public function updateNamedFormulas(Spreadsheet $spreadsheet, $oldName = '', $ne
839
888
*
840
889
* @return string Updated cell range
841
890
*/
842
- private function updateCellRange (string $ cellRange = 'A1:A1 ' ): string
891
+ private function updateCellRange (string $ cellRange = 'A1:A1 ' , bool $ includeAbsoluteReferences = false ): string
843
892
{
844
893
if (!Coordinate::coordinateIsRange ($ cellRange )) {
845
894
throw new Exception ('Only cell ranges may be passed to this method. ' );
@@ -853,14 +902,14 @@ private function updateCellRange(string $cellRange = 'A1:A1'): string
853
902
for ($ j = 0 ; $ j < $ jc ; ++$ j ) {
854
903
if (ctype_alpha ($ range [$ i ][$ j ])) {
855
904
$ range [$ i ][$ j ] = Coordinate::coordinateFromString (
856
- $ this ->cellReferenceHelper ->updateCellReference ($ range [$ i ][$ j ] . '1 ' )
905
+ $ this ->cellReferenceHelper ->updateCellReference ($ range [$ i ][$ j ] . '1 ' , $ includeAbsoluteReferences )
857
906
)[0 ];
858
907
} elseif (ctype_digit ($ range [$ i ][$ j ])) {
859
908
$ range [$ i ][$ j ] = Coordinate::coordinateFromString (
860
- $ this ->cellReferenceHelper ->updateCellReference ('A ' . $ range [$ i ][$ j ])
909
+ $ this ->cellReferenceHelper ->updateCellReference ('A ' . $ range [$ i ][$ j ], $ includeAbsoluteReferences )
861
910
)[1 ];
862
911
} else {
863
- $ range [$ i ][$ j ] = $ this ->cellReferenceHelper ->updateCellReference ($ range [$ i ][$ j ]);
912
+ $ range [$ i ][$ j ] = $ this ->cellReferenceHelper ->updateCellReference ($ range [$ i ][$ j ], $ includeAbsoluteReferences );
864
913
}
865
914
}
866
915
}
@@ -985,17 +1034,8 @@ private function duplicateStylesByColumn(Worksheet $worksheet, int $beforeColumn
985
1034
$ coordinate = $ beforeColumnName . $ i ;
986
1035
if ($ worksheet ->cellExists ($ coordinate )) {
987
1036
$ xfIndex = $ worksheet ->getCell ($ coordinate )->getXfIndex ();
988
- $ conditionalStyles = $ worksheet ->conditionalStylesExists ($ coordinate ) ?
989
- $ worksheet ->getConditionalStyles ($ coordinate ) : false ;
990
1037
for ($ j = $ beforeColumn ; $ j <= $ beforeColumn - 1 + $ numberOfColumns ; ++$ j ) {
991
1038
$ worksheet ->getCellByColumnAndRow ($ j , $ i )->setXfIndex ($ xfIndex );
992
- if ($ conditionalStyles ) {
993
- $ cloned = [];
994
- foreach ($ conditionalStyles as $ conditionalStyle ) {
995
- $ cloned [] = clone $ conditionalStyle ;
996
- }
997
- $ worksheet ->setConditionalStyles (Coordinate::stringFromColumnIndex ($ j ) . $ i , $ cloned );
998
- }
999
1039
}
1000
1040
}
1001
1041
}
@@ -1009,17 +1049,8 @@ private function duplicateStylesByRow(Worksheet $worksheet, int $beforeColumn, i
1009
1049
$ coordinate = Coordinate::stringFromColumnIndex ($ i ) . ($ beforeRow - 1 );
1010
1050
if ($ worksheet ->cellExists ($ coordinate )) {
1011
1051
$ xfIndex = $ worksheet ->getCell ($ coordinate )->getXfIndex ();
1012
- $ conditionalStyles = $ worksheet ->conditionalStylesExists ($ coordinate ) ?
1013
- $ worksheet ->getConditionalStyles ($ coordinate ) : false ;
1014
1052
for ($ j = $ beforeRow ; $ j <= $ beforeRow - 1 + $ numberOfRows ; ++$ j ) {
1015
1053
$ worksheet ->getCell (Coordinate::stringFromColumnIndex ($ i ) . $ j )->setXfIndex ($ xfIndex );
1016
- if ($ conditionalStyles ) {
1017
- $ cloned = [];
1018
- foreach ($ conditionalStyles as $ conditionalStyle ) {
1019
- $ cloned [] = clone $ conditionalStyle ;
1020
- }
1021
- $ worksheet ->setConditionalStyles (Coordinate::stringFromColumnIndex ($ i ) . $ j , $ cloned );
1022
- }
1023
1054
}
1024
1055
}
1025
1056
}
0 commit comments