How can I search for records where two specific words appear in order using the LIKE operator in VB6’s ADODB.Recordset.Filter property?
I’m working with an ADODB.Recordset called rsCustomers that persists in memory during my form’s lifecycle. I’m using the Filter property to search through records as the user types in a TextBox. The current approach using LIKE %John Doe% works when “John” is immediately followed by “Doe”, but it fails when there are other characters between them (like “John O’ Doe”).
I’ve tried using the syntax rsCustomers.Filter("Name LIKE %John%Doe%") similar to SQL Server, but it doesn’t seem to work. Is there a different syntax for this in VB6? Is this functionality even possible with the Filter property, or do I need to implement a different approach?
The ADODB.Recordset.Filter property in VB6 doesn’t support the same complex pattern matching as SQL Server. The LIKE %John%Doe% syntax you tried isn’t valid for ADO Filter, which only supports basic wildcard patterns at the beginning and/or end of strings. For searching records where two words appear in order with any characters between them, you’ll need to use a different approach.
Contents
- Understanding ADO Filter Limitations
- Alternative Approaches
- Implementation Strategies
- Recommended Solution
- Examples and Code
Understanding ADO Filter Limitations
The ADO Filter property has specific constraints with the LIKE operator:
- Wildcard Restrictions: The LIKE operator only supports
*or%wildcards at the beginning and/or end of strings, not in the middle - Syntax Requirement: As stated in Microsoft documentation, the Filter property only supports basic pattern matching
- String Formatting: Values must be enclosed in single quotes when using string comparisons
According to DevGuru, “if the Filter begins with a wildcard (* or %) then it must end with a wildcard (* or %)” - this explains why
LIKE %John%Doe%fails, as it has wildcards in both middle and end positions.
Alternative Approaches
Since the Filter property can’t handle your specific requirement, consider these alternatives:
1. Use SQL Query with Regular Expressions
Many databases support regular expressions or pattern matching functions that can handle “words in order with characters between” scenarios.
2. Client-Side Filtering
Loop through the recordset and apply custom logic to check for the pattern.
3. Full-Text Search
If available, use database-specific full-text search capabilities.
Implementation Strategies
SQL-Based Solution
Modify your SQL query to use database-specific pattern matching:
' For SQL Server using PATINDEX
strSQL = "SELECT * FROM Customers " & _
"WHERE PATINDEX('%John% Doe%', Name) > 0"
' For Access using Instr
strSQL = "SELECT * FROM Customers " & _
"WHERE InStr(1, [Name], 'John') > 0 AND " & _
"InStr(InStr(1, [Name], 'John') + 4, [Name], 'Doe') > 0"
Client-Side Solution
If you must use the in-memory recordset, implement custom filtering:
Function FilterByWordOrder(rs As ADODB.Recordset, fieldName As String, _
firstWord As String, secondWord As String) As Boolean
Dim firstPos As Long, secondPos As Long
firstPos = InStr(1, rs(fieldName), firstWord)
If firstPos = 0 Then Exit Function
secondPos = InStr(firstPos + Len(firstWord), rs(fieldName), secondWord)
FilterByWordOrder = (secondPos > 0)
End Function
' Usage:
Dim filteredRS As New ADODB.Recordset
filteredRS.Filter = adFilterNone ' Clear any existing filter
rsCustomers.Filter = adFilterNone
rsCustomers.MoveFirst
Do While Not rsCustomers.EOF
If FilterByWordOrder(rsCustomers, "Name", "John", "Doe") Then
filteredRS.AddNew
' Copy all fields from rsCustomers to filteredRS
' (implementation depends on your field structure)
filteredRS.Update
End If
rsCustomers.MoveNext
Loop
Recommended Solution
The most efficient approach is to modify your SQL query to use the database’s pattern matching capabilities. Here’s a comprehensive solution:
Private Sub SearchCustomers(searchText As String)
Dim firstWord As String, secondWord As String
Dim strSQL As String
Dim rsFiltered As New ADODB.Recordset
' Parse the search text to extract words
' This is a simplified example - you may need more sophisticated parsing
Dim words() As String
words = Split(searchText, " ")
If UBound(words) >= 1 Then
firstWord = words(0)
secondWord = words(1)
' Build SQL based on database type
Select Case GetDatabaseType()
Case "SQLServer"
strSQL = "SELECT * FROM Customers " & _
"WHERE PATINDEX('%" & firstWord & "% " & secondWord & "%', Name) > 0"
Case "Access"
strSQL = "SELECT * FROM Customers " & _
"WHERE InStr(1, [Name], '" & firstWord & "') > 0 AND " & _
"InStr(InStr(1, [Name], '" & firstWord & "') + 4, [Name], '" & secondWord & "') > 0"
Case Else
' Default to simple containment
strSQL = "SELECT * FROM Customers " & _
"WHERE Name LIKE '%" & searchText & "%'"
End Select
Else
' Single word search
strSQL = "SELECT * FROM Customers WHERE Name LIKE '%" & searchText & "%'"
End If
' Execute the query and get filtered results
rsFiltered.Open strSQL, gConnection, adOpenStatic, adLockReadOnly
' Replace the current recordset with filtered results
Set rsCustomers = rsFiltered
rsCustomers.MoveFirst
' Update your UI to reflect the filtered results
RefreshCustomerDisplay
End Sub
Private Function GetDatabaseType() As String
' Determine your database type - implement based on your connection
' This is a placeholder - you need to implement actual detection
GetDatabaseType = "Access" ' or "SQLServer" etc.
End Function
Examples and Code
Here are practical examples for different scenarios:
Basic Two-Word Search
' Search for "John" followed by "Doe" with any characters between
Private Sub SearchForJohnDoe()
Dim strSQL As String
' For Access databases
strSQL = "SELECT * FROM Customers " & _
"WHERE InStr(1, [Name], 'John') > 0 AND " & _
"InStr(InStr(1, [Name], 'John') + 4, [Name], 'Doe') > 0"
' Execute and display results
ExecuteAndDisplay strSQL
End Sub
Dynamic Multi-Word Search
' Handle searches with multiple words
Private Sub HandleDynamicSearch(searchText As String)
Dim words() As String
Dim strSQL As String
Dim i As Integer
words = Split(searchText, " ")
If UBound(words) = 0 Then
' Single word search
strSQL = "SELECT * FROM Customers WHERE Name LIKE '%" & searchText & "%'"
Else
' Multiple word search - look for words in order
strSQL = "SELECT * FROM Customers WHERE "
For i = 0 To UBound(words)
If i > 0 Then strSQL = strSQL & " AND "
strSQL = strSQL & "InStr(1, [Name], '" & words(i) & "') > " & IIf(i > 0, _
"InStr(1, [Name], '" & words(i-1) & "') + " & Len(words(i-1)), "0")
Next i
End If
ExecuteAndDisplay strSQL
End Sub
Performance Considerations
' Optimize for large recordsets
Private Sub OptimizedSearch(searchText As String)
' Create a temporary index if frequently searching
' Or use server-side filtering as shown above
' Client-side filtering can be slow for large datasets
' Alternative: Use Find method with custom criteria
rsCustomers.Filter = adFilterNone
rsCustomers.MoveFirst
Dim foundCount As Long
foundCount = 0
Do While Not rsCustomers.EOF
If CheckWordOrder(rsCustomers!Name, searchText) Then
foundCount = foundCount + 1
' Add to results or highlight in UI
End If
rsCustomers.MoveNext
Loop
MsgBox foundCount & " records found"
End Sub
Private Function CheckWordOrder(text As String, searchText As String) As Boolean
Dim words() As String
Dim positions() As Long
Dim i As Integer
words = Split(searchText, " ")
ReDim positions(UBound(words))
' Find positions of each word
For i = 0 To UBound(words)
positions(i) = InStr(1, text, words(i))
If positions(i) = 0 Then Exit Function
Next i
' Check if words appear in order
For i = 1 To UBound(positions)
If positions(i) <= positions(i-1) Then Exit Function
Next i
CheckWordOrder = True
End Function
Sources
- ADO Filter Property - Microsoft Learn
- ADO Recordset Filter - DevGuru
- VBA Recordset Filter Wildcard Issues - Stack Overflow
- LIKE Operator in ADO vs SQL Server - Stack Overflow
- Filter Property - Oracle Documentation
Conclusion
The ADODB.Recordset.Filter property in VB6 has limitations that prevent it from handling complex pattern matching like searching for words in order with arbitrary characters between them. While the Filter property works well for simple wildcard searches at the beginning or end of strings, more sophisticated text matching requires alternative approaches:
- Use SQL-based solutions with database-specific pattern matching functions like PATINDEX (SQL Server) or InStr (Access)
- Implement client-side filtering with custom logic when server-side filtering isn’t feasible
- Consider full-text search capabilities if available in your database
- Pre-process your queries to handle multi-word searches by building dynamic SQL statements
For your specific case of searching for “John” followed by “Doe” with characters between them, the recommended approach is to modify your SQL query to use the database’s native string functions rather than relying on the ADO Filter property’s limited pattern matching capabilities.