Excel 检查VBA中的列中是否存在值

Excel 检查VBA中的列中是否存在值,excel,vba,matching,Excel,Vba,Matching,我有一列超过500行的数字。我需要使用VBA检查变量X是否与列中的任何值匹配 有人能帮我吗?如果您想在没有VBA的情况下执行此操作,您可以使用If、iError和MATCH的组合 因此,如果所有值都在A列中,请在B列中输入以下公式: =IF(ISERROR(MATCH(12345,A:A,0)),"Not Found","Value found on row " & MATCH(12345,A:A,0)) 这将查找值“12345”(也可以是单元格引用)。如果未找到该值,MATCH返回“

我有一列超过500行的数字。我需要使用VBA检查变量X是否与列中的任何值匹配

有人能帮我吗?

如果您想在没有VBA的情况下执行此操作,您可以使用
If
iError
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”,并且
iError
尝试捕捉该值

如果要使用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循环非常简单。

范围的查找方法比使用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
Sub Find_First()
作为字符串的暗FindString
变暗Rng As范围
FindString=InputBox(“输入搜索值”)
如果修剪(FindString)“,则
带图纸(“Sheet1”)。范围(“A:A”)搜索A列的所有内容
Set Rng=.Find(What:=FindString_
之后:=.Cells(.Cells.Count)_
LookIn:=xlValues_
看:=xlother_
搜索顺序:=xlByRows_
SearchDirection:=xlNext_
匹配案例:=假)
如果不是,那么Rng什么都不是
Application.Goto Rng,找到“True”值
其他的
未找到MsgBox“未找到任何内容”的值
如果结束
以
如果结束
端接头

最简单的方法是使用
匹配

If Not IsError(Application.Match(ValueToSearchFor, RangeToSearchIn, 0)) Then
    ' String is in range

尝试添加工作表功能:

If Not IsError(Application.WorksheetFunction.Match(ValueToSearchFor, RangeToSearchIn, 0)) Then
' String is in range
试试这个:

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;如果找到值,则返回范围

您可以选择告诉它区分大小写,和/或允许部分单词匹配

我去掉了饰件,因为如果你想的话,你可以事先加上

例如:

MsgBox FindFirstInRange(StringToFind, Range("2:2"), TRUE, FALSE).Address
它在第二行进行区分大小写的部分单词搜索,并显示一个带有地址的框。以下是相同的搜索,但是不区分大小写的整词搜索:

MsgBox FindFirstInRange(StringToFind, Range("2:2")).Address
您可以根据自己的喜好轻松地调整此函数,或将其从变量更改为布尔值,或其他任何形式,以稍微加快速度


请注意,VBA的查找有时比其他方法(如蛮力循环或匹配)慢,因此不要仅仅因为它是VBA固有的,就认为它是最快的。它更加复杂和灵活,这也使得它不总是那么高效。它还有一些有趣的怪癖需要注意,比如“对象变量或块变量未设置”。

修复了@sdanse函数中@JeffC提到的问题:

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

还有一件事-我如何要求它在特定的工作表中搜索?我在当前程序中有几个工作表,我需要它来搜索一个名为“代码”的工作表。谢谢。使用范围的find方法比在每个单元格中循环快得多。fyi,你可以做得比match函数简单得多:
=countif(a:a,12345)>0
如果找到数字将返回True,如果找不到则返回false。@user1547174要对特定的工作表执行此操作,请参考如下单元格:
工作表(“代码”).Cells(i,1).Value
@scott true,但如果用户不检查许多值,则可能更容易在范围上实现
FOR
循环。如果@user1547174想要使用此方法,请查看MSDN:@nutsch good thinking上的
FIND
方法。还可以通过VBA与
应用程序.WorksheetFunction.CountIf
配合使用。感谢您这么做,Scott。对于非数值,它比对于循环的
更健壮@user1547174您可以使用变量
Rng
获取有关匹配位置的信息,特别是调用
Rng.Address
,它以字符串形式返回单元格位置。不会显示在VB编辑器的自动完成中,但是使用WorksheetFunction似乎可以改变VBA在找不到值时处理错误的方式。VBA不会返回错误值(然后可以由IsError函数检查),而是抛出需要错误处理或将停止执行的错误。为了测试某个值是否存在,您只需要一个真或假结果,而不是潜在地生成运行时错误。我喜欢这一概念,但如果找不到字符串,您的示例将不起作用,例如
MsgBox FindFirstInRange(StringToFind,Range(“2:2”)。Address
。它将抛出“objectrequired”。因为这种方法是唯一有希望的方法,所以我修复了JeffC提到的问题:如果输入的搜索字符串为空,问题就是情况。我更改了函数,使返回值始终为布尔值。你可以在下面的某个地方找到我的完整的awnser。