VBA Dictionary to merge rows

Guinaba

Board Regular
Joined
Sep 19, 2018
Messages
233
Office Version
  1. 2016
Platform
  1. Windows
Hi guys,

Wondering if there is a way to combine rows like the example below, my range has 10 columns and whenever there is the same record in a different row, after running the code the new format is the bottom part:

1689249541910.png


The code still not correct, but I appreciate any suggestion.

VBA Code:
Sub DataDic()
  Dim dic As Object
  Dim a As Variant
  Dim c As Range
  Dim i As Long

  Set dic = CreateObject("Scripting.Dictionary")

  With Sheets("Export")
    ReDim a(1 To .Range("A" & Rows.Count).End(xlUp).Row, 1 To 10)
    For Each c In .Range("A2", .Range("A" & Rows.Count).End(xlUp))
      If Not dic.exists(c.Value) Then
        i = i + 1
        dic(c.Value) = i
        a(i, 1) = c.Value
        a(i, 2) = c.Offset(, 1).Value
        a(i, 3) = c.Offset(, 2).Value
        a(i, 4) = c.Offset(, 3).Value
        a(i, 5) = c.Offset(, 4).Value
        a(i, 6) = c.Offset(, 5).Value
        a(i, 7) = c.Offset(, 6).Value
        a(i, 8) = c.Offset(, 7).Value
        a(i, 9) = c.Offset(, 8).Value
        a(i, 10) = c.Offset(, 9).Value
      Else
        i = dic(c.Value)
        a(i, 10) = a(i, 10) & Chr(10) & c.Offset(, 5).Value
      End If
    Next
    .Range("M2").Resize(UBound(a), 3).Value = a
  End With
  Set dic = Nothing
End Sub
 

Excel Facts

Who is Mr Spreadsheet?
Author John Walkenbach was Mr Spreadsheet until his retirement in June 2019.
Try:

VBA Code:
Sub DataDic()
  Dim sh1 As Worksheet
  Dim dic As Object
  Dim a As Variant, b As Variant
  Dim i As Long, j As Long, n As Long

  Set sh1 = Sheets("Export")
  Set dic = CreateObject("Scripting.Dictionary")

  a = sh1.Range("A2:J" & sh1.Range("A" & Rows.Count).End(3).Row).Value
  ReDim b(1 To UBound(a, 1), 1 To UBound(a, 2))
        
  For i = 1 To UBound(a)
    If Not dic.exists(a(i, 1)) Then dic(a(i, 1)) = dic.Count + 1
    n = dic(a(i, 1))
    For j = 1 To UBound(a, 2)
      If b(n, j) = "" Then b(n, j) = a(i, j)
      If b(n, j) <> a(i, j) Then b(n, j) = b(n, j) & ", " & Chr(10) & a(i, j)
    Next
  Next
  sh1.Range("M2").Resize(UBound(b, 1), UBound(b, 2)).Value = b
End Sub

--------------
Let me know the result and I'll get back to you as soon as I can.
Cordially
Dante Amor
--------------​
 
Last edited:
Upvote 0
Try:

VBA Code:
Sub DataDic()
  Dim sh1 As Worksheet
  Dim dic As Object
  Dim a As Variant, b As Variant
  Dim i As Long, j As Long, n As Long

  Set sh1 = Sheets("Export")
  Set dic = CreateObject("Scripting.Dictionary")

  a = sh1.Range("A2:J" & sh1.Range("A" & Rows.Count).End(3).Row).Value
  ReDim b(1 To UBound(a, 1), 1 To UBound(a, 2))
      
  For i = 1 To UBound(a)
    If Not dic.exists(a(i, 1)) Then dic(a(i, 1)) = dic.Count + 1
    n = dic(a(i, 1))
    For j = 1 To UBound(a, 2)
      If b(n, j) = "" Then b(n, j) = a(i, j)
      If b(n, j) <> a(i, j) Then b(n, j) = b(n, j) & ", " & Chr(10) & a(i, j)
    Next
  Next
  sh1.Range("M2").Resize(UBound(b, 1), UBound(b, 2)).Value = b
End Sub

--------------
Let me know the result and I'll get back to you as soon as I can.
Cordially
Dante Amor
--------------​
Hey @DanteAmor,

Thank you for your prompt help, but the code still not generating the correct format, here is the source data that I am using:


Input:
Material NumberLocation IDExpiry DateEXTN FlagTip DateStock StatusBatch IDSum of QTY (ZPU)EXTN FlagEXTN Days
12530311024
7/02/2024​
N
30/08/2023​
0000145242
2970​
N0
12530311024
7/02/2024​
N
30/08/2023​
0000145259
3879​
N0
12530311026
6/02/2024​
N
29/08/2023​
0000145072
3780​
N0
12530311026
6/02/2024​
N
29/08/2023​
0000145110
2249​
N0
12530311026
6/02/2024​
N
29/08/2023​
0000145174
1620​
N0
12530311026
6/02/2024​
N
29/08/2023​
0000145230
810​
N0
12530311026
13/02/2024​
N
5/09/2023​
0000145889
3330​
N0
12530311026
13/02/2024​
N
5/09/2023​
0000145959
3240​
N0
12530311026
13/02/2024​
N
5/09/2023​
0000145979
720​
N0
12530311026
13/02/2024​
Y
5/09/2023​
0000145994
1800​
N0
12530311026
13/02/2024​
N
5/09/2023​
InTransit0000145857_IT
360​
N0
12530311026
13/02/2024​
N
5/09/2023​
InTransit0000145889_IT
540​
N0
12530311026
13/02/2024​
N
5/09/2023​
InTransit0000145959_IT
720​
N0
12530311026
13/02/2024​
N
5/09/2023​
InTransit0000145994_IT
540​
N0
12530311026
23/02/2024​
N
15/09/2023​
0000146925
1890​
N0
12530311026
28/02/2024​
N
20/09/2023​
InTransit0000147348_IT
1890​
N0
12530311026
28/02/2024​
N
20/09/2023​
InTransit0000147379_IT
90​
N0
12530311026
28/02/2024​
N
20/09/2023​
InTransit0000147450_IT
3060​
N0
12530311030
27/02/2024​
N
19/09/2023​
0000147293
13​
N0
12530311030
28/02/2024​
N
20/09/2023​
0000147379
90​
N0

Output:
Material NumberLocation IDExpiry DateEXTN FlagTip DateStock StatusBatch IDSum of QTY (ZPU)EXTN FlagEXTN Days
125303110247/02/2024N30/08/2023145242,1452592970,3879N0
125303110266/02/2024N29/08/2023145072,145110,145174,145230,145889,145959,1459793780,2249,1620,810,3330,3240,720N0
1253031102613/02/2024Y5/09/20231459941800N0
1253031102613/02/2024N5/09/2023InTransit0000145857_IT,0000145889_IT,0000145959_IT,0000145994_IT360,540,720,540N0
1253031102623/02/2024N15/09/20231469251890N0
1253031102628/02/2024N20/09/2023InTransit0000147348_IT,0000147379_IT,0000147450_IT1890,90,3060N0
1253031103027/02/2024N19/09/202314729313N0
1253031103028/02/2024N20/09/202314737990N0
 
Upvote 0
but the code still not generating the correct format

My code works as seen in your macro:
For Each c In .Range("A2", .Range("A" & Rows.Count).End(xlUp))
If Not dic.exists(c.Value) Then
That means the grouper is column A and that's just what my macro does.
-----------------------

Your example in the original post with only 2 records is not very representative. You must clearly explain which fields you need to carry out the grouping, they are your data and I do not know what the final objective is.
So explain what those columns are to group.

Your example from post #3 is not very clear either.
You are grouping the following numbers highlighted in yellow in a row where the date does not correspond, so you must explain what the grouping rules are for each of your records.

1689349447076.png



--------------
I hope to hear from you soon.
Respectfully
Dante Amor
--------------​
 
Upvote 0
Hey @DanteAmor,

Sorry, the logic was confusing for me, hopefully I am ansering your questions now.

I believe if you index columns (1,2,3,4,5,6,7,8), you will hit the nail on the head! Instead of only (A) , like in your code,

For Each c In .Range("A2", .Range("A" & Rows.Count).End(xlUp))
If Not dic.exists(c.Value) Then

1689376229020.png

Columns (1,2,3,4,5,6,7,8) should be indexed.

INPUT
12345678
Material NumberMaterial DescriptionLocation IDExpiry DateEXTN FlagEXTN DaysTip DateStock StatusQTY (ZPU)Batch ID
1253031XXXX Gold 30x375ml CAN DD 21102628/02/2024N020/09/2023InTransit30600000147450_IT
1253031XXXX Gold 30x375ml CAN DD 21102628/02/2024N020/09/2023InTransit900000147379_IT
1253031XXXX Gold 30x375ml CAN DD 21102628/02/2024N020/09/2023InTransit18900000147348_IT
1253031XXXX Gold 30x375ml CAN DD 21102623/02/2024N015/09/202318900000146925
1253031XXXX Gold 30x375ml CAN DD 21102613/02/2024N005/09/2023InTransit5400000145994_IT
1253031XXXX Gold 30x375ml CAN DD 21102613/02/2024N005/09/202318000000145994
1253031XXXX Gold 30x375ml CAN DD 21102613/02/2024N005/09/20237200000145979
1253031XXXX Gold 30x375ml CAN DD 21102613/02/2024N005/09/2023InTransit7200000145959_IT
1253031XXXX Gold 30x375ml CAN DD 21102613/02/2024N005/09/202332400000145959
1253031XXXX Gold 30x375ml CAN DD 21102613/02/2024N005/09/2023InTransit5400000145889_IT
1253031XXXX Gold 30x375ml CAN DD 21102613/02/2024N005/09/202333300000145889
1253031XXXX Gold 30x375ml CAN DD 21102613/02/2024N005/09/2023InTransit3600000145857_IT
1253031XXXX Gold 30x375ml CAN DD 21102407/02/2024N030/08/202338790000145259
1253031XXXX Gold 30x375ml CAN DD 21102407/02/2024N030/08/202329700000145242
OUPUT
12345678
Material NumberMaterial DescriptionLocation IDExpiry DateTip DateStock StatusQTY (ZPU)Batch ID
1253031XXXX Gold 30x375ml CAN DD 21102628/02/2024N020/09/2023InTransit3060,90,18900000147450_IT,0000147379_IT,0000147348_IT
1253031XXXX Gold 30x375ml CAN DD 21102623/02/2024N015/09/202318900000146925
1253031XXXX Gold 30x375ml CAN DD 21102613/02/2024N05/09/2023,InTransit, ,InTransit, ,InTransit, ,InTransit540,1800,720,720,3240,540,3330,3600000145994_IT,0000145994,0000145979,0000145959_IT,0000145959,0000145889_IT,0000145889,0000145857_IT
1253031XXXX Gold 30x375ml CAN DD 2110247/02/2024N030/08/20233879,29700000145259,0000145242
 

Attachments

  • 1689375475061.png
    1689375475061.png
    112.3 KB · Views: 7
Upvote 0
Again you changed the examples, you are not consistent in the examples.
Your example has errors.

The QTYs highlighted in yellow must be in another record since the Stock status column is empty, so they must not be on the same "Intransit" line

1689378226828.png



I give you the macro with the 8 column key, but the macro does not return the results as you are putting it.
From now on try to be consistent, clear and truthful with the examples.


VBA Code:
Sub DataDic()
  Dim sh1 As Worksheet
  Dim dic As Object
  Dim a As Variant, b As Variant, ky As Variant
  Dim i As Long, j As Long, n As Long

  Set sh1 = Sheets("Export")
  Set dic = CreateObject("Scripting.Dictionary")

  a = sh1.Range("A2:J" & sh1.Range("A" & Rows.Count).End(3).Row).Value
  ReDim b(1 To UBound(a, 1), 1 To UBound(a, 2))
  sh1.Range("M2:V" & Rows.Count).ClearContents
        
  For i = 1 To UBound(a)
    ky = a(i, 1) & "|" & a(i, 2) & "|" & a(i, 3) & "|" & a(i, 4) & "|" & _
         a(i, 5) & "|" & a(i, 6) & "|" & a(i, 7) & "|" & a(i, 8)
    If Not dic.exists(ky) Then dic(ky) = dic.Count + 1
    n = dic(ky)
    For j = 1 To UBound(a, 2)
      If b(n, j) = "" Then b(n, j) = a(i, j)
      If b(n, j) <> a(i, j) Then b(n, j) = b(n, j) & ", " & a(i, j)
    Next
  Next
  sh1.Range("M2").Resize(UBound(b, 1), UBound(b, 2)).Value = b
End Sub

Although I would like to continue offering my help, I will no longer do so because the examples are not consistent with what is described and that caused the macro not to work, but it is not a problem with the macro, it is a problem with the definition of the poster's data .

😶
 
Upvote 0
Again you changed the examples, you are not consistent in the examples.
Your example has errors.

The QTYs highlighted in yellow must be in another record since the Stock status column is empty, so they must not be on the same "Intransit" line

View attachment 95302


I give you the macro with the 8 column key, but the macro does not return the results as you are putting it.
From now on try to be consistent, clear and truthful with the examples.


VBA Code:
Sub DataDic()
  Dim sh1 As Worksheet
  Dim dic As Object
  Dim a As Variant, b As Variant, ky As Variant
  Dim i As Long, j As Long, n As Long

  Set sh1 = Sheets("Export")
  Set dic = CreateObject("Scripting.Dictionary")

  a = sh1.Range("A2:J" & sh1.Range("A" & Rows.Count).End(3).Row).Value
  ReDim b(1 To UBound(a, 1), 1 To UBound(a, 2))
  sh1.Range("M2:V" & Rows.Count).ClearContents
      
  For i = 1 To UBound(a)
    ky = a(i, 1) & "|" & a(i, 2) & "|" & a(i, 3) & "|" & a(i, 4) & "|" & _
         a(i, 5) & "|" & a(i, 6) & "|" & a(i, 7) & "|" & a(i, 8)
    If Not dic.exists(ky) Then dic(ky) = dic.Count + 1
    n = dic(ky)
    For j = 1 To UBound(a, 2)
      If b(n, j) = "" Then b(n, j) = a(i, j)
      If b(n, j) <> a(i, j) Then b(n, j) = b(n, j) & ", " & a(i, j)
    Next
  Next
  sh1.Range("M2").Resize(UBound(b, 1), UBound(b, 2)).Value = b
End Sub

Although I would like to continue offering my help, I will no longer do so because the examples are not consistent with what is described and that caused the macro not to work, but it is not a problem with the macro, it is a problem with the definition of the poster's data .

😶

Thanks @DanteAmor, the numbers messed up when copying and pasting into the website, but the logic I told you was corrrect now. Just looking at the picture I sent you having different collors per group, I believe you would be able to understand the logic. Anyway, thanks for your help. The sub is working now as expect.
 
Upvote 0
Please mark the post that has the solution, unless your own post contains the solution. Thank you
Dante Amor
 
Upvote 1
Columns (1,2,3,4,5,6,7,8) should be indexed.

If the result is not what you are looking for, you can remove column 8 in this line of the macro:
VBA Code:
ky = a(i, 1) & "|" & a(i, 2) & "|" & a(i, 3) & "|" & a(i, 4) & "|" & _
         a(i, 5) & "|" & a(i, 6) & "|" & a(i, 7) & "|" & a(i, 8)

For example:
VBA Code:
ky = a(i, 1) & "|" & a(i, 2) & "|" & a(i, 3) & "|" & a(i, 4) & "|" & _
         a(i, 5) & "|" & a(i, 6) & "|" & a(i, 7)

If the rules change later, you can play with those columns to determine which columns will be the index.
;)
 
Upvote 1
Solution
If the result is not what you are looking for, you can remove column 8 in this line of the macro:
VBA Code:
ky = a(i, 1) & "|" & a(i, 2) & "|" & a(i, 3) & "|" & a(i, 4) & "|" & _
         a(i, 5) & "|" & a(i, 6) & "|" & a(i, 7) & "|" & a(i, 8)

For example:
VBA Code:
ky = a(i, 1) & "|" & a(i, 2) & "|" & a(i, 3) & "|" & a(i, 4) & "|" & _
         a(i, 5) & "|" & a(i, 6) & "|" & a(i, 7)

If the rules change later, you can play with those columns to determine which columns will be the index.
;)
Awesome!! Thanks @DanteAmor!
 
Upvote 0

Forum statistics

Threads
1,223,911
Messages
6,175,324
Members
452,635
Latest member
laura12345

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