Проверьте, существует ли значение в столбце в VBA

У меня есть столбец с числами более 500 строк. Мне нужно использовать VBA, чтобы проверить, соответствует ли переменная X любому из значений в столбце.

Кто-нибудь может мне помочь?


person Trung Tran    schedule 28.09.2012    source источник


Ответы (7)


Если вы хотите сделать это без 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 довольно надежна.

person Jake Bathman    schedule 28.09.2012
comment
Еще одна вещь - как я могу попросить его выполнить поиск на конкретном листе? У меня есть несколько листов в моей текущей программе, и они мне нужны для поиска на листе под названием «Коды». Спасибо. - person Trung Tran; 28.09.2012
comment
Намного быстрее использовать метод поиска диапазона, чем перебирать каждую ячейку в цикле. - person scott; 28.09.2012
comment
К вашему сведению, вы можете сделать намного проще, чем функцию сопоставления: =countif(A:A,12345)>0 вернет True, если число найдено, и false, если нет. - person nutsch; 28.09.2012
comment
@ user1547174 Чтобы сделать это для определенного листа, ссылайтесь на ячейки следующим образом: Sheets("Codes").Cells(i,1).Value @scott true, но если пользователь не проверяет много значений, может быть проще реализовать цикл FOR для диапазона. Если @ user1547174 хочет использовать этот метод, проверьте метод FIND в MSDN: msdn.microsoft.com/en-us/library/office/ff839746.aspx - person Jake Bathman; 28.09.2012
comment
@nutsch хорошее мышление. Также отлично работает с Application.WorksheetFunction.CountIf через VBA. - person ashleedawg; 02.09.2018

Метод поиска диапазона быстрее, чем использование цикла for для ручного перебора всех ячеек.

вот пример использования метода поиска в vba

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
person scott    schedule 28.09.2012
comment
Спасибо за это, Скотт. Он будет более устойчивым для нечисловых значений, чем цикл FOR. @ user1547174 вы можете использовать переменную Rng для получения информации о местоположении совпадения, в частности вызывая Rng.Address, который возвращает местоположение ячейки в виде строки. - person Jake Bathman; 28.09.2012

Самый простой - использовать Match

If Not IsError(Application.Match(ValueToSearchFor, RangeToSearchIn, 0)) Then
    ' String is in range
person chris neilsen    schedule 28.09.2012
comment
Не отображается при автозаполнении в редакторе VB, но, похоже, работает - person Urchin; 21.09.2016

попробуй это:

If Application.WorksheetFunction.CountIf(RangeToSearchIn, ValueToSearchFor) = 0 Then
Debug.Print "none"
End If
person user11078722    schedule 18.02.2019

Просто чтобы изменить ответ Скотта, чтобы он стал функцией:

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

Это выполняет поиск с учетом регистра, частичный поиск во 2-й строке и отображает поле с адресом. Ниже приводится тот же поиск, но поиск по всему слову без учета регистра:

MsgBox FindFirstInRange(StringToFind, Range("2:2")).Address

Вы можете легко настроить эту функцию по своему вкусу или изменить ее с Variant на логическое или что-то еще, чтобы немного ускорить ее.

Обратите внимание, что Find VBA иногда медленнее, чем другие методы, такие как цикл перебора или Match, поэтому не думайте, что он самый быстрый только потому, что он является родным для VBA. Он более сложный и гибкий, что также может сделать его не всегда таким эффективным. И у него есть несколько забавных причуд, на которые нужно обратить внимание, например, «Переменная объекта или переменная блока не установлена» error.

person sdanse    schedule 18.11.2019
comment
Мне нравится концепция этого, но ваши примеры не будут работать, если строка не найдена, например. MsgBox FindFirstInRange(StringToFind, Range("2:2")).Address. Будет выброшен объект "Требуемый объект". - person JeffC; 12.04.2021
comment
Поскольку этот подход был единственным многообещающим, я решил проблему, упомянутую JeffC: Проблема заключается в ситуации, если введенная строка поиска пуста. Я изменил функцию, поэтому возвращаемое значение всегда является логическим. Где-то внизу вы найдете мой полный тент. - person MaKaNu; 27.05.2021

Исправленная проблема, упомянутая @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
person MaKaNu    schedule 27.05.2021

Попробуйте добавить WorksheetFunction:

If Not IsError(Application.WorksheetFunction.Match(ValueToSearchFor, RangeToSearchIn, 0)) Then
' String is in range
person Chris    schedule 02.05.2018
comment
Использование WorksheetFunction изменяет способ обработки VBA ошибки, возникающей, если значение не может быть найдено. Вместо того, чтобы возвращать значение ошибки (которое затем может быть проверено функцией IsError), VBA выдает ошибку, которая требует обработки ошибок или останавливает выполнение. Для проверки того, существует ли значение, вам просто нужен результат True или False, чтобы не генерировать ошибку времени выполнения. - person Michael; 29.01.2019