【发布时间】:2012-09-20 11:10:44
【问题描述】:
我有一列超过 500 行的数字。我需要使用 VBA 来检查变量 X 是否与列中的任何值匹配。
有人可以帮帮我吗?
【问题讨论】:
我有一列超过 500 行的数字。我需要使用 VBA 来检查变量 X 是否与列中的任何值匹配。
有人可以帮帮我吗?
【问题讨论】:
范围的查找方法比使用 for 循环手动遍历所有单元格更快。
这里是一个在vba中使用find方法的例子
Sub Find_First()
Dim FindString As String
Dim Rng As Range
FindString = InputBox("Enter a Search value")
If Trim(FindString) <> "" Then
With Sheets("Sheet1").Range("A:A") 'searches all of column A
Set Rng = .Find(What:=FindString, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
Application.Goto Rng, True 'value found
Else
MsgBox "Nothing found" 'value not found
End If
End With
End If
End Sub
【讨论】:
FOR 循环更健壮。 @user1547174 您可以使用变量Rng 来获取有关匹配位置的信息,特别是调用Rng.Address,它将单元格位置作为字符串返回。
最简单的就是使用Match
If Not IsError(Application.Match(ValueToSearchFor, RangeToSearchIn, 0)) Then
' String is in range
【讨论】:
如果您想在没有 VBA 的情况下执行此操作,可以使用IF、ISERROR 和MATCH 的组合。
因此,如果所有值都在 A 列中,请在 B 列中输入此公式:
=IF(ISERROR(MATCH(12345,A:A,0)),"Not Found","Value found on row " & MATCH(12345,A:A,0))
这将查找值“12345”(也可以是单元格引用)。如果未找到该值,MATCH 会返回“#N/A”,ISERROR 会尝试捕捉它。
如果你想使用 VBA,最快的方法是使用 FOR 循环:
Sub FindMatchingValue()
Dim i as Integer, intValueToFind as integer
intValueToFind = 12345
For i = 1 to 500 ' Revise the 500 to include all of your values
If Cells(i,1).Value = intValueToFind then
MsgBox("Found value on row " & i)
Exit Sub
End If
Next i
' This MsgBox will only show if the loop completes with no success
MsgBox("Value not found in the range!")
End Sub
您可以在 VBA 中使用工作表函数,但它们很挑剔,有时会引发无意义的错误。 FOR 循环非常简单。
【讨论】:
=countif(A:A,12345)>0 如果找到数字,将返回 True,否则返回 false。
Sheets("Codes").Cells(i,1).Value@scott true,但如果用户不检查许多值,则可能更容易实现 @987654332 @ 在范围上循环。如果@user1547174想用这个方法,查看MSDN上的FIND方法:msdn.microsoft.com/en-us/library/office/ff839746.aspx
Application.WorksheetFunction.CountIf 配合使用。
试试这个:
If Application.WorksheetFunction.CountIf(RangeToSearchIn, ValueToSearchFor) = 0 Then
Debug.Print "none"
End If
【讨论】:
只是为了修改 scott 的答案以使其成为一个函数:
Function FindFirstInRange(FindString As String, RngIn As Range, Optional UseCase As Boolean = True, Optional UseWhole As Boolean = True) As Variant
Dim LookAtWhat As Integer
If UseWhole Then LookAtWhat = xlWhole Else LookAtWhat = xlPart
With RngIn
Set FindFirstInRange = .Find(What:=FindString, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=LookAtWhat, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=UseCase)
If FindFirstInRange Is Nothing Then FindFirstInRange = False
End With
End Function
如果找不到该值,则返回 FALSE,如果找到,则返回范围。
您可以选择让它区分大小写和/或允许部分单词匹配。
我取出了 TRIM,因为您可以根据需要预先添加它。
一个例子:
MsgBox FindFirstInRange(StringToFind, Range("2:2"), TRUE, FALSE).Address
这会在第二行进行区分大小写的部分单词搜索,并显示一个带有地址的框。以下是相同的搜索,但是是不区分大小写的全词搜索:
MsgBox FindFirstInRange(StringToFind, Range("2:2")).Address
您可以根据自己的喜好轻松调整此函数,或将其从 Variant 更改为布尔值或其他任何值,以加快速度。
请注意,VBA 的 Find 有时比蛮力循环或 Match 等其他方法慢,因此不要仅仅因为它是 VBA 的原生方法就认为它是最快的。它更加复杂和灵活,这也可能使其并不总是那么高效。它有一些有趣的怪癖需要注意,比如“对象变量或未设置块变量”error。
【讨论】:
MsgBox FindFirstInRange(StringToFind, Range("2:2")).Address。它将抛出“需要对象”。
修复了@JeffC 在来自@sdanse 的函数中提到的问题:
Function FindFirstInRange(FindString As String, RngIn As Range, Optional UseCase As Boolean = True, Optional UseWhole As Boolean = True) As Variant
Dim LookAtWhat As Integer
If UseWhole Then LookAtWhat = xlWhole Else LookAtWhat = xlPart
With RngIn
Set FindFirstInRange = .Find(What:=FindString, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=LookAtWhat, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=UseCase)
If FindFirstInRange Is Nothing Then
FindFirstInRange = False
Exit Function
End If
If IsEmpty(FindFirstInRange) Then
FindFirstInRange = False
Else
FindFirstInRange = True
End If
End With
End Function
【讨论】:
尝试添加 WorksheetFunction:
If Not IsError(Application.WorksheetFunction.Match(ValueToSearchFor, RangeToSearchIn, 0)) Then
' String is in range
【讨论】:
=IF(COUNTIF($C$2:$C$500,A2)>0,"Exist","Not Exists")
【讨论】: