在VBA

时间:2018-11-12 15:12:18

标签: excel vba string formula

在VBA中,我想搜索一个Excel公式(字符串)以查找单元格引用。

具体来说,我想在字符串中找到相对单元格引用(任何相对单元格引用,而不是特定的引用)或混合单元格引用的位置。

  • 我不需要查找绝对单元格引用,尽管我可以检查并忽略它们。
  • 我不介意参考文献是否在另一张纸上,我很高兴在!之后找到一点。符号。
  • 我将需要确保不会在字符串,工作表名称或数据名称中找到看起来像单元格引用的内容。

我该怎么做?(这是主要问题)

我的想法:

我可以看到如何找到混合单元格引用-我很确定$符号只能出现在混合单元格引用,绝对引用,内部工作表名称或内部字符串中(有人可以确认吗?) ,因此使用正确的正则表达式或算法,您可以找到所有这些情况,然后只需检查它是否是绝对单元格引用,然后忽略它即可。

但是如何找到所有相关的单元格引用呢?我唯一的想法与上述类似。除单元格引用外,Excel公式中(表名之外或字符串内)是否曾经有字母后面有数字?任何公式名称或其他名称?我能想到的唯一另一个是在定义的数据名称中,但是我不确定是否可以在公式(尤其是条件格式公式)中使用它们。谁能想到其他时间吗?

有人有什么想法吗?

1 个答案:

答案 0 :(得分:1)

我不确定您的用例是什么,但是您可以在此函数中尝试一些方法:

  

该项目使用 Early Binding -您必须将引用设置为:

Microsoft VBScript Regular Expressions 5.5
Function findCellReferences(vTestVal As Variant) As Variant

    'Check if vTestVal is a range, if so, convert to string
    If TypeName(vTestVal) = "Range" Then
        vTestVal = vTestVal.Formula
    ElseIf TypeName(vTestVal) <> "String" Then
        findCellReferences = "Type-Err!"
        Exit Function
    End If

    Dim oMatches As MatchCollection

    With New RegExp
        .Pattern = "(?:^|[,!(=\s])((?:\$?[A-Z]{1,3}\$?\d+(?::\$?[A-Z]{1,3}\$?\d+)?|" & _
                "\$?[a-z]{1,3}:\$?[a-z]{1,3}|\$?\d+:\$?\d+))(?:$|[\s,)])"
        .IgnoreCase = True
        .Global = True
        If .test(vTestVal) Then
            Dim i As Long, retArr()
            Set oMatches = .Execute(vTestVal)
            With oMatches
                ReDim retArr(.Count - 1)
                For i = 0 To .Count - 1
                    retArr(i) = .Item(i).SubMatches(0)
                Next
            End With
            findCellReferences = Join(retArr, ",")
        Else
            findCellReferences = False
        End If
    End With

End Function

此函数可以接受两种不同的数据类型:

  1. 范围
  2. 字符串

这使您可以将其用作工作表函数来测试公式的文本值,也可以将其直接用于测试输入字符串。

这是检查单元格的返回信息:

enter image description here

这是上面的公式:

enter image description here

这也可以在VBA中使用:

Sub Test()

    Rem: Passing a string argument
    Debug.Print findCellReferences("A1:B1, $C1")
    ' Prints: A1:B1,$C1

End Sub

打破正则表达式:Regex101

(?:^|[,!(=\s])((?:\$?[A-Z]{1,3}\$?\d+(?::\$?[A-Z]{1,3}\$?\d+)?|\$?[a-z]{1,3}:\$?
[a-z]{1,3}|\$?\d+:\$?\d+))(?:$|[\s,)])
  • (?:^|[,(=\s])要求在匹配之前之前发生以下情况之一
    • ^字符串的开头;或
    • 一个字符,可以是
      • ,逗号(在公式中有用)
      • !感叹号(用于Sheet!引用)
      • (开括号(在公式中有用)
      • =文字等号(在公式中有用)
      • \s空格字符
  • (...)捕获组将返回您的值(三个选项之一)
    • \$?[A-Z]{1,3}\$?\d+(?::\$?[A-Z]{1,3}\$?\d+)?而不是整个行/列
      • \$获取绝对引用(列),后跟?使其成为可选
      • [A-Z]个字母的字符类,+一次或多次
      • \$获取绝对引用(行),后跟?使其成为可选
      • \d任意一位,+一次或多次
      • (?:...)非捕获组以匹配范围范围(例如A1:B1
        • 这使用与上面相同的方法
        • 后跟?,使整个非捕获组都是可选的
    • \$?[a-z]{1,3}:\$?[a-z]{1,3}整个列,例如A:C
    • \$?\d+:\$?\d+整个行,例如1:3
  • (?:$|[\s,)])要求您的比赛之后发生以下情况之一
    • $字符串结尾;或
    • 单个字符之一
      • \s空格字符
      • ,逗号
      • )右括号

积分:

tripleee的建议:
 -使用字符类[xyz]代替OR语句(?:x|y|z)
 -更好的击穿压痕
 -语法用法

Makyen的建议:
 -支持整行1:4和整列A:C
 -通过检查Excel的最大列限制[a-z]{1,3} (而不是[a-z]+

来限制FP