Excel 2010+ VBA - 如何搜索范围的公式而不是值
Excel 2010+ VBA - How can I Search a Range's Formulas Rather Than Values
我需要使用 Excel VBA、return 第一个匹配项的行号来搜索一系列单元格。只要我正在搜索值,使用 Match 函数就可以轻松做到这一点。但我需要搜索公式,而不是值。
当我搜索“=A4+2”时,e.g.I 需要 VBA 到 return “4”...
你可以直接用 match
Application.Match("=A4+2", Range("B1:B5").Formula)
会给你4
编辑
您可能会收到来自 Match
的 255 个字符限制的错误。您也可能希望使用工作表内的输出。只需将此代码放在模块中:
Public Function MATCHFUNC(str As String, rng As Range, Optional fOnly As Boolean, Optional fAdr As Boolean) As Variant
Dim i As Long, runner As Variant
If UBound(rng.Value, 1) > 1 And UBound(rng.Value, 2) > 1 And Not fAdr Then MATCHFUNC = 0: Exit Function
For Each runner In rng
i = i + 1
If Not fOnly Or (runner.Text <> runner.Formula) Then
If InStr(1, runner.Formula, str, 1) Then
If fAdr Then MATCHFUNC = runner.Address Else MATCHFUNC = i
Exit Function
End If
End If
Next
MATCHFUNC = 0
End Function
您现在可以像使用普通工作表函数一样使用它。以您的图片为例:
MATCHFUNC([string to search for],[range to look in],[1 to look only in cells containing formulas],[1 to get the address in $A format])
=MATCHFUNC("+2",B3:B5) = 1 - it was found in the first cell
=MATCHFUNC("2",B1:B5) = 2 - "2" is also in B2
=MATCHFUNC("2",B1:B5,1) = 3 - B2 will be skipped - formulas only
=MATCHFUNC("+2",B3:B5,,1) = "$B" - address of the first cell with match
=MATCHFUNC("9",B1:B5) = 0 - not found in range
=MATCHFUNC("2",A1:B5) = 0 - range needs to be only 1 row or 1 column without fAdr
=MATCHFUNC("2",A1:B5,,1) = "$B" - check goes A1->B1...->A2->B2...
对于像这样的特殊情况,您可能希望使用 fAdr = 1
:
=ROW(INDIRECT(MATCHFUNC("2",B4:B5,,1))) = 4 - absolute row of the first cell with match
假设您出于某种原因不想检查 B1:B3 但您需要绝对行。
您也可以在 VBA 中使用它,例如:iVal = MATCHFUNC("=B", Range("B4:B5"))
此外,函数本身可以轻松改进,以输出数组或检查一个 运行 中的不同字符串或做任何你想做的事情(如果不需要,你也可以跳过 2 个可选部分以保持快速和简单理解):)
如果您想要第一个找到的单元格的地址 - 这将用作工作表函数 (=FindFirst("=A",B2:B6)
) 并从另一个 VBA 过程调用:
Public Function FindFirst(FindValue As String, InRange As Range) As Variant
Dim rFound As Range
With InRange
Set rFound = .Find( _
What:=FindValue, _
After:=InRange.Cells(InRange.Cells.Count), _
LookIn:=xlFormulas, _
LookAt:=xlPart)
If Not rFound Is Nothing Then
FindFirst = rFound.Address
Else
FindFirst = CVErr(xlErrValue)
End If
End With
End Function
另一方面,如果您想要所有找到的单元格,您可以使用它 - 但请注意,它不能用作工作表函数。
Public Sub Test()
MsgBox FindInFormula("=A", ThisWorkbook.Worksheets("Sheet1").Range("B2:B6")).Address
End Sub
Public Function FindInFormula(FindValue As String, InRange As Range) As Range
Dim rFound As Range
Dim sFirstAdd As String
Dim rReturnRange As Range
With InRange
Set rFound = .Find( _
What:=FindValue, _
After:=InRange.Cells(InRange.Cells.Count), _
LookIn:=xlFormulas, _
LookAt:=xlPart)
If Not rFound Is Nothing Then
sFirstAdd = rFound.Address
Do
If rReturnRange Is Nothing Then
Set rReturnRange = rFound
Else
Set rReturnRange = Union(rReturnRange, rFound)
End If
Set rFound = .FindNext(rFound)
Loop While Not rFound Is Nothing And rFound.Address <> sFirstAdd
End If
End With
Set FindInFormula = rReturnRange
End Function
您需要将程序更新为 return 地址或单元格引用 - 根据您的需要进行调整。
我需要使用 Excel VBA、return 第一个匹配项的行号来搜索一系列单元格。只要我正在搜索值,使用 Match 函数就可以轻松做到这一点。但我需要搜索公式,而不是值。
当我搜索“=A4+2”时,e.g.I 需要 VBA 到 return “4”...
你可以直接用 match
Application.Match("=A4+2", Range("B1:B5").Formula)
会给你4
编辑
您可能会收到来自 Match
的 255 个字符限制的错误。您也可能希望使用工作表内的输出。只需将此代码放在模块中:
Public Function MATCHFUNC(str As String, rng As Range, Optional fOnly As Boolean, Optional fAdr As Boolean) As Variant
Dim i As Long, runner As Variant
If UBound(rng.Value, 1) > 1 And UBound(rng.Value, 2) > 1 And Not fAdr Then MATCHFUNC = 0: Exit Function
For Each runner In rng
i = i + 1
If Not fOnly Or (runner.Text <> runner.Formula) Then
If InStr(1, runner.Formula, str, 1) Then
If fAdr Then MATCHFUNC = runner.Address Else MATCHFUNC = i
Exit Function
End If
End If
Next
MATCHFUNC = 0
End Function
您现在可以像使用普通工作表函数一样使用它。以您的图片为例:
MATCHFUNC([string to search for],[range to look in],[1 to look only in cells containing formulas],[1 to get the address in $A format])
=MATCHFUNC("+2",B3:B5) = 1 - it was found in the first cell
=MATCHFUNC("2",B1:B5) = 2 - "2" is also in B2
=MATCHFUNC("2",B1:B5,1) = 3 - B2 will be skipped - formulas only
=MATCHFUNC("+2",B3:B5,,1) = "$B" - address of the first cell with match
=MATCHFUNC("9",B1:B5) = 0 - not found in range
=MATCHFUNC("2",A1:B5) = 0 - range needs to be only 1 row or 1 column without fAdr
=MATCHFUNC("2",A1:B5,,1) = "$B" - check goes A1->B1...->A2->B2...
对于像这样的特殊情况,您可能希望使用 fAdr = 1
:
=ROW(INDIRECT(MATCHFUNC("2",B4:B5,,1))) = 4 - absolute row of the first cell with match
假设您出于某种原因不想检查 B1:B3 但您需要绝对行。
您也可以在 VBA 中使用它,例如:iVal = MATCHFUNC("=B", Range("B4:B5"))
此外,函数本身可以轻松改进,以输出数组或检查一个 运行 中的不同字符串或做任何你想做的事情(如果不需要,你也可以跳过 2 个可选部分以保持快速和简单理解):)
如果您想要第一个找到的单元格的地址 - 这将用作工作表函数 (=FindFirst("=A",B2:B6)
) 并从另一个 VBA 过程调用:
Public Function FindFirst(FindValue As String, InRange As Range) As Variant
Dim rFound As Range
With InRange
Set rFound = .Find( _
What:=FindValue, _
After:=InRange.Cells(InRange.Cells.Count), _
LookIn:=xlFormulas, _
LookAt:=xlPart)
If Not rFound Is Nothing Then
FindFirst = rFound.Address
Else
FindFirst = CVErr(xlErrValue)
End If
End With
End Function
另一方面,如果您想要所有找到的单元格,您可以使用它 - 但请注意,它不能用作工作表函数。
Public Sub Test()
MsgBox FindInFormula("=A", ThisWorkbook.Worksheets("Sheet1").Range("B2:B6")).Address
End Sub
Public Function FindInFormula(FindValue As String, InRange As Range) As Range
Dim rFound As Range
Dim sFirstAdd As String
Dim rReturnRange As Range
With InRange
Set rFound = .Find( _
What:=FindValue, _
After:=InRange.Cells(InRange.Cells.Count), _
LookIn:=xlFormulas, _
LookAt:=xlPart)
If Not rFound Is Nothing Then
sFirstAdd = rFound.Address
Do
If rReturnRange Is Nothing Then
Set rReturnRange = rFound
Else
Set rReturnRange = Union(rReturnRange, rFound)
End If
Set rFound = .FindNext(rFound)
Loop While Not rFound Is Nothing And rFound.Address <> sFirstAdd
End If
End With
Set FindInFormula = rReturnRange
End Function
您需要将程序更新为 return 地址或单元格引用 - 根据您的需要进行调整。