Search code examples
excelvba

problem with VBA code for vlookup from a few different workbooks


I am new to VBA, but want to try and make a code that groups, counts, sorts and vlookups values from 3 diferent files.

At the moment I am at a point where I group, sort and count the data, but the vlookup is not working properly - it gives answers that are not exact match, even dough its in the code.

Can you please help with here I am wrong?

Sub GroupMentionsSortedAndVLookupThreeWorkbooks()
    Dim wsSource As Worksheet
    Dim wsOutput As Worksheet
    Dim mentionsRange As Range
    Dim mentionDict As Object
    Dim mention As Variant
    Dim lastRow As Long
    Dim i As Long
    Dim outputRow As Long
    Dim sortedMentions As Variant
    Dim currentLetter As String
    Dim firstLetter As String
    
    Dim wb2 As Workbook
    Dim ws2 As Worksheet
    Dim lookupRange2 As Range
    Dim lookupValue As String
    Dim lookupResult2 As Variant
    
    Dim wb3 As Workbook
    Dim ws3 As Worksheet
    Dim lookupRange3 As Range
    Dim lookupResult3 As Variant
    
    Dim wb4 As Workbook
    Dim ws4 As Worksheet
    Dim lookupRange4 As Range
    Dim lookupResult4 As Variant
    
    Dim combinedResult As String
    Dim finalResult As String
    
    ' Set source and output worksheets in Workbook 1
    Set wsSource = ThisWorkbook.Sheets("Sheet1") ' Source of the mentions
    Set wsOutput = ThisWorkbook.Sheets("Sheet2") ' Output sheet for grouped mentions
    
    ' Clear the output sheet
    wsOutput.Cells.Clear
    
    ' Find the last row with data in Sheet1 (Column A)
    lastRow = wsSource.Cells(wsSource.Rows.Count, "A").End(xlUp).Row
    
    ' Set the range for the mentions
    Set mentionsRange = wsSource.Range("A1:A" & lastRow)
    
    ' Create a dictionary object to store mention counts
    Set mentionDict = CreateObject("Scripting.Dictionary")
    
    ' Loop through the mentions and count occurrences
    For i = 1 To mentionsRange.Rows.Count
        mention = mentionsRange.Cells(i, 1).Value
        If mentionDict.exists(mention) Then
            mentionDict(mention) = mentionDict(mention) + 1
        Else
            mentionDict.Add mention, 1
        End If
    Next i
    
    ' Get the sorted list of keys (mentions)
    sortedMentions = mentionDict.Keys
    Call QuickSort(sortedMentions, LBound(sortedMentions), UBound(sortedMentions))
    
    ' Output the grouped mentions and counts to Sheet2
    outputRow = 1
    wsOutput.Cells(outputRow, 1).Value = "Item"
    wsOutput.Cells(outputRow, 2).Value = "Count"
    wsOutput.Cells(outputRow, 3).Value = "Lookup from WB2"
    wsOutput.Cells(outputRow, 4).Value = "Lookup from WB3"
    wsOutput.Cells(outputRow, 5).Value = "Lookup from WB4"
    wsOutput.Cells(outputRow, 6).Value = "Final Combined Result"
    outputRow = outputRow + 1
    
    ' Open Workbook2, Workbook3, and Workbook4
    Set wb2 = Workbooks.Open("C:\path\to\Workbook2.xlsx") ' Update the path to Workbook2
    Set ws2 = wb2.Sheets("Sheet1") ' Update if Workbook2 has a different sheet name
    lastRow = ws2.Cells(ws2.Rows.Count, "A").End(xlUp).Row
    Set lookupRange2 = ws2.Range("A1:B" & lastRow) ' Lookup range in Workbook2 (A and B)
    
    Set wb3 = Workbooks.Open("C:\path\to\Workbook3.xlsx") ' Update the path to Workbook3
    Set ws3 = wb3.Sheets("Sheet1") ' Update if Workbook3 has a different sheet name
    lastRow = ws3.Cells(ws3.Rows.Count, "A").End(xlUp).Row
    Set lookupRange3 = ws3.Range("A1:B" & lastRow) ' Lookup range in Workbook3 (A and B)
    
    Set wb4 = Workbooks.Open("C:\path\to\Workbook4.xlsx") ' Update the path to Workbook4
    Set ws4 = wb4.Sheets("Sheet1") ' Update if Workbook4 has a different sheet name
    lastRow = ws4.Cells(ws4.Rows.Count, "A").End(xlUp).Row
    Set lookupRange4 = ws4.Range("A1:B" & lastRow) ' Lookup range in Workbook4 (A and B)
    
    ' Add alphabetic separators and output the sorted data
    currentLetter = ""
    
    For i = LBound(sortedMentions) To UBound(sortedMentions)
        mention = sortedMentions(i)
        firstLetter = UCase(Left(mention, 1))
        
        ' If the first letter of the mention has changed, add a separator row
        If firstLetter <> currentLetter Then
            wsOutput.Cells(outputRow, 1).Value = firstLetter
            wsOutput.Cells(outputRow, 1).Font.Bold = True
            wsOutput.Cells(outputRow, 1).Font.Size = 12
            outputRow = outputRow + 1
            currentLetter = firstLetter
        End If
        
        ' Output the mention and its count
        wsOutput.Cells(outputRow, 1).Value = mention
        wsOutput.Cells(outputRow, 2).Value = mentionDict(mention)
        
        ' Perform the VLOOKUP for this mention in Workbook2
        lookupValue = Trim(CStr(mention)) ' Convert to string and trim spaces
        On Error Resume Next
        lookupResult2 = Application.WorksheetFunction.VLookup(lookupValue, lookupRange2, 2, False)
        On Error GoTo 0
        If IsError(lookupResult2) Then
            lookupResult2 = "#N/A"
        End If
        
        ' Perform the VLOOKUP for this mention in Workbook3
        On Error Resume Next
        lookupResult3 = Application.WorksheetFunction.VLookup(lookupValue, lookupRange3, 2, False)
        On Error GoTo 0
        If IsError(lookupResult3) Then
            lookupResult3 = "#N/A"
        End If
        
        ' Perform the VLOOKUP for this mention in Workbook4
        On Error Resume Next
        lookupResult4 = Application.WorksheetFunction.VLookup(lookupValue, lookupRange4, 2, False)
        On Error GoTo 0
        If IsError(lookupResult4) Then
            lookupResult4 = "#N/A"
        End If
        
        ' Output the individual lookup results in Columns C, D, and E
        wsOutput.Cells(outputRow, 3).Value = lookupResult2
        wsOutput.Cells(outputRow, 4).Value = lookupResult3
        wsOutput.Cells(outputRow, 5).Value = lookupResult4
        
        ' Combine the results
        combinedResult = ""
        If lookupResult2 <> "#N/A" Then combinedResult = lookupResult2
        If lookupResult3 <> "#N/A" Then
            If combinedResult <> "" And combinedResult <> lookupResult3 Then
                combinedResult = combinedResult & " \ " & lookupResult3
            ElseIf combinedResult = "" Then
                combinedResult = lookupResult3
            End If
        End If
        
        If lookupResult4 <> "#N/A" Then
            If combinedResult <> "" And combinedResult <> lookupResult4 Then
                combinedResult = combinedResult & " \ " & lookupResult4
            ElseIf combinedResult = "" Then
                combinedResult = lookupResult4
            End If
        End If
        
        ' If no matches, display #N/A
        If combinedResult = "" Then
            combinedResult = "#N/A"
        End If
        
        ' Output the final combined result in Column E
        wsOutput.Cells(outputRow, 6).Value = combinedResult
        
        outputRow = outputRow + 1
    Next i
    
    ' Close Workbook2, Workbook3, and Workbook4
    wb2.Close False
    wb3.Close False
    wb4.Close False
    
    MsgBox "Mentions have been grouped, sorted, and lookup results combined successfully!", vbInformation
End Sub
' QuickSort algorithm to sort the mentions alphabetically
Sub QuickSort(arr As Variant, low As Long, high As Long)
    Dim pivot As Variant
    Dim i As Long
    Dim j As Long
    Dim temp As Variant
    
    If low < high Then
        pivot = arr((low + high) \ 2)
        i = low
        j = high
        
        Do While i <= j
            Do While arr(i) < pivot
                i = i + 1
            Loop
            Do While arr(j) > pivot
                j = j - 1
            Loop
            
            If i <= j Then
                temp = arr(i)
                arr(i) = arr(j)
                arr(j) = temp
                i = i + 1
                j = j - 1
            End If
        Loop
        
        Call QuickSort(arr, low, j)
        Call QuickSort(arr, i, high)
    End If
End Sub

Solution

  • This will not work as you expect it to:

    ' Perform the VLOOKUP for this mention in Workbook2
    lookupValue = Trim(CStr(mention)) ' Convert to string and trim spaces
    On Error Resume Next
    lookupResult2 = Application.WorksheetFunction.VLookup(lookupValue, lookupRange2, 2, False)
    On Error GoTo 0
    If IsError(lookupResult2) Then
         lookupResult2 = "#N/A"
    End If
    

    When using WorksheetFunction if no match is made then that line raises an error and no assignment is made for lookupResult2, and it retains whatever value it had previously.

    This would work:

    lookupResult2 = Application.VLookup(lookupValue, lookupRange2, 2, False)
    'then check using `If IsError(lookupResult2)`
    

    Without the WorksheetFunction, vlookup returns an error value if there's no match.