Compare first 3 characters in two columns to find multiple matchings

youngernest

New Member
Joined
May 19, 2023
Messages
3
Office Version
  1. 2021
  2. 2019
  3. 2016
Platform
  1. Windows
I need to compare column A (ref1) and column B (ref2) with the same first 3 characters of a string. For the same 3 characters, then I will copy the entire multiple matching row to new tab. I will then insert one row below each matching and sum column C.



The raw data should look like this



Ref1Ref2Price
CatGreen2
YellowCathjb-2
Dog345Black1
WhiteDog1
Bird34Purple4
DogOrange-2
BlueBird3


The result will be as below in the new tab



Ref1Ref2Price
CatGreen2
YellowCathjb-2
0
Dog345Black1
WhiteDog1
DogOrange-2
0
Bird34Purple4
BlueBird3
7
From the new tab, row 2 and 3 have same first 3 character of Cat, then Dog, then Bir.



I tried using below code but got an error.

VBA Code:
Sub CompareAndCalculateSum()
    Dim wsSource As Worksheet
    Dim wsDestination As Worksheet
    Dim lastRowA As Long
    Dim lastRowB As Long
    Dim i As Long, j As Long
    Dim dictA As Object
    Dim dictB As Object
    Dim key As String
    Dim total As Double
    Dim newRow As Long
    Dim copyRange As Range
    
    ' Set the source and destination worksheets
    Set wsSource = ThisWorkbook.Sheets("Sheet1") ' Replace "Sheet1" with the actual name of your source sheet
    Set wsDestination = ThisWorkbook.Sheets.Add(After:=wsSource)
    wsDestination.Name = "MatchingRows"
    
    ' Find the last row in column A and B
    lastRowA = wsSource.Cells(wsSource.Rows.Count, "A").End(xlUp).Row
    lastRowB = wsSource.Cells(wsSource.Rows.Count, "B").End(xlUp).Row
    
    ' Create dictionaries to store the matching groups
    Set dictA = CreateObject("Scripting.Dictionary")
    Set dictB = CreateObject("Scripting.Dictionary")
    
    ' Loop through each row in column A
    For i = 1 To lastRowA
        ' Get the key from the first 3 characters in column A
        key = Left(wsSource.Cells(i, "A").Value, 3)
        
        ' Check if the key already exists in the dictionary
        If Not dictA.exists(key) Then
            dictA(key) = New Collection
        End If
        
        ' Add the row to the matching group
        dictA(key).Add i
    Next i
    
    ' Loop through each row in column B
    For j = 1 To lastRowB
        ' Get the key from the first 3 characters in column B
        key = Left(wsSource.Cells(j, "B").Value, 3)
        
        ' Check if the key already exists in the dictionary
        If Not dictB.exists(key) Then
            dictB(key) = New Collection
        End If
        
        ' Add the row to the matching group
        dictB(key).Add j
    Next j
    
    ' Initialize the newRow variable
    newRow = 1
    
    ' Loop through each key in dictionary A
    For Each key In dictA.keys
        ' Check if the key exists in dictionary B
        If dictB.exists(key) Then
            ' Calculate the sum in column C for the matching group
            total = 0
            
            ' Copy the matching rows to the destination sheet and calculate the total
            For Each itemA In dictA(key)
                For Each itemB In dictB(key)
                    If copyRange Is Nothing Then
                        Set copyRange = wsSource.Rows(itemA)
                    Else
                        Set copyRange = Union(copyRange, wsSource.Rows(itemA))
                    End If
                    total = total + wsSource.Cells(itemA, "C").Value + wsSource.Cells(itemB, "C").Value
                Next itemB
            Next itemA
            
            ' Copy the matching rows to the destination sheet
            copyRange.Copy wsDestination.Cells(newRow, 1)
            newRow = newRow + copyRange.Rows.Count
            
            ' Insert a new row to display the total in column C
            wsDestination.Cells(newRow, "C").Value = total
            newRow = newRow + 1
            
            ' Reset the copyRange variable for the next group
            Set copyRange = Nothing
        End If
    Next key
End Sub

Do you guys have any idea on how to do this? I only know to do if it has two matching rows. Not able to do for three or more rows like the Dog example.
 

Excel Facts

Test for Multiple Conditions in IF?
Use AND(test, test, test, test) or OR(test, test, test, ...) as the logical_test argument of IF.
Hi @youngernest
Welcome to the MrExcel forum. Please accept my warmest greetings and sincere hope that all is well.​

I made a new macro.
Based on your examples, the data is in columns A, B, and C, starting at row 2.
Try this:
VBA Code:
Sub CompareFirst3Characters()
  Dim dic As Object
  Dim tot As Double
  Dim ky1 As String, ky2 As String, theky As String
  Dim a As Variant, b As Variant, c As Variant, ky As Variant
  Dim i As Long, j As Long, k As Long, y As Long, nRow As Long, nCol As Long
  
  a = Sheets("Sheet1").Range("A2:C" & Sheets("Sheet1").Range("A" & Rows.Count).End(3).Row).Value
  ReDim b(1 To UBound(a, 1), 1 To UBound(a, 1))
  ReDim c(1 To UBound(a, 1) * 2, 1 To 3)
  Set dic = CreateObject("Scripting.Dictionary")
  
  For i = 1 To UBound(a, 1)
    ky1 = Left(a(i, 1), 3)
    ky2 = Left(a(i, 2), 3)
    theky = ""
    If dic.exists(ky1) Then
      theky = ky1
    ElseIf dic.exists(ky2) Then
      theky = ky2
    End If
    If theky = "" Then
      y = y + 1
      dic(ky1) = y & "|" & 1
      b(y, 1) = i
    Else
      nRow = Split(dic(theky), "|")(0)
      nCol = Split(dic(theky), "|")(1)
      nCol = nCol + 1
      b(nRow, nCol) = i
      dic(theky) = nRow & "|" & nCol
    End If
  Next
  
  For Each ky In dic.keys
    nRow = Split(dic(ky), "|")(0)
    nCol = Split(dic(ky), "|")(1)
    tot = 0
    For j = 1 To nCol
      k = k + 1
      c(k, 1) = a(b(nRow, j), 1)
      c(k, 2) = a(b(nRow, j), 2)
      c(k, 3) = a(b(nRow, j), 3)
      tot = tot + c(k, 3)
    Next
    c(k + 1, 3) = tot
    k = k + 1
  Next
  
  Sheets.Add after:=Sheets(Sheets.Count)
  Range("A2").Resize(UBound(c, 1), UBound(c, 2)).Value = c
End Sub

--------------
Let me know the result and I'll get back to you as soon as I can.
Cordially
Dante Amor
--------------​
 
Upvote 0
Hi @youngernest
Welcome to the MrExcel forum. Please accept my warmest greetings and sincere hope that all is well.​

I made a new macro.
Based on your examples, the data is in columns A, B, and C, starting at row 2.
Try this:
VBA Code:
Sub CompareFirst3Characters()
  Dim dic As Object
  Dim tot As Double
  Dim ky1 As String, ky2 As String, theky As String
  Dim a As Variant, b As Variant, c As Variant, ky As Variant
  Dim i As Long, j As Long, k As Long, y As Long, nRow As Long, nCol As Long
 
  a = Sheets("Sheet1").Range("A2:C" & Sheets("Sheet1").Range("A" & Rows.Count).End(3).Row).Value
  ReDim b(1 To UBound(a, 1), 1 To UBound(a, 1))
  ReDim c(1 To UBound(a, 1) * 2, 1 To 3)
  Set dic = CreateObject("Scripting.Dictionary")
 
  For i = 1 To UBound(a, 1)
    ky1 = Left(a(i, 1), 3)
    ky2 = Left(a(i, 2), 3)
    theky = ""
    If dic.exists(ky1) Then
      theky = ky1
    ElseIf dic.exists(ky2) Then
      theky = ky2
    End If
    If theky = "" Then
      y = y + 1
      dic(ky1) = y & "|" & 1
      b(y, 1) = i
    Else
      nRow = Split(dic(theky), "|")(0)
      nCol = Split(dic(theky), "|")(1)
      nCol = nCol + 1
      b(nRow, nCol) = i
      dic(theky) = nRow & "|" & nCol
    End If
  Next
 
  For Each ky In dic.keys
    nRow = Split(dic(ky), "|")(0)
    nCol = Split(dic(ky), "|")(1)
    tot = 0
    For j = 1 To nCol
      k = k + 1
      c(k, 1) = a(b(nRow, j), 1)
      c(k, 2) = a(b(nRow, j), 2)
      c(k, 3) = a(b(nRow, j), 3)
      tot = tot + c(k, 3)
    Next
    c(k + 1, 3) = tot
    k = k + 1
  Next
 
  Sheets.Add after:=Sheets(Sheets.Count)
  Range("A2").Resize(UBound(c, 1), UBound(c, 2)).Value = c
End Sub

--------------
Let me know the result and I'll get back to you as soon as I can.
Cordially
Dante Amor
--------------​
Hi I have tweaked some of the code to fit my criteria. Changed it from first 3 characters to first 6 characters.

VBA Code:
Sub CompareFirst6Characters()
    Dim dic As Object
    Dim tot As Double
    Dim ky1 As String, ky2 As String, theky As String
    Dim a As Variant, b As Variant, c As Variant, ky As Variant
    Dim i As Long, j As Long, k As Long, y As Long, nRow As Long, nCol As Long
    Dim newSheet As Worksheet
    
    ' Read data from Sheet1
    a = Sheets("Sheet1").Range("A1:C" & Sheets("Sheet1").Range("A" & Rows.Count).End(3).Row).Value
    
    ReDim b(1 To UBound(a, 1), 1 To UBound(a, 1))
    ReDim c(1 To UBound(a, 1) * 2 + 1, 1 To 3) ' Increase the row count to include the header
    Set dic = CreateObject("Scripting.Dictionary")
    
    ' Copy header to the result array
    For j = 1 To UBound(a, 2)
        c(1, j) = a(1, j)
    Next
    
    For i = 2 To UBound(a, 1) ' Start from row 2 to skip the header
        ky1 = Left(a(i, 1), 6)
        ky2 = Left(a(i, 2), 6)
        theky = ""
        If dic.Exists(ky1) Then
            theky = ky1
        ElseIf dic.Exists(ky2) Then
            theky = ky2
        End If
        If theky = "" Then
            y = y + 1
            dic(ky1) = y & "|" & 1
            b(y, 1) = i
        Else
            nRow = Split(dic(theky), "|")(0)
            nCol = Split(dic(theky), "|")(1)
            nCol = nCol + 1
            b(nRow, nCol) = i
            dic(theky) = nRow & "|" & nCol
        End If
    Next
    
    For Each ky In dic.keys
        nRow = Split(dic(ky), "|")(0)
        nCol = Split(dic(ky), "|")(1)
        tot = 0
        For j = 1 To nCol
            k = k + 1
            c(k + 1, 1) = a(b(nRow, j), 1)
            c(k + 1, 2) = a(b(nRow, j), 2)
            c(k + 1, 3) = a(b(nRow, j), 3)
            tot = tot + c(k + 1, 3)
        Next
        c(k + 2, 3) = tot
        k = k + 2
    Next
    
    ' Add a new worksheet and write the result
    Set newSheet = Sheets.Add(After:=Sheets(Sheets.Count))
    newSheet.Name = "Result"
    newSheet.Range("A1").Resize(UBound(c, 1), UBound(c, 2)).Value = c
End Sub

However, my current data has 27 columns. Based on table above, column A= column K in my dataset, column B=L, and column C=G. I'm not able to figure out how to change the code to fit this. And also, I'm wondering if we able to highlight all the row that has total sum to zero in yellow.
 
Upvote 0
column A= column K in my dataset, column B=L, and column C=G
Ok try the following:
VBA Code:
Sub Compare_Characters()
  Dim dic As Object
  Dim tot As Double
  Dim ky1 As String, ky2 As String, theky As String
  Dim a As Variant, b As Variant, c As Variant, ky As Variant
  Dim i As Long, j As Long, k As Long, y As Long, nRow As Long, nCol As Long
  Dim sh As Worksheet
  Set sh = Sheets("Sheet1")
  
  a = sh.Range("A2", sh.Cells(sh.Range("K" & Rows.Count).End(3).Row, 27)).Value
  ReDim b(1 To UBound(a, 1), 1 To UBound(a, 1))
  ReDim c(1 To UBound(a, 1) * 2, 1 To 3)
  Set dic = CreateObject("Scripting.Dictionary")
  
  For i = 1 To UBound(a, 1)
    ky1 = Left(a(i, 11), 6)       'column K
    ky2 = Left(a(i, 12), 6)       'column L
    theky = ""
    If dic.exists(ky1) Then
      theky = ky1
    ElseIf dic.exists(ky2) Then
      theky = ky2
    End If
    If theky = "" Then
      y = y + 1
      dic(ky1) = y & "|" & 1
      b(y, 1) = i
    Else
      nRow = Split(dic(theky), "|")(0)
      nCol = Split(dic(theky), "|")(1)
      nCol = nCol + 1
      b(nRow, nCol) = i
      dic(theky) = nRow & "|" & nCol
    End If
  Next
  
  For Each ky In dic.keys
    nRow = Split(dic(ky), "|")(0)
    nCol = Split(dic(ky), "|")(1)
    tot = 0
    For j = 1 To nCol
      k = k + 1
      c(k, 1) = a(b(nRow, j), 11)    'column K
      c(k, 2) = a(b(nRow, j), 12)    'column L
      c(k, 3) = a(b(nRow, j), 7)     'column G
      tot = tot + c(k, 3)
    Next
    c(k + 1, 3) = tot
    k = k + 1
  Next
  
  Sheets.Add after:=Sheets(Sheets.Count)
  Range("A2").Resize(UBound(c, 1), UBound(c, 2)).Value = c
End Sub
 
Upvote 0

Forum statistics

Threads
1,223,712
Messages
6,174,033
Members
452,542
Latest member
Bricklin

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