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,39 @@ 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 , $ this ->cellReferenceHelper ->beforeCellAddress (), $ numberOfColumns , $ numberOfRows , $ worksheet ->getTitle (), true );
227
+ }
228
+ }
229
+ $ cfRule ->setConditions ($ conditions );
230
+ }
231
+ $ worksheet ->setConditionalStyles ($ newReference , $ cfRules );
232
+ }
233
+ }
234
+
201
235
/**
202
236
* Update data validations when inserting/deleting rows/columns.
203
237
*
@@ -442,6 +476,9 @@ function ($coordinate) use ($allCoordinates) {
442
476
// Update worksheet: hyperlinks
443
477
$ this ->adjustHyperlinks ($ worksheet , $ numberOfColumns , $ numberOfRows );
444
478
479
+ // Update worksheet: conditional formatting styles
480
+ $ this ->adjustConditionalFormatting ($ worksheet , $ numberOfColumns , $ numberOfRows );
481
+
445
482
// Update worksheet: data validations
446
483
$ this ->adjustDataValidations ($ worksheet , $ numberOfColumns , $ numberOfRows );
447
484
@@ -505,8 +542,14 @@ function ($coordinate) use ($allCoordinates) {
505
542
*
506
543
* @return string Updated formula
507
544
*/
508
- public function updateFormulaReferences ($ formula = '' , $ beforeCellAddress = 'A1 ' , $ numberOfColumns = 0 , $ numberOfRows = 0 , $ worksheetName = '' )
509
- {
545
+ public function updateFormulaReferences (
546
+ $ formula = '' ,
547
+ $ beforeCellAddress = 'A1 ' ,
548
+ $ numberOfColumns = 0 ,
549
+ $ numberOfRows = 0 ,
550
+ $ worksheetName = '' ,
551
+ bool $ includeAbsoluteReferences = false
552
+ ) {
510
553
if (
511
554
$ this ->cellReferenceHelper === null ||
512
555
$ this ->cellReferenceHelper ->refreshRequired ($ beforeCellAddress , $ numberOfColumns , $ numberOfRows )
@@ -528,8 +571,8 @@ public function updateFormulaReferences($formula = '', $beforeCellAddress = 'A1'
528
571
foreach ($ matches as $ match ) {
529
572
$ fromString = ($ match [2 ] > '' ) ? $ match [2 ] . '! ' : '' ;
530
573
$ fromString .= $ match [3 ] . ': ' . $ match [4 ];
531
- $ modified3 = substr ($ this ->updateCellReference ('$A ' . $ match [3 ]), 2 );
532
- $ modified4 = substr ($ this ->updateCellReference ('$A ' . $ match [4 ]), 2 );
574
+ $ modified3 = substr ($ this ->updateCellReference ('$A ' . $ match [3 ], $ includeAbsoluteReferences ), 2 );
575
+ $ modified4 = substr ($ this ->updateCellReference ('$A ' . $ match [4 ], $ includeAbsoluteReferences ), 2 );
533
576
534
577
if ($ match [3 ] . ': ' . $ match [4 ] !== $ modified3 . ': ' . $ modified4 ) {
535
578
if (($ match [2 ] == '' ) || (trim ($ match [2 ], "' " ) == $ worksheetName )) {
@@ -553,8 +596,8 @@ public function updateFormulaReferences($formula = '', $beforeCellAddress = 'A1'
553
596
foreach ($ matches as $ match ) {
554
597
$ fromString = ($ match [2 ] > '' ) ? $ match [2 ] . '! ' : '' ;
555
598
$ 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 );
599
+ $ modified3 = substr ($ this ->updateCellReference ($ match [3 ] . '$1 ' , $ includeAbsoluteReferences ), 0 , -2 );
600
+ $ modified4 = substr ($ this ->updateCellReference ($ match [4 ] . '$1 ' , $ includeAbsoluteReferences ), 0 , -2 );
558
601
559
602
if ($ match [3 ] . ': ' . $ match [4 ] !== $ modified3 . ': ' . $ modified4 ) {
560
603
if (($ match [2 ] == '' ) || (trim ($ match [2 ], "' " ) == $ worksheetName )) {
@@ -578,8 +621,8 @@ public function updateFormulaReferences($formula = '', $beforeCellAddress = 'A1'
578
621
foreach ($ matches as $ match ) {
579
622
$ fromString = ($ match [2 ] > '' ) ? $ match [2 ] . '! ' : '' ;
580
623
$ fromString .= $ match [3 ] . ': ' . $ match [4 ];
581
- $ modified3 = $ this ->updateCellReference ($ match [3 ]);
582
- $ modified4 = $ this ->updateCellReference ($ match [4 ]);
624
+ $ modified3 = $ this ->updateCellReference ($ match [3 ], $ includeAbsoluteReferences );
625
+ $ modified4 = $ this ->updateCellReference ($ match [4 ], $ includeAbsoluteReferences );
583
626
584
627
if ($ match [3 ] . $ match [4 ] !== $ modified3 . $ modified4 ) {
585
628
if (($ match [2 ] == '' ) || (trim ($ match [2 ], "' " ) == $ worksheetName )) {
@@ -606,7 +649,7 @@ public function updateFormulaReferences($formula = '', $beforeCellAddress = 'A1'
606
649
$ fromString = ($ match [2 ] > '' ) ? $ match [2 ] . '! ' : '' ;
607
650
$ fromString .= $ match [3 ];
608
651
609
- $ modified3 = $ this ->updateCellReference ($ match [3 ]);
652
+ $ modified3 = $ this ->updateCellReference ($ match [3 ], $ includeAbsoluteReferences );
610
653
if ($ match [3 ] !== $ modified3 ) {
611
654
if (($ match [2 ] == '' ) || (trim ($ match [2 ], "' " ) == $ worksheetName )) {
612
655
$ toString = ($ match [2 ] > '' ) ? $ match [2 ] . '! ' : '' ;
@@ -786,18 +829,18 @@ private function updateRowRangesAllWorksheets(string $formula, int $numberOfRows
786
829
*
787
830
* @return string Updated cell range
788
831
*/
789
- private function updateCellReference ($ cellReference = 'A1 ' )
832
+ private function updateCellReference ($ cellReference = 'A1 ' , bool $ includeAbsoluteReferences = false )
790
833
{
791
834
// Is it in another worksheet? Will not have to update anything.
792
835
if (strpos ($ cellReference , '! ' ) !== false ) {
793
836
return $ cellReference ;
794
837
// Is it a range or a single cell?
795
838
} elseif (!Coordinate::coordinateIsRange ($ cellReference )) {
796
839
// Single cell
797
- return $ this ->cellReferenceHelper ->updateCellReference ($ cellReference );
840
+ return $ this ->cellReferenceHelper ->updateCellReference ($ cellReference, $ includeAbsoluteReferences );
798
841
} elseif (Coordinate::coordinateIsRange ($ cellReference )) {
799
842
// Range
800
- return $ this ->updateCellRange ($ cellReference );
843
+ return $ this ->updateCellRange ($ cellReference, $ includeAbsoluteReferences );
801
844
}
802
845
803
846
// Return original
@@ -839,7 +882,7 @@ public function updateNamedFormulas(Spreadsheet $spreadsheet, $oldName = '', $ne
839
882
*
840
883
* @return string Updated cell range
841
884
*/
842
- private function updateCellRange (string $ cellRange = 'A1:A1 ' ): string
885
+ private function updateCellRange (string $ cellRange = 'A1:A1 ' , bool $ includeAbsoluteReferences = false ): string
843
886
{
844
887
if (!Coordinate::coordinateIsRange ($ cellRange )) {
845
888
throw new Exception ('Only cell ranges may be passed to this method. ' );
@@ -853,14 +896,14 @@ private function updateCellRange(string $cellRange = 'A1:A1'): string
853
896
for ($ j = 0 ; $ j < $ jc ; ++$ j ) {
854
897
if (ctype_alpha ($ range [$ i ][$ j ])) {
855
898
$ range [$ i ][$ j ] = Coordinate::coordinateFromString (
856
- $ this ->cellReferenceHelper ->updateCellReference ($ range [$ i ][$ j ] . '1 ' )
899
+ $ this ->cellReferenceHelper ->updateCellReference ($ range [$ i ][$ j ] . '1 ' , $ includeAbsoluteReferences )
857
900
)[0 ];
858
901
} elseif (ctype_digit ($ range [$ i ][$ j ])) {
859
902
$ range [$ i ][$ j ] = Coordinate::coordinateFromString (
860
- $ this ->cellReferenceHelper ->updateCellReference ('A ' . $ range [$ i ][$ j ])
903
+ $ this ->cellReferenceHelper ->updateCellReference ('A ' . $ range [$ i ][$ j ], $ includeAbsoluteReferences )
861
904
)[1 ];
862
905
} else {
863
- $ range [$ i ][$ j ] = $ this ->cellReferenceHelper ->updateCellReference ($ range [$ i ][$ j ]);
906
+ $ range [$ i ][$ j ] = $ this ->cellReferenceHelper ->updateCellReference ($ range [$ i ][$ j ], $ includeAbsoluteReferences );
864
907
}
865
908
}
866
909
}
@@ -985,17 +1028,8 @@ private function duplicateStylesByColumn(Worksheet $worksheet, int $beforeColumn
985
1028
$ coordinate = $ beforeColumnName . $ i ;
986
1029
if ($ worksheet ->cellExists ($ coordinate )) {
987
1030
$ xfIndex = $ worksheet ->getCell ($ coordinate )->getXfIndex ();
988
- $ conditionalStyles = $ worksheet ->conditionalStylesExists ($ coordinate ) ?
989
- $ worksheet ->getConditionalStyles ($ coordinate ) : false ;
990
1031
for ($ j = $ beforeColumn ; $ j <= $ beforeColumn - 1 + $ numberOfColumns ; ++$ j ) {
991
1032
$ 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
1033
}
1000
1034
}
1001
1035
}
@@ -1009,17 +1043,8 @@ private function duplicateStylesByRow(Worksheet $worksheet, int $beforeColumn, i
1009
1043
$ coordinate = Coordinate::stringFromColumnIndex ($ i ) . ($ beforeRow - 1 );
1010
1044
if ($ worksheet ->cellExists ($ coordinate )) {
1011
1045
$ xfIndex = $ worksheet ->getCell ($ coordinate )->getXfIndex ();
1012
- $ conditionalStyles = $ worksheet ->conditionalStylesExists ($ coordinate ) ?
1013
- $ worksheet ->getConditionalStyles ($ coordinate ) : false ;
1014
1046
for ($ j = $ beforeRow ; $ j <= $ beforeRow - 1 + $ numberOfRows ; ++$ j ) {
1015
1047
$ 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
1048
}
1024
1049
}
1025
1050
}
0 commit comments