Consolidate Excel Sheets to one Sheet using VBA

Been awhile since I used Visual Basic for Applications. I mean it's like VBScript on steroids.  So many things I'm used to now in Visual Studio 2008 that I take for granted.  Simple things, like collapsing my subs and functions. Or not getting a compile error just because I click off somewhere to copy a variable name. Anyway, I had a friend of mine, ask me how to consolidate sheets in excel. At first I said, oh that's easy, however the more I looked into it, consolidating numbers works fine, but when it comes to text, not so much.

The idea was this....

Sheet1 is the "Master" sheet, which will hold all the information from the other Sheets.

Sheet2 looks sort of of like this...

Name Address City State Zip
Bob Joe 1234 Kingly Tampa FL 33647
Jane Doe 352 Thisway Clearwater FL 33607
Billy Bob 232 Highway Atlanta GA 33450

Sheet3 looks like this....

Name Address City State Zip
Fred Mastro 13324 Lane Honolulu HI 45612
Brain Chris 845 Thatway Miami FL 12345
Dan April 232 ByWay Washington DC 78464
Jane See 3222 Flower Howell NJ 99706

The idea was to combine Sheet2, and Sheet3 into Sheet1 so that Sheet1 is the combined rows of both sheets. Then later be able to add say Sheet4 with more data and show it as well on Sheet1.

Sheet1 would look like this basically.....

Name Address City State Zip
Bob Joe 1234 Kingly Tampa FL 33647
Jane Doe 352 Thisway Clearwater FL 33607
Billy Bob 232 Highway Atlanta GA 33450
Fred Mastro 13324 Lane Honolulu HI 45612
Brain Chris 845 Thatway Miami FL 12345
Dan April 232 ByWay Washington DC 78464
Jane See 3222 Flower Howell NJ 99706

Easy way of doing this? At first glance you would suspect yes. Maybe I do not know all the Excel functions possible, I'm sure an Excel Guru maybe could. Upon searching the Internet I found many "add-ins" created by people to perform this function.

So I thought I'd save someone the trouble, here's a macro/vba code you could use in your excel sheet.  Most common problem when using this? Not having Macro's Enabled. Please make sure Macros are enabled for your workbook, and close and re-open excel after making the needed changes.

So in excel you'd have to find your VBA code. I'm using Excel 2007 so you have to show the developer tab first. Use help to find the Developer tab or View Code.

The event I used was Sheet1  Worksheet_Activate.  So on activate of Sheet1 the code runs.

Private Sub Worksheet_Activate()

End Sub

Then you can paste this function, this is the heart of it.  There a better way to write this? I'm sure there is, as I never work in creating VBA macros for Excel, this was my first run through. The last time I did VBA was with Access about 10 years ago.

Sub ConsolidateRows(ByVal SourceSheet As Worksheet, ByVal DestinationSheet As Worksheet, ByVal TotalColumns As Integer, Optional SkipFirstRow As Boolean = False)
    Dim SourceSheetRowCount As Integer
    Dim DestinationSheetRowCount As Integer
    Dim FoundDataInColumns As Boolean
    SourceSheetRowCount = 1
    If SkipFirstRow = True Then SourceSheetRowCount = 2
    DestinationSheetRowCount = 1
    FoundDataInColumns = False

    'Loop Through Every Source Sheet Row
    Do Until SourceSheetRowCount = SourceSheet.Rows.Count
        'Check Each Row for Data In First Cell
        If SourceSheet.Cells(SourceSheetRowCount, 1) = "" Then
            'If No Data In First Cell, Lets Check Rest of Cells In This Row
            For C = 2 To TotalColumns
                If SourceSheet.Cells(SourceSheetRowCount, C) <> "" Then
                    'Data Was Found In A Cell
                    FoundDataInColumns = True
                Else
                    FoundDataInColumns = False
                End If
                If FoundDataInColumns = True Then Exit For 'Data Found so Exit For, No Need To Check Rest of Cells
            Next
            If FoundDataInColumns = False Then Exit Do ' Data Was Not Found In Any of the Cells, so Exit Loop Completely, This Row is Empty
        Else
            FoundDataInColumns = True
        End If
        'If data was found, lets move on
        If FoundDataInColumns = True Then
            'Lets skip through rows that already have data on the DestinationSheet
            Do Until DestinationSheet.Cells(DestinationSheetRowCount, 1) = ""
                DestinationSheetRowCount = DestinationSheetRowCount + 1
            Loop
                'Now lets loop through the cells for this row and copy the data over
                For C = 1 To TotalColumns
                    DestinationSheet.Cells(DestinationSheetRowCount, C) = SourceSheet.Cells(SourceSheetRowCount, C)
                    'Could copy formatting here
                Next
            DestinationSheetRowCount = DestinationSheetRowCount + 1
        End If
        SourceSheetRowCount = SourceSheetRowCount + 1
        FoundDataInColumns = False
    Loop
End Sub

Now you could call this directly for each sheet you wanted to import into the master...

Call ConsolidateRows(Sheet2, Sheet1, 14)
Call ConsolidateRows(Sheet3, Sheet1, 14)

So after this, my friend was adding sheets, so I said, let me write a quick function to do all the sheets for you. So this function just loops through all the sheets and adds them to the destination one. Nothing fancy.

Sub ConsolidateAllSheetsTo(ByVal DestinationSheetName As String, ByVal DestinationSheet As Worksheet, ByVal TotalColumns As Integer)
    Dim Sheet As Worksheet
    Dim I As Integer
    I = 1
    For Each Sheet In ThisWorkbook.Worksheets
        If Sheet.Name <> DestinationSheetName Then
            If I = 1 Then
                Call ConsolidateRows(Sheet, DestinationSheet, TotalColumns)
            Else
                Call ConsolidateRows(Sheet, DestinationSheet, TotalColumns, True)
            End If
             I = I + 1
        End If
    Next
End Sub

And so then you can stop calling the ConsolidateRows directly and instead call ColsolidateAllSheetsTo instead.

Call ConsolidateAllSheetsTo("Master", Sheet1, 14)

Yes, yes I know "Call" is old school and you don't need it.  I just use it because it makes for faster skimming of code when I'm trying to debug.

So in the end, your activate event might look something like this...

Private Sub Worksheet_Activate()
    Sheet1.Cells.Delete
    Call ConsolidateAllSheetsTo("Master", Sheet1, 14)
End Sub

Complete Code from Top to Bottom:

   1: Private Sub Worksheet_Activate()
   2:     Sheet1.Cells.Delete
   3:     Call ConsolidateAllSheetsTo("Master", Sheet1, 14)
   4: End Sub
   5:
   6: Sub ConsolidateAllSheetsTo(ByVal DestinationSheetName As String, ByVal DestinationSheet As Worksheet, ByVal TotalColumns As Integer)
   7:     Dim Sheet As Worksheet
   8:     Dim I As Integer
   9:     I = 1
  10:     For Each Sheet In ThisWorkbook.Worksheets
  11:         If Sheet.Name <> DestinationSheetName Then
  12:             If I = 1 Then
  13:                 Call ConsolidateRows(Sheet, DestinationSheet, TotalColumns)
  14:             Else
  15:                 Call ConsolidateRows(Sheet, DestinationSheet, TotalColumns, True)
  16:             End If
  17:              I = I + 1
  18:         End If
  19:     Next
  20: End Sub
  21:
  22:
  23: Sub ConsolidateRows(ByVal SourceSheet As Worksheet, ByVal DestinationSheet As Worksheet, ByVal TotalColumns As Integer, Optional SkipFirstRow As Boolean = False)
  24:     Dim SourceSheetRowCount As Integer
  25:     Dim DestinationSheetRowCount As Integer
  26:     Dim FoundDataInColumns As Boolean
  27:     SourceSheetRowCount = 1
  28:     If SkipFirstRow = True Then SourceSheetRowCount = 2
  29:     DestinationSheetRowCount = 1
  30:     FoundDataInColumns = False
  31:
  32:     'Loop Through Every Source Sheet Row
  33:     Do Until SourceSheetRowCount = SourceSheet.Rows.Count
  34:         'Check Each Row for Data In First Cell
  35:         If SourceSheet.Cells(SourceSheetRowCount, 1) = "" Then
  36:             'If No Data In First Cell, Lets Check Rest of Cells In This Row
  37:             For C = 2 To TotalColumns
  38:                 If SourceSheet.Cells(SourceSheetRowCount, C) <> "" Then
  39:                     'Data Was Found In A Cell
  40:                     FoundDataInColumns = True
  41:                 Else
  42:                     FoundDataInColumns = False
  43:                 End If
  44:                 If FoundDataInColumns = True Then Exit For 'Data Found so Exit For, No Need To Check Rest of Cells
  45:             Next
  46:             If FoundDataInColumns = False Then Exit Do ' Data Was Not Found In Any of the Cells, so Exit Loop Completely, This Row is Empty
  47:         Else
  48:             FoundDataInColumns = True
  49:         End If
  50:         'If data was found, lets move on
  51:         If FoundDataInColumns = True Then
  52:             'Lets skip through rows that already have data on the DestinationSheet
  53:             Do Until DestinationSheet.Cells(DestinationSheetRowCount, 1) = ""
  54:                 DestinationSheetRowCount = DestinationSheetRowCount + 1
  55:             Loop
  56:                 'Now lets loop through the cells for this row and copy the data over
  57:                 For C = 1 To TotalColumns
  58:                     DestinationSheet.Cells(DestinationSheetRowCount, C) = SourceSheet.Cells(SourceSheetRowCount, C)
  59:                     'Could copy formatting here
  60:                 Next
  61:             DestinationSheetRowCount = DestinationSheetRowCount + 1
  62:         End If
  63:         SourceSheetRowCount = SourceSheetRowCount + 1
  64:         FoundDataInColumns = False
  65:     Loop
  66: End Sub

So there you have it, my quickly rigged consolidate function. Does it have bugs? Of course! It was free and quick.

Wexelblat's Scheduling Algorithm:

Choose Two:

  • Good
  • Fast
  • Cheap

So you can see by this.. it was Fast and Free, so = No Good. haha.

Known Issue, I don't think these are bugs, just things I didn't code for.

-Your Source Sheets can not have blank rows between data. Code will stop at first blank row and go to next sheet -Your source sheets have to have data in the first column, otherwise it gets overwritten on the master

That's all I know of so far.

Good luck, hope this helps someone out there, 5 years from now.

Upgrading my MacBook Pro 17" 200GB Hard Drive to 320GB with Boot Camp partition (using VMFusion)

Team Foundation TFS 2010/2008 Deleting / Solving Multiple Workspace Problem