Fuzzy Matching - new version plus explanation

al_b_cnu

Well-known Member
Joined
Jul 18, 2003
Messages
4,546
It has been a while since I originally posted my Fuzzy matching UDF’s on the board, and several variants have appeared subsequently.

I thought it time to ‘put the record straight’ & post a definitive version which contains slightly more efficient code, and better matching algorithms, so here it is.

Firstly, I must state that the Fuzzy matching algorithms are very CPU hungry, and should be used sparingly. If for instance you require to lookup a match for a string which starts with, contains or ends with a specified value, this can be performed far more efficiently using the MATCH function:
Fuzzy Examples.xls
ABCDE
1Starts WithEndsContains
2BilljelenBill
3Mr Bill Jelen433
4Bill Jelen
5Joe Bloggs
6Fred Smith
MATCH Example


... Continued ...
 
Apologies!

Code:
iLen = Max(String1, String2)

Should have been

Code:
iLen = Worksheetfunction.Max(String1, String2)

But your solution works just as well.
 
Upvote 0

Excel Facts

Using Function Arguments with nested formulas
If writing INDEX in Func. Arguments, type MATCH(. Use the mouse to click inside MATCH in the formula bar. Dialog switches to MATCH.
Thanks again! WorksheetFunction.Max is an XL thing, and I'm in Word VBA, so I'll have to stick with the VBA version.

See you again in 4 months, when I'll be back to ask the same question.;)
 
Upvote 0
Is it possible to combine the Fuzzy Matching as Smart Tag?
Which means whilst inputing data, the fuzzy matching can provide a kind of Smart Tag, suggesting the possible entries. Current Smart Tag only provide as the order. But what I want is Smart Tag that can also suggest even though somehow only partially same.
For example: the list of ID in sheet1 are 1234abcd, 2345efgh, 376kjbh, ghyj7349. So, when I type 34 in sheet2, the smart tag will pop up and suggest 1234abcd, 2345efgh, ghyj7349.
This will very helpful if possible. Please help me regarding this issue.
Thank you in advance for fellows' attention.
 
Upvote 0
Hi Culprit79,

You can achieve that using a userform and a hook into the Selection_Change event.
This code will display a userform wjhen you select a cell in column A of sheet 2, and give a drop down box of candidates from sheet 1 column A (rows 2 onwards)

To install:
1) Create a Userform, name it "FSmartTag"
2) Create the following controls in the userform
- A Text box named "txtSearch"
- A combo Box named "cboTags"
- A command button named "btnCancel" with the caption "Cancel"
- A command button named "btnOK" with the caption "OK"
3) Place this code in the userform:
Code:
Option Explicit
Public OK As Boolean
Public SmartTagCandidateList As Variant

Private Sub cboTags_Change()
btnOK.Enabled = cboTags.Value <> ""

End Sub

Private Sub txtSearch_Change()
Dim sSearch As String
Dim vCurrent As Variant

sSearch = "*" & UCase$(txtSearch.Value) & "*"
cboTags.Clear

If IsArray(SmartTagCandidateList) Then
    For Each vCurrent In SmartTagCandidateList
        If UCase$(CStr(vCurrent)) Like sSearch Then cboTags.AddItem vCurrent
    Next vCurrent
Else
    If UCase$(CStr(SmartTagCandidateList)) Like sSearch Then cboTags.AddItem vCurrent
End If

cboTags.Value = txtSearch.Value

End Sub

Private Sub UserForm_Activate()
With cboTags
    .Clear
    .MatchRequired = True
End With

OK = False
btnOK.Enabled = False
End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    If Cancel <> 1 Then
    Cancel = -1
    OK = False
    Me.Hide
    End If
End Sub
 
 Private Sub btnCancel_Click()
OK = False
Me.Hide
End Sub

Private Sub btnOK_Click()
OK = True
Me.Hide
End Sub

4) In Sheet2 right-click the tab and select [View Code]
5) Place this in the code window:
Code:
Option Explicit

Dim mvaSmartTags As Variant

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Const iSmartTagColumn As Integer = 1    'column 1 for smart Tag Column

Dim frmSmartTag As New fSmartTag

Dim lRowEnd As Long
Dim lRow As Long

'-- Exit if not correct column or row 1 or if > 1 cell selected
If Target.Column <> iSmartTagColumn Then Exit Sub
If Target.Row < 2 Then Exit Sub
If Target.Cells.Count <> 1 Then Exit Sub

If IsArray(mvaSmartTags) = False Then
    '-- Get list from Sheet1 column A
    With Sheets("Sheet1")
        lRowEnd = .Cells(Rows.Count, "A").End(xlUp).Row
        If lRowEnd > 1 Then mvaSmartTags = .Range("A2:A" & lRowEnd).Value
    End With
End If

Set frmSmartTag = New fSmartTag
frmSmartTag.SmartTagCandidateList = mvaSmartTags
frmSmartTag.Show
If frmSmartTag.OK Then Target.Value = frmSmartTag.cboTags.Value
Set frmSmartTag = Nothing
End Sub

When you select a cell in column A of sheet2, the userform will be displayed. Enter a search string in the text box and the combobox will display the list of candidates. Select as appropriate & click "OK".
 
Upvote 0
I've tried your VBA and it worked.
But is it possible to list down the possibilities in LIST BOX, instead of COMBO BOX?
Thank a lot your your help.
 
Upvote 0
ok,

Replace the combobox "cboTags" with a listbox named "lstTags"

This is the new code in Sheet2:
Code:
Option Explicit

Dim mvaSmartTags As Variant

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Const iSmartTagColumn As Integer = 1    'column 1 for smart Tag Column

Dim frmSmartTag As New fSmartTag

Dim lRowEnd As Long
Dim lRow As Long

'-- Exit if not correct column or row 1 or if > 1 cell selected
If Target.Column <> iSmartTagColumn Then Exit Sub
If Target.Row < 2 Then Exit Sub
If Target.Cells.Count <> 1 Then Exit Sub

If IsArray(mvaSmartTags) = False Then
    '-- Get list from Sheet1 column A
    With Sheets("Sheet1")
        lRowEnd = .Cells(Rows.Count, "A").End(xlUp).Row
        If lRowEnd > 1 Then mvaSmartTags = .Range("A2:A" & lRowEnd).Value
    End With
End If

Set frmSmartTag = New fSmartTag
frmSmartTag.SmartTagCandidateList = mvaSmartTags
frmSmartTag.CellValue = Target.Resize(1, 1).Value
frmSmartTag.Show
If frmSmartTag.OK Then Target.Value = frmSmartTag.CellValue
Set frmSmartTag = Nothing
End Sub

This is the new userform code:
Code:
Option Explicit
Public OK As Boolean
Public SmartTagCandidateList As Variant
Public CellValue As String

Private Sub lsttags_Change()
btnOK.Enabled = lstTags.ListIndex > -1

End Sub

Private Sub txtSearch_Change()
Dim sSearch As String
Dim vCurrent As Variant

sSearch = "*" & UCase$(txtSearch.Value) & "*"
lstTags.Clear

If IsArray(SmartTagCandidateList) Then
    For Each vCurrent In SmartTagCandidateList
        If UCase$(CStr(vCurrent)) Like sSearch Then lstTags.AddItem vCurrent
    Next vCurrent
Else
    If UCase$(CStr(SmartTagCandidateList)) Like sSearch Then lstTags.AddItem vCurrent
End If

End Sub

Private Sub UserForm_Activate()
With lstTags
    .Clear
End With

OK = False
txtSearch.Value = CellValue

btnOK.Enabled = txtSearch.Value <> ""
End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    If Cancel <> 1 Then
    Cancel = -1
    OK = False
    Me.Hide
    End If
End Sub
 
 Private Sub btnCancel_Click()
OK = False
Me.Hide
End Sub

Private Sub btnOK_Click()
CellValue = lstTags.Value
OK = True
Me.Hide
End Sub
 
Last edited:
Upvote 0
Nice and remarkable solution.
Is it possible to contact you via MSN or Yahoo Messenger, instead of via this forum? I'm still new and might have other inquiries regarding excel VBA.
Thank you.
 
Upvote 0
Is it possible to tune the fuzzyvlookup function to give a best match from an array rather than specifying a certain cutoff percentage for matches?

I might be mistaken, but it seems that the function returns the first result from the lookup array that fulfills the matching criteria, even if better matches exist below.

Thanks for a very usefull formula, it saved me a lot of time! :cool:
 
Upvote 0
Hi Avest,

Try using the 'Rank' parameter - a rank of 1 (default) will return the best match, a rank of 2 will return the 2nd best match etc.

If too heavy on resources post back & we'll work something out.
 
Upvote 0

Forum statistics

Threads
1,223,931
Messages
6,175,465
Members
452,645
Latest member
Tante

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top