@@ -15,10 +15,12 @@ class ReferenceHelper
1515{
1616 /** Constants */
1717 /** Regular Expressions */
18- const REFHELPER_REGEXP_CELLREF = '((\w*| \'[^!]* \')!)?(?<![:a-z\$])(\$?[a-z]{1,3}\$?\d+)(?=[^:!\d \']) ' ;
19- const REFHELPER_REGEXP_CELLRANGE = '((\w*| \'[^!]* \')!)?(\$?[a-z]{1,3}\$?\d+):(\$?[a-z]{1,3}\$?\d+) ' ;
20- const REFHELPER_REGEXP_ROWRANGE = '((\w*| \'[^!]* \')!)?(\$?\d+):(\$?\d+) ' ;
21- const REFHELPER_REGEXP_COLRANGE = '((\w*| \'[^!]* \')!)?(\$?[a-z]{1,3}):(\$?[a-z]{1,3}) ' ;
18+ private const SHEETNAME_PART = '((\w*| \'[^!]* \')!) ' ;
19+ private const SHEETNAME_PART_WITH_SLASHES = '/ ' . self ::SHEETNAME_PART . '/ ' ;
20+ const REFHELPER_REGEXP_CELLREF = self ::SHEETNAME_PART . '?(?<![:a-z1-9_\.\$])(\$?[a-z]{1,3}\$?\d+)(?=[^:!\d \']) ' ;
21+ const REFHELPER_REGEXP_CELLRANGE = self ::SHEETNAME_PART . '?(\$?[a-z]{1,3}\$?\d+):(\$?[a-z]{1,3}\$?\d+) ' ;
22+ const REFHELPER_REGEXP_ROWRANGE = self ::SHEETNAME_PART . '?(\$?\d+):(\$?\d+) ' ;
23+ const REFHELPER_REGEXP_COLRANGE = self ::SHEETNAME_PART . '?(\$?[a-z]{1,3}):(\$?[a-z]{1,3}) ' ;
2224
2325 /**
2426 * Instance of this class.
@@ -545,6 +547,18 @@ public function insertNewBefore(
545547 $ worksheet ->garbageCollect ();
546548 }
547549
550+ private static function matchSheetName (?string $ match , string $ worksheetName ): bool
551+ {
552+ return $ match === null || $ match === '' || $ match === "' \u{fffc}' " || $ match === "' \u{fffb}' " || strcasecmp (trim ($ match , "' " ), $ worksheetName ) === 0 ;
553+ }
554+
555+ private static function sheetnameBeforeCells (string $ match , string $ worksheetName , string $ cells ): string
556+ {
557+ $ toString = ($ match > '' ) ? "$ match! " : '' ;
558+
559+ return str_replace (["\u{fffc}" , "' \u{fffb}' " ], $ worksheetName , $ toString ) . $ cells ;
560+ }
561+
548562 /**
549563 * Update references within formulas.
550564 *
@@ -565,6 +579,7 @@ public function updateFormulaReferences(
565579 bool $ includeAbsoluteReferences = false ,
566580 bool $ onlyAbsoluteReferences = false
567581 ): string {
582+ $ callback = fn (array $ matches ): string => (strcasecmp (trim ($ matches [2 ], "' " ), $ worksheetName ) === 0 ) ? (($ matches [2 ][0 ] === "' " ) ? "' \u{fffc}'! " : "' \u{fffb}'! " ) : "' \u{fffd}'! " ;
568583 if (
569584 $ this ->cellReferenceHelper === null
570585 || $ this ->cellReferenceHelper ->refreshRequired ($ beforeCellAddress , $ numberOfColumns , $ numberOfRows )
@@ -582,18 +597,17 @@ public function updateFormulaReferences(
582597 $ adjustCount = 0 ;
583598 $ newCellTokens = $ cellTokens = [];
584599 // Search for row ranges (e.g. 'Sheet1'!3:5 or 3:5) with or without $ absolutes (e.g. $3:5)
585- $ matchCount = preg_match_all ('/ ' . self ::REFHELPER_REGEXP_ROWRANGE . '/mui ' , ' ' . $ formulaBlock . ' ' , $ matches , PREG_SET_ORDER );
600+ $ formulaBlockx = ' ' . (preg_replace_callback (self ::SHEETNAME_PART_WITH_SLASHES , $ callback , $ formulaBlock ) ?? $ formulaBlock ) . ' ' ;
601+ $ matchCount = preg_match_all ('/ ' . self ::REFHELPER_REGEXP_ROWRANGE . '/mui ' , $ formulaBlockx , $ matches , PREG_SET_ORDER );
586602 if ($ matchCount > 0 ) {
587603 foreach ($ matches as $ match ) {
588- $ fromString = ($ match [2 ] > '' ) ? $ match [2 ] . '! ' : '' ;
589- $ fromString .= $ match [3 ] . ': ' . $ match [4 ];
604+ $ fromString = self ::sheetnameBeforeCells ($ match [2 ], $ worksheetName , "{$ match [3 ]}: {$ match [4 ]}" );
590605 $ modified3 = substr ($ this ->updateCellReference ('$A ' . $ match [3 ], $ includeAbsoluteReferences , $ onlyAbsoluteReferences ), 2 );
591606 $ modified4 = substr ($ this ->updateCellReference ('$A ' . $ match [4 ], $ includeAbsoluteReferences , $ onlyAbsoluteReferences ), 2 );
592607
593608 if ($ match [3 ] . ': ' . $ match [4 ] !== $ modified3 . ': ' . $ modified4 ) {
594- if (($ match [2 ] == '' ) || (trim ($ match [2 ], "' " ) == $ worksheetName )) {
595- $ toString = ($ match [2 ] > '' ) ? $ match [2 ] . '! ' : '' ;
596- $ toString .= $ modified3 . ': ' . $ modified4 ;
609+ if (self ::matchSheetName ($ match [2 ], $ worksheetName )) {
610+ $ toString = self ::sheetnameBeforeCells ($ match [2 ], $ worksheetName , "$ modified3: $ modified4 " );
597611 // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
598612 $ column = 100000 ;
599613 $ row = 10000000 + (int ) trim ($ match [3 ], '$ ' );
@@ -607,18 +621,17 @@ public function updateFormulaReferences(
607621 }
608622 }
609623 // Search for column ranges (e.g. 'Sheet1'!C:E or C:E) with or without $ absolutes (e.g. $C:E)
610- $ matchCount = preg_match_all ('/ ' . self ::REFHELPER_REGEXP_COLRANGE . '/mui ' , ' ' . $ formulaBlock . ' ' , $ matches , PREG_SET_ORDER );
624+ $ formulaBlockx = ' ' . (preg_replace_callback (self ::SHEETNAME_PART_WITH_SLASHES , $ callback , $ formulaBlock ) ?? $ formulaBlock ) . ' ' ;
625+ $ matchCount = preg_match_all ('/ ' . self ::REFHELPER_REGEXP_COLRANGE . '/mui ' , $ formulaBlockx , $ matches , PREG_SET_ORDER );
611626 if ($ matchCount > 0 ) {
612627 foreach ($ matches as $ match ) {
613- $ fromString = ($ match [2 ] > '' ) ? $ match [2 ] . '! ' : '' ;
614- $ fromString .= $ match [3 ] . ': ' . $ match [4 ];
628+ $ fromString = self ::sheetnameBeforeCells ($ match [2 ], $ worksheetName , "{$ match [3 ]}: {$ match [4 ]}" );
615629 $ modified3 = substr ($ this ->updateCellReference ($ match [3 ] . '$1 ' , $ includeAbsoluteReferences , $ onlyAbsoluteReferences ), 0 , -2 );
616630 $ modified4 = substr ($ this ->updateCellReference ($ match [4 ] . '$1 ' , $ includeAbsoluteReferences , $ onlyAbsoluteReferences ), 0 , -2 );
617631
618632 if ($ match [3 ] . ': ' . $ match [4 ] !== $ modified3 . ': ' . $ modified4 ) {
619- if (($ match [2 ] == '' ) || (trim ($ match [2 ], "' " ) == $ worksheetName )) {
620- $ toString = ($ match [2 ] > '' ) ? $ match [2 ] . '! ' : '' ;
621- $ toString .= $ modified3 . ': ' . $ modified4 ;
633+ if (self ::matchSheetName ($ match [2 ], $ worksheetName )) {
634+ $ toString = self ::sheetnameBeforeCells ($ match [2 ], $ worksheetName , "$ modified3: $ modified4 " );
622635 // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
623636 $ column = Coordinate::columnIndexFromString (trim ($ match [3 ], '$ ' )) + 100000 ;
624637 $ row = 10000000 ;
@@ -632,18 +645,17 @@ public function updateFormulaReferences(
632645 }
633646 }
634647 // Search for cell ranges (e.g. 'Sheet1'!A3:C5 or A3:C5) with or without $ absolutes (e.g. $A1:C$5)
635- $ matchCount = preg_match_all ('/ ' . self ::REFHELPER_REGEXP_CELLRANGE . '/mui ' , ' ' . $ formulaBlock . ' ' , $ matches , PREG_SET_ORDER );
648+ $ formulaBlockx = ' ' . (preg_replace_callback (self ::SHEETNAME_PART_WITH_SLASHES , $ callback , "$ formulaBlock " ) ?? "$ formulaBlock " ) . ' ' ;
649+ $ matchCount = preg_match_all ('/ ' . self ::REFHELPER_REGEXP_CELLRANGE . '/mui ' , $ formulaBlockx , $ matches , PREG_SET_ORDER );
636650 if ($ matchCount > 0 ) {
637651 foreach ($ matches as $ match ) {
638- $ fromString = ($ match [2 ] > '' ) ? $ match [2 ] . '! ' : '' ;
639- $ fromString .= $ match [3 ] . ': ' . $ match [4 ];
652+ $ fromString = self ::sheetnameBeforeCells ($ match [2 ], $ worksheetName , "{$ match [3 ]}: {$ match [4 ]}" );
640653 $ modified3 = $ this ->updateCellReference ($ match [3 ], $ includeAbsoluteReferences , $ onlyAbsoluteReferences );
641654 $ modified4 = $ this ->updateCellReference ($ match [4 ], $ includeAbsoluteReferences , $ onlyAbsoluteReferences );
642655
643656 if ($ match [3 ] . $ match [4 ] !== $ modified3 . $ modified4 ) {
644- if (($ match [2 ] == '' ) || (trim ($ match [2 ], "' " ) == $ worksheetName )) {
645- $ toString = ($ match [2 ] > '' ) ? $ match [2 ] . '! ' : '' ;
646- $ toString .= $ modified3 . ': ' . $ modified4 ;
657+ if (self ::matchSheetName ($ match [2 ], $ worksheetName )) {
658+ $ toString = self ::sheetnameBeforeCells ($ match [2 ], $ worksheetName , "$ modified3: $ modified4 " );
647659 [$ column , $ row ] = Coordinate::coordinateFromString ($ match [3 ]);
648660 // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
649661 $ column = Coordinate::columnIndexFromString (trim ($ column , '$ ' )) + 100000 ;
@@ -658,18 +670,18 @@ public function updateFormulaReferences(
658670 }
659671 }
660672 // Search for cell references (e.g. 'Sheet1'!A3 or C5) with or without $ absolutes (e.g. $A1 or C$5)
661- $ matchCount = preg_match_all ('/ ' . self ::REFHELPER_REGEXP_CELLREF . '/mui ' , ' ' . $ formulaBlock . ' ' , $ matches , PREG_SET_ORDER );
673+
674+ $ formulaBlockx = ' ' . (preg_replace_callback (self ::SHEETNAME_PART_WITH_SLASHES , $ callback , $ formulaBlock ) ?? $ formulaBlock ) . ' ' ;
675+ $ matchCount = preg_match_all ('/ ' . self ::REFHELPER_REGEXP_CELLREF . '/mui ' , $ formulaBlockx , $ matches , PREG_SET_ORDER );
662676
663677 if ($ matchCount > 0 ) {
664678 foreach ($ matches as $ match ) {
665- $ fromString = ($ match [2 ] > '' ) ? $ match [2 ] . '! ' : '' ;
666- $ fromString .= $ match [3 ];
679+ $ fromString = self ::sheetnameBeforeCells ($ match [2 ], $ worksheetName , "{$ match [3 ]}" );
667680
668681 $ modified3 = $ this ->updateCellReference ($ match [3 ], $ includeAbsoluteReferences , $ onlyAbsoluteReferences );
669682 if ($ match [3 ] !== $ modified3 ) {
670- if (($ match [2 ] == '' ) || (trim ($ match [2 ], "' " ) == $ worksheetName )) {
671- $ toString = ($ match [2 ] > '' ) ? $ match [2 ] . '! ' : '' ;
672- $ toString .= $ modified3 ;
683+ if (self ::matchSheetName ($ match [2 ], $ worksheetName )) {
684+ $ toString = self ::sheetnameBeforeCells ($ match [2 ], $ worksheetName , "$ modified3 " );
673685 [$ column , $ row ] = Coordinate::coordinateFromString ($ match [3 ]);
674686 $ columnAdditionalIndex = $ column [0 ] === '$ ' ? 1 : 0 ;
675687 $ rowAdditionalIndex = $ row [0 ] === '$ ' ? 1 : 0 ;
0 commit comments