This Excel macro starts by filtering a column and create a new worksheet for each unique value found. By default, the active column selected will be filtered. If the active column selected is blank an InputBox will ask for the column number to filter. (Example: A=1, B=2, C=3, etc.) Once a column has been identified the duplicate values will be removed and what remains will be used to determine how many worksheets to create. Each worksheet will contain the filtered information based on each value found. Next each worksheet will be saved as their own workbook. By default, the Folder Path of the Active Workbook will be used so the new Workbooks are saved at the same location. (Customize: You can indicate a different path in the VBA code) When saving the Workbook name will be the name of the respective Worksheet. Finally, this macro will use the name of each Worksheet to find Workbooks with the same name in the Folder Path. If a match is found a new email with be generated with the Workbook attached. The Outlook email generated will have the subject and body populated. With a few updates to the VBA code you can have specific recipients pull in based on the Worksheet name.
These macros used together automates an entire process! The time saved using this macro allows you to focus on how you can bring more value to your customers. Take a look at the Value Stream Map we discussed in the Macro Monday video. We don’t know the source of the initial data but what follows is a standardized process leveraging VBA to complete all this busy work. Creating processes like this don’t just save time but also mistake proof processes eliminating defects. You won’t send the wrong attachment to the incorrect recipients if the computer performs the action for you. Of course, there is the potential the code doesn’t work but you can spend time ensuring this macro always works instead of relying on your ability to complete the steps of this process perfectly each and every time.
See it in Action!Watch this video to see this macro in action.
The CodeHere is the code for this macro. Make sure the following References are setup before running it: Visual Basic For Applications, Microsoft Excel 16.0 Object Library
'Leverage & Lean "Less Clicks, More Results" Sub ExcelCombineMacros16_18_23() ' Means variable is in use Dim ActiveColumn As Integer ' Dim ActiveWorksheetName As String ' Dim CCRecipients As String ' Dim Counter As Integer ' Dim DupLastColumnLetter As String ' Dim DupLastRow As Integer ' Dim FolderPath As String ' Dim i As Integer ' Dim LastColumnLetter As String ' Dim LastColumnNumber As Integer ' Dim LastRow As Integer ' Dim objNewEmail As Object ' Dim objOutlookApp As Object ' Dim oFile As Object ' Dim oFolder As Object ' Dim oFSO As Object ' Dim Recipients As String ' Dim WorksheetName As String ' Dim WS As Worksheet ' On Error GoTo LeverageLean 'Hide ScreenUpdating and Display Alerts Application.ScreenUpdating = False Application.DisplayAlerts = False FolderPath = Left(ActiveWorkbook.FullName, Len(ActiveWorkbook.FullName) - Len(ActiveWorkbook.Name)) 'Active Workbook Folder Path ActiveWorksheetName = ActiveSheet.Name 'What is the Active Sheet's Name LastColumnNumber = Cells(1, Columns.Count).End(xlToLeft).Column 'Identify Last Column Number LastColumnLetter = Replace(Cells(1, LastColumnNumber).Address(True, False), "$1", "") 'Identify Last Column Letter LastRow = Cells(Rows.Count, 1).End(xlUp).Row 'Identify Last Row on worksheet ActiveColumn = ActiveCell.Column 'What is the Active Column to filter If ActiveColumn > LastColumnNumber Then ActiveColumn = InputBox("What column do you want to filter?" & vbNewLine & vbNewLine & "Please use a number A=1, B=2, C=3, etc.") 'Pick a column with data in it ElseIf ActiveColumn > LastColumnNumber Then Exit Sub End If 'Copy Column information and remove duplicates Columns(ActiveColumn).Select Selection.Copy Columns(LastColumnNumber + 2).Select ActiveSheet.Paste DupLastColumnLetter = Replace(Cells(1, LastColumnNumber + 2).Address(True, False), "$1", "") 'Identify Column Letter in Duplicate Column ActiveSheet.Range(DupLastColumnLetter & "1:" & DupLastColumnLetter & LastRow).RemoveDuplicates Columns:=1, Header:=xlYes DupLastRow = Cells(Rows.Count, LastColumnNumber + 2).End(xlUp).Row 'Identify Last Row Number in Duplicate Column 'If there are more then 50 values Exit the Sub If DupLastRow > 50 Then Columns(LastColumnNumber + 2).Delete Range("A1").Select MsgBox "Exited because " & DupLastRow & " tabs were going to be created." Exit Sub End If Counter = 2 'Assuming there is a header row 'Loop through each duplicate value copy and paste information to appropriate worksheet Do Until Counter > DupLastRow Sheets(ActiveWorksheetName).Select WorksheetName = Cells(Counter, LastColumnNumber + 2).Value ActiveSheet.Range("$A$1:$" & LastColumnLetter & "$" & LastRow).AutoFilter Field:=ActiveColumn, Criteria1:=WorksheetName Range("A1").Select Range(Selection, Selection.End(xlDown)).Select Range(Selection, Selection.End(xlToRight)).Select Selection.Copy Set WS = Sheets.Add(After:=Sheets(Sheets.Count)) WS.Name = WorksheetName 'Use the duplicate value as a tab name Range("A1").Select ActiveSheet.Paste Counter = Counter + 1 Loop 'Clear the filter and delete the duplicates column Sheets(ActiveWorksheetName).Select ActiveSheet.AutoFilterMode = False Range("A1").Select Columns(LastColumnNumber + 2).Delete MsgBox "Excel Create Worksheet per Filter Value | VBA Macro #16 is complete!" For Each WS In ActiveWorkbook.Sheets WS.Copy 'Copy Worksheet Application.ActiveWorkbook.SaveAs Filename:=FolderPath & WS.Name & ".xlsx" 'Save new Workbooks to Active Workbook File Path Application.ActiveWorkbook.Close 'Remove if you want the New Workbooks to remain open Next MsgBox "Excel Save Worksheets as Workbooks | VBA Macro #18 is complete!" Set oFSO = CreateObject("Scripting.FileSystemObject") Set oFolder = oFSO.GetFolder(FolderPath) For i = 2 To Worksheets.Count 'Loop through every Worksheet (except the first one) For Each oFile In oFolder.Files 'Loop through every File in FolderPath If oFile.Name = Sheets(i).Name & Right(oFile.Name, (Len(oFile.Name) + 1) - InStrRev(oFile.Name, ".")) Then 'If the File Name equals the Worksheet Name 'Using the Worksheet Name indicate who the Email Recipients should be If Sheets(i).Name = "Marketing" Then Recipients = "" 'CCRecipients = "" ElseIf Sheets(i).Name = "Sales" Then Recipients = "" 'CCRecipients = "" ElseIf Sheets(i).Name = "IT" Then Recipients = "" 'CCRecipients = "" ElseIf Sheets(i).Name = "HR" Then Recipients = "" 'CCRecipients = "" ElseIf Sheets(i).Name = "Operations" Then Recipients = "" 'CCRecipients = "" ElseIf Sheets(i).Name = "PR" Then Recipients = "" 'CCRecipients = "" ElseIf Sheets(i).Name = "Finance" Then Recipients = "" 'CCRecipients = "" End If 'Create a new email Set objOutlookApp = CreateObject("Outlook.Application") Set objNewEmail = objOutlookApp.CreateItem(olMailItem) objNewEmail.To = Recipients 'objNewEmail.CC = CCRecipients 'Update to include CCed Recipients to emails objNewEmail.Subject = Sheets(i).Name & ": Review attached Workbook" objNewEmail.HTMLBody = "<HTML><BODY><span style=""font-family : Calibri;font-size : 11pt"">" & _ "Hello " & Sheets(i).Name & ",<br></br><br></br>" & _ "Can you please review the attached Workbook? Please contact me with any questions or concerns.<br></br><br></br>" & _ "Stay Awesome!</span></BODY></HTML>" objNewEmail.Attachments.Add FolderPath & "\" & oFile.Name objNewEmail.Display 'objNewEmail.Send 'Automatically send the email End If Next oFile Next Set objNewEmail = Nothing Set objOutlookApp = Nothing Set oFile = Nothing Set oFolder = Nothing Set oFSO = Nothing MsgBox "Excel Create Emails with Workbooks Attached | VBA Macro #23 is complete!" Exit Sub LeverageLean: MsgBox (Err.Number & " - " & Err.Description & vbNewLine & vbNewLine & "Don't hesitate to email me: firstname.lastname@example.org") End Sub 'Stay Awesome
Macro MondayHere is the Macro Monday video this macro was featured in. Watch this video to learn how to get the most out of this macro and start using it today!
Customization30. FolderPath = Left(ActiveWorkbook.FullName, Len(ActiveWorkbook.FullName) – Len(ActiveWorkbook.Name)) ‘Active Workbook Folder Path By Default the Folder Path is the Active Workbook but you can change this to a different path if desired
55. If DupLastRow > 50 Then If the filtered column returns more than 50 values the macro will exit to ensure the Excel can handle the request. Update this number to reflect how you want this to behave.
62. Counter = 2 ‘Assuming there is a header row If you are not working with a header row then you should change Counter = 1
82. ActiveSheet.AutoFilterMode = False If you don’t want the filter to be removed from the first spreadsheet make this line a comment with ‘ 84. Columns(LastColumnNumber + 2).Delete If you don’t want the duplicates column to be deleted from the first spreadsheet make this line a comment with ‘
86. MsgBox “Excel Create Worksheet per Filter Value | VBA Macro #16 is complete!” Remove the MsgBox or make it comment to not see it when this macro runs
94. MsgBox “Excel Save Worksheets as Workbooks | VBA Macro #18 is complete!” Remove the MsgBox or make it comment to not see it when this macro runs
99. For i = 2 To Worksheets.Count ‘Loop through every Worksheet (except the first one) By Default this macro will start at the 2nd Worksheet and loop through all the Worksheets following it. You can update 2 to a 1 to include the 1st Worksheet.
104 through 125 ‘Using the Worksheet Name indicate who the Email Recipients should be Update the Sheet Names and set the Recipients (also CCRecipients) with the appropriate email addresses
132. ‘objNewEmail.CC = CCRecipients ‘Update to include CCed Recipients to emails If CC’ing Recipients then update this code line to not be a comment
133. objNewEmail.Subject = Sheets(i).Name & “: Review attached Workbook” This code line controls what populates in the Email Subject
134 through 137 objNewEmail.HTMLBody These code lines control what will populate into the Email Body
140. ‘objNewEmail.Send ‘Automatically send the email If you want the email to send automatically then update this code line to not be a comment
153. MsgBox “Excel Create Emails with Workbooks Attached | VBA Macro #23 is complete!” Remove the MsgBox or make it comment to not see it when this macro runs