这是RegEx是否与Excel公式中的任何单元格引用匹配?

我一直在尝试创build一个正则expression式模式,它匹配任何Excel公式中的任何引用,包括绝对引用,相对引用和外部引用。 我需要返回整个引用,包括工作表和工作簿名称。

我一直无法find有关Excel A1-notation的详尽文档,但是通过大量testing,我确定了以下内容:

  • 公式前面加上等号“=”
  • 公式中的string用双引号括起来,在查找真正的引用之前需要删除,否则=A1&"A1"会打破正则expression式
  • 工作表名称最多可以有31个字符,不包括\ /? * []:
  • 外部引用中的工作表名称必须成功使用bang =Sheet1!A1
  • 外部引用中的工作簿名称必须用方括号括起来=[Book1.xlsx]Sheet1!A1
  • 工作簿path(如果引用是closures工作簿中的范围,则Excel将添加)始终用单引号括起来,并放在工作簿名称'C:\[Book1.xlsx]Sheet1'!A1的括号左侧'C:\[Book1.xlsx]Sheet1'!A1
  • 某些字符(例如,非中断空格)导致Excel将工作簿和工作表名称括在单引号中的外部引用中, 但是我不知道哪些字符 ='[Book 1.xlsx]Sheet 1'!A1
  • 即使启用R1C1-notation, Range.Formula仍然以A1表示法返回引用。 Range.FormulaR1C1返回R1C1表示法中的引用。
  • 3D参考样式允许一个工作簿上的一系列工作表名称=SUM([Book5]Sheet1:Sheet3!A1)
  • 命名范围可以用公式指定:
    • 名称的第一个字符必须是字母,下划线字符(_)或反斜杠(\)。 名称中剩余的字符可以是字母,数字,句点和下划线字符。
    • 您不能将大写和小写字符“C”,“c”,“R”或“r”用作定义名称,因为它们全部用作select当前选定单元格的行或列的简写forms在“名称”或“转到”文本框中input它们。
    • 名称不能与单元格引用相同,例如Z $ 100或R1C1。
    • 空间不允许作为名字的一部分。
    • 名称最长可以有255个字符。
    • 名称可以包含大写和小写字母。 Excel不区分名称中的大写和小写字符。

这是我想出来的包装在VBA程序中进行testing。 我更新了代码以处理名称:

 Sub ReturnFormulaReferences() Dim objRegExp As New VBScript_RegExp_55.RegExp Dim objCell As Range Dim objStringMatches As Object Dim objReferenceMatches As Object Dim objMatch As Object Dim intReferenceCount As Integer Dim intIndex As Integer Dim booIsReference As Boolean Dim objName As Name Dim booNameFound As Boolean With objRegExp .MultiLine = True .Global = True .IgnoreCase = True End With For Each objCell In Selection.Cells If Left(objCell.Formula, 1) = "=" Then objRegExp.Pattern = "\"".*\""" Set objStringMatches = objRegExp.Execute(objCell.Formula) objRegExp.Pattern = "(\'.*(\[.*\])?([^\:\\\/\?\*\[\]]{1,31}\:)?[^\:\\\/\?\*\[\]]{1,31}\'\!" _ & "|(\[.*\])?([^\:\\\/\?\*\[\]]{1,31}\:)?[^\:\\\/\?\*\[\]]{1,31}\!)?" _ & "(\$?[az]{1,3}\$?[0-9]{1,7}(\:\$?[az]{1,3}\$?[0-9]{1,7})?" _ & "|\$[az]{1,3}\:\$[az]{1,3}" _ & "|[az]{1,3}\:[az]{1,3}" _ & "|\$[0-9]{1,7}\:\$[0-9]{1,7}" _ & "|[0-9]{1,7}\:[0-9]{1,7}" _ & "|[a-z_\\][a-z0-9_\.]{0,254})" Set objReferenceMatches = objRegExp.Execute(objCell.Formula) intReferenceCount = 0 For Each objMatch In objReferenceMatches intReferenceCount = intReferenceCount + 1 Next Debug.Print objCell.Formula For intIndex = intReferenceCount - 1 To 0 Step -1 booIsReference = True For Each objMatch In objStringMatches If objReferenceMatches(intIndex).FirstIndex > objMatch.FirstIndex _ And objReferenceMatches(intIndex).FirstIndex < objMatch.FirstIndex + objMatch.Length Then booIsReference = False Exit For End If Next If booIsReference Then objRegExp.Pattern = "(\'.*(\[.*\])?([^\:\\\/\?\*\[\]]{1,31}\:)?[^\:\\\/\?\*\[\]]{1,31}\'\!" _ & "|(\[.*\])?([^\:\\\/\?\*\[\]]{1,31}\:)?[^\:\\\/\?\*\[\]]{1,31}\!)?" _ & "(\$?[az]{1,3}\$?[0-9]{1,7}(\:\$?[az]{1,3}\$?[0-9]{1,7})?" _ & "|\$[az]{1,3}\:\$[az]{1,3}" _ & "|[az]{1,3}\:[az]{1,3}" _ & "|\$[0-9]{1,7}\:\$[0-9]{1,7}" _ & "|[0-9]{1,7}\:[0-9]{1,7})" If Not objRegExp.Test(objReferenceMatches(intIndex).Value) Then 'reference is not A1 objRegExp.Pattern = "^(\'.*(\[.*\])?([^\:\\\/\?\*\[\]]{1,31}\:)?[^\:\\\/\?\*\[\]]{1,31}\'\!" _ & "|(\[.*\])?([^\:\\\/\?\*\[\]]{1,31}\:)?[^\:\\\/\?\*\[\]]{1,31}\!)" _ & "[a-z_\\][a-z0-9_\.]{0,254}$" If Not objRegExp.Test(objReferenceMatches(intIndex).Value) Then 'name is not external booNameFound = False For Each objName In objCell.Worksheet.Parent.Names If objReferenceMatches(intIndex).Value = objName.Name Then booNameFound = True Exit For End If Next If Not booNameFound Then objRegExp.Pattern = "^(\'.*(\[.*\])?([^\:\\\/\?\*\[\]]{1,31}\:)?[^\:\\\/\?\*\[\]]{1,31}\'\!" _ & "|(\[.*\])?([^\:\\\/\?\*\[\]]{1,31}\:)?[^\:\\\/\?\*\[\]]{1,31}\!)" For Each objName In objCell.Worksheet.Names If objReferenceMatches(intIndex).Value = objRegExp.Replace(objName.Name, "") Then booNameFound = True Exit For End If Next End If booIsReference = booNameFound End If End If End If If booIsReference Then Debug.Print " " & objReferenceMatches(intIndex).Value _ & " (" & objReferenceMatches(intIndex).FirstIndex & ", " _ & objReferenceMatches(intIndex).Length & ")" End If Next intIndex Debug.Print End If Next Set objRegExp = Nothing Set objStringMatches = Nothing Set objReferenceMatches = Nothing Set objMatch = Nothing Set objCell = Nothing Set objName = Nothing End Sub 

任何人都可以打破或改善这个? 没有Excel公式语法的详尽文档,很难知道这是否正确。

谢谢!

jtolle把我引向了正确的方向。 据我所知,这正是我想要做的。 我一直在testing,似乎工作。

 stringOriginFormula = rangeOrigin.Formula rangeOrigin.Cut rangeDestination rangeOrigin.Formula = stringOriginFormula 

谢谢jtolle!