Excel VBA Course
Excel VBA Course - From Beginner to Expert

200+ Video Lessons
50+ Hours of Video
200+ Excel Guides

Become a master of VBA and Macros in Excel and learn how to automate all of your tasks in Excel with this online course. (No VBA experience required.)

View Course

combine two columns across sheets in one column

0

hello 

I  need  way to mrege  two  columns  across sheets  without  duplicating 

so  I  put  the result  in sheet  summary  how  should  show .

with  considering  I  put  simple  data  to  understand  my  idea , but  my  real  data  about  500 rows  in  all  the  sheets .

this  is  what  I  have , but  it's  not  based  on  my  requirement 

Sub CopyRange()
    Dim bottomD As Integer
    Dim ws As Worksheet
    For Each ws In Sheets(Array("A", "B", "C"))
        ws.Activate
        bottomD = Range("B" & Rows.Count).End(xlUp).Row
        Range("A2:B" & bottomD).Copy Sheets("Summary").Cells(Rows.Count, "A").End(xlUp).Offset(1, 0)
    Next ws
End Sub

thanks

Answer
Discuss

Answers

0
Selected Answer

Alaa

The attached file contains the revised macro below (heavily commented for your guidance)- it can now be run from a form button called "Collate from other sheets" on the "summary" sheet.

It uses a VBA dictionary (which is alphabetically sorted anyway) whose "key" is the combined values (from columns B and C) and the output (currently blank) will list the combinations plus say where they were found (in column D) - I think that might be useful when you have many rows but you could change the code to avoid that.

To understand a little more about why I used a dictionary, see my recently selected Answer at higlight new data across sheets with matching in another

Note there's a (commented) line in bold below giving you an extra learning point.

Sub CopyRange()
    Dim bottomB As Integer
    Dim ws As Worksheet
    Dim OutDict As Object, Key As Variant, n As Integer, Val As String
    'create a new empty dicionary
    Set OutDict = CreateObject("scripting.dictionary")

    'Loop through sheets
    For Each ws In Sheets(Array("A", "B", "C"))
        'ws.Activate ' ## no need to activate a worksheet to work on it
        bottomB = ws.Range("B" & Rows.Count).End(xlUp).Row
        ' loop down sheet rows
        For n = 2 To bottomB
            'create a "key" from B and C with a rare delimiter (¬)
            Val = ws.Cells(n, 2) & "¬" & ws.Cells(n, 3)
            ' if there's no dictionary key like that, add one with no value
            If Not OutDict.exists(Val) Then OutDict.Add Key:=Val, Item:=""
            ' add something to the value for that key (here the worksheet name and cell without $ signs)
            OutDict(Val) = OutDict(Val) & ws.Name & "(" & Cells(n, 2).Address(False, False) & "); "
        Next n
    Next ws

    With Sheets("summary")
        bottomB = .UsedRange.Rows.Count
        'clear existing rows below header (if any)
        If bottomB > 1 Then .Range("B2:B" & bottomB).EntireRow.Delete
        n = 2
        ' loop through dictionary and add to row (n)
        For Each Key In OutDict
            'split values (using delimter ¬), add to cells and draw borders
            .Cells(n, 2).Resize(1, 2) = Split(Key, "¬")
            'optionally output the dictionary value
            .Cells(n, 4) = OutDict(Key)
            'draw borders around cells
            .Cells(n, 2).Resize(1, 3).Borders.LineStyle = xlContinuous
            'increment row counter
            n = n + 1
        Next Key
        ' set the column widths to suit contents
        .Columns("B:D").AutoFit
        ' show this sheet
        .Activate
    End With
    ' tell user something happened
    MsgBox "Items found= " & OutDict.Count
End Sub

Finally, you're using an array of sheet names for your loop- that's fine but if you have just one summary sheet and need to loop through every other sheet (and there are many more than 3), you might want to use this instead (same code extract as above but with changes in bold and comments removed):

    'Loop through sheets
    For Each ws In ThisWorkbook.Sheets
        If ws.Name <> "summary" Then
        bottomB = ws.Range("B" & Rows.Count).End(xlUp).Row
            For n = 2 To bottomB
                Val = ws.Cells(n, 2) & "¬" & ws.Cells(n, 3)
                If Not OutDict.exists(Val) Then OutDict.Add Key:=Val, Item:=""
                OutDict(Val) = OutDict(Val) & ws.Name & "(" & Cells(n, 2).Address(False, False) & "); "
            Next n
        End If
    Next ws

Hope this helps.

Discuss

Discussion

Alaa. I forgot to say that my sheet A deleted column A to leave values in columns B and C (like sheets B, C and D).
John_Ru (rep: 6142) Feb 28, '22 at 5:25 am
truly  this  is  impressive !  but  just   curiosity   , I  note  your  code  is  too  slow . it  gives  running  speed  about 8.50  with  comparision  my  simple  data. do  you  think  the code  is  too  slow  or  it's  normal ?
Alaa (rep: 28) Feb 28, '22 at 7:58 am
Alaa, the code isn't slow on my old PC (with your example data)- if I comment out the MsgBox line (so eliminating the need for a user response) then the run duration = 0.02734375 seconds. 

If you need to quicken the macro, Don has a sub-section of his tutorials here: Speeding Up Macros

If I apply the method:
Application.ScreenUpdating = False
<code>
Application.ScreenUpdating = False
, then the run duration = 0.0078125 seconds (so about 3.5 times faster).

If you have a large amount of data then an array approach might be needed to make it even quicker (but you didn't ask that).

Also, if I answered your question, please rememeber to mark my Answer as selected.
John_Ru (rep: 6142) Feb 28, '22 at 8:43 am
then the run duration = 0.0078125 seconds (so about 3.5 times faster).
this what I want from you to confirm me . it seems from my PC  or because I open many files EXCEL .
Also, if I answered your question, please rememeber to mark my Answer as selected.
yes  you  really  did  it.
much  appreciated  for  your  help.
Alaa (rep: 28) Feb 28, '22 at 1:21 pm
Thanks for selecting my answer Alaa. As you say, things will slow down if you  have several Excel files open since your PC will need to share resource . I suggest you try the file when only that app/file is running. 
John_Ru (rep: 6142) Feb 28, '22 at 2:06 pm
Add to Discussion


Answer the Question

You must create an account to use the forum. Create an Account or Login