Home » excel » excel – Trouble getting custom function syntax right: Contains()

excel – Trouble getting custom function syntax right: Contains()

Posted by: admin May 14, 2020 Leave a comment

Questions:

I’m desperately trying to implement this solution to my own code: https://stackoverflow.com/a/43196497/11632049

The goal is to search for various strings (“ABC”, “123”, …) and if a data row contains the string, copy the row to a different workbook. I am getting a sub or function not defined error

Public Function ContainsAny(ByVal needle As String, ByVal caseSensitive As _ 
    Boolean, ParamArray haystack() As Variant) As Boolean

    Dim k As Integer
    Dim found As Boolean

    For k = LBound(haystack) To UBound(haystack)
        found = Contains(needle, CStr(haystack(k)), caseSensitive)
        If found Then Exit For
    Next
    ContainsAny = found

End Function


Private Sub Workbook_AfterSave(ByVal Success As Boolean)

    Dim CoderBook As Workbook
    Dim Review As Workbook
    Dim Alpha As Worksheet
    Dim Coder As Worksheet
    Dim LastRow As Long
    Dim NextRow As Long
    Dim i As Long

    Set CoderBook = Workbooks.Open(FilePath)
    Set Coder = CoderBook.Sheets("Sheet1")

    Set Review = ThisWorkbook
    Set Alpha = Review.Sheets("Sheet5")

    'Search code
    LastRow = Alpha.Cells.Find(What:="*", After:=[A1], _
    SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row

    Application.ScreenUpdating = False

    'Loop search code
    For i = 2 To LastRow

        If Alpha.Range("G" & i) <> Alpha.Range("H" & i) Or _
        Alpha.Range("J" & i) <> Alpha.Range("K" & i) Then

        Select Case True
        Case ContainsAny(Ophth.Range("H" & i), False, "ABC", "123")

            DuplicateCheck = Application.Match(Alpha.Range("A" & i).Value, _ 
            Coder.Columns(1), 0)
            If IsError(DuplicateCheck) Then
                Coder.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0). _
                EntireRow.Value = Alpha.Rows(i).Value
            End If
        End Select
       End If

    Next i

CoderBook.Close SaveChanges:=True
Application.ScreenUpdating = True
End Sub
How to&Answers:

You are getting a “function not defined” compile error because ContainsAny is invoking the Contains function, which you removed. Add it back.

found = Contains(needle, CStr(haystack(k)), caseSensitive)

But, the logic of the Contains method needs to be flipped for it to work the way you want to use it:

Public Function Contains(ByVal needle As String, ByVal haystack As String, Optional ByVal caseSensitive As Boolean = False) As Boolean

    Dim compareMethod As VbCompareMethod

    If caseSensitive Then
        compareMethod = vbBinaryCompare
    Else
        compareMethod = vbTextCompare
    End If

    Contains = (InStr(1, haystack, needle, compareMethod) <> 0)
    If Not Contains Then Contains = (InStr(1, needle, haystak, compareMethod) <> 0)

End Function

That way Contains will return True when either string contains the other – and with that you can do:

 If ContainsAny(Ophth.Range("H" & i).Value, False, "ABC", "123", "XYZ") Then

And the conditional block will execute when the cell value contains any one of the specified strings.

Answer:

This seems to be working – I adjusted @MathieuGuindon ‘s custom function to try clarify for myself the desired relationship between my search terms: I have a set of search terms and I need to know when any of them appear in my data.

Public Function ContainsAny(ByVal data As String, ByVal caseSensitive _ 
    As Boolean, ParamArray searchterms() As Variant) As Boolean

    Dim k As Integer
    Dim found As Boolean

    For k = LBound(searchterms) To UBound(searchterms)
        found = Contains(data, CStr(searchterms(k)), caseSensitive)
        If found Then Exit For
    Next

    ContainsAny = found

End Function



Public Function Contains(ByVal data As String, ByVal searchterms _
    As String, Optional ByVal caseSensitive As Boolean = False) As Boolean

    Dim compareMethod As VbCompareMethod

    If caseSensitive Then
        compareMethod = vbBinaryCompare
    Else
        compareMethod = vbTextCompare
    End If

    Contains = (InStr(1, data, searchterms, compareMethod) <> 0)

End Function


'implemented as
Case ContainsAny(Alpha.Range("H" & i), False, "ABC", "123", "XYZ)