正则表达式,用于确定字符串是范围的名称还是单元格的地址

时间:2016-11-01 22:05:18

标签: regex excel excel-vba vba

我正在努力想出一个正则表达式模式,它可以帮助我确定字符串是单元格的地址还是单元格的名称。

以下是单元格地址的一些示例:

  • “E5”
  • “AA55:E5”
  • “DD5555:DDD55555,E5,F5:AA55”
  • “$ F7:$ G $ 7”

以下是单元名称的一些示例:

  • “bis_document_id”
  • “PCR1MM_YPCVolume”
  • “sheet_error7”
  • “blahE5”
  • “training_A1”
  • “myNameIsGeorgeJR”

有没有一个正则表达式模式,你们可以想出哪个匹配任何一个组都没有?

我已经能够想出几种方法来确定字符串不是什么:

  • 如果其中包含除“$”或“:”之外的任何其他字符,我知道它不是单元格的名称,很可能是单元格的地址。
  • 如果连续数超过三个,则很可能不是单元格的地址。
  • 单元格的地址极不可能在数字前面加上2个以上的字母,99.9%的单元格地址将在A到ZZ列中。
唉,这三个小测试很难证明这个字符串是什么。

感谢您的帮助!

3 个答案:

答案 0 :(得分:4)

好的,这个很有趣:

^\$?[A-Z]+\$?\d+(?::\$?[A-Z]+\$?\d+)?(?:,\s*(?:\$?[A-Z]+\$?\d+(?::\$?[A-Z]+\$?\d+)?))*$

让它分解,因为它相当令人讨厌。真正的神奇子模式就是:

\$?[A-Z]+\$?\d+

这个小东西将匹配任何单个有效单元格地址,并带有可选的绝对值$ s。下一位,

(?::\$?[A-Z]+\$?\d+)?

会选择匹配相同的东西(最后是?量词),但前面跟冒号(:)。这让我们得到了范围。下一位,

(?:,\s*(?:\$?[A-Z]+\$?\d+(?::\$?[A-Z]+\$?\d+)?))*

匹配与第一个相同的东西,但是零次或多次(使用*量词),并且前面有逗号和可选空格,使用特殊的\s标记(这意味着&#34 ;任何空白")。

Demo on Regex101

如果我们想要变得非常花哨(并且,请注意,我不知道Excel的正则表达式引擎是否支持这个;我只是为了好玩而写它),我们可以使用recursion来完成同样的事情:

^((\$?[A-Z]+\$?\d+)(?::(?2))?)(?:,\s*(?1))*$

在这种情况下,魔术\$?[A-Z]+\$?\d+位于第二个捕获组内,由(?2)令牌递归使用。单个地址或范围的整个子模式包含在第一个捕获组中,然后用于匹配列表中的其他地址或范围。

Demo on Regex101

答案 1 :(得分:1)

所以这里是VBA的正则表达式,它将找到任何单元格引用,无论它在哪里。

注意:我假设您在Formula对象上执行此操作,因此不需要位于字符串的开头或结尾;所以你可以有一个包含单元格引用和单元格名称的字符串,它只会获取单元格引用,如下所示:

(?:\W|^)(\$?[A-Z]{1,3}\$?[0-9]{1,7}(:\$?[A-Z]{1,3}\$?[0-9]{1,7})?)(?!\w)

(?:\W|^)位于开头,确保在字符串或字符串开头之前有一个非单词字符(如果始终有|^,则删除=Formula个对象开始)--- VBA我发现遗憾的是没有正常的负面看法背后)

(\$?[A-Z]{1,3}\$?[0-9]{1,7}(:\$?[A-Z]{1,3}\$?[0-9]{1,7})?)找到实际的单元格引用,并在下面细分:

  • \$?[A-Z]{1,3}\$?[0-9]{1,7}匹配一至三个大写字母(适用于Excel的可能当前范围;
  • (:\$?[A-Z]{1,3}\$?[0-9]{1,7})?与上述内容相同,只是在列?使其成为可选项后,它会添加第二个单元格引用的选项。

(?!\w)是一个消极的期待,并说它后面的字符不能是一个单词字符(可能在函数中,你可以在单元格引用周围唯一的东西是括号和运算符)。

我在Excel中编写了一个VBA函数,并使用上面的RegEx返回了以下内容:

RegEx Output

注意:如果字符的顺序正确,则显然不会显示,因为尽管不可能,但仍会返回引用$AZO113:A4

答案 2 :(得分:0)

在尝试了几个解决方案后,我不得不修改一个正则表达式,所以它对我有用。我的版本只支持非命名范围。

((?![\=,\(\);])(\w+!)|('.+'!))?((\$?[A-Z]{1,3}\$?[0-9]{1,7}(:\$?[A-Z]{1,3}\$?[0-9]{1,7})?)|(\$?[A-Z]{1,3}(:\$?[A-Z]{1,3}\$?)))

它将在以下所有情况下捕获范围

=FUNCTION(F:F)
=FUNCTION($B22,G$5)
=SUM($F$10:$F$11)
=$J10-$K10
=SUMMARY!D4

我为RegEx创建了以下函数。但首先勾选参考" Microsoft VBScript正则表达式5.5"来自工具>参考文献

Function RegExp(ByVal sText As String, ByVal sPattern, Optional bGlobal As Boolean = True, Optional bIgnoreCase As Boolean = False, Optional bArray As Boolean = False) As Variant
    Dim objRegex As New RegExp
    Dim Matches As MatchCollection
    Dim Match As Match
    Dim i As Integer
    objRegex.IgnoreCase = bIgnoreCase
    objRegex.Global = bGlobal
    objRegex.Pattern = sPattern
    If objRegex.test(sText) Then
        Set Matches = objRegex.Execute(sText)
        If Matches.count <> 0 Then
            If bArray Then ' if we want to return array instead of MatchCollection
                ReDim aMatches(Matches.count - 1) As Variant
                For Each Match In Matches
                    aMatches(i) = Match.value
                    i = i + 1
                Next
                RegExp = aMatches
            Else
                Set RegExp = Matches
            End If
        End If
    End If
End Function