Last updated on October 4, 2024 By Victor Chan
Imagine your Excel worksheet is like a cluttered bookshelf, with all your books jumbled together. Finding what you need can be a real chore.
Now, what if you could magically organize those books into neat sections, making everything easy to find?
In Excel, this is like splitting your data into separate sheets based on categories. And guess what? There's a way to do this automatically and super fast using a bit of VBA magic!
In this tutorial, we'll show you how to use VBA (Visual Basic for Applications) to automatically split your data into multiple worksheets based on unique values in a category column.
Whether you're managing sales data, inventory lists, or personnel records, this method will save you time and effort.
Download FREE Excel Workbook
Step 1: Sign up for free Click Here
Step 2: Log in for access Click Here
Step 3: Download file Excel Table Splitter (VBA).zip
Are you new to Excel VBA Macros?
• Find out how to enable and disable macros in Excel with this tutorial
• Save time and effort by copying VBA macros from one workbook to another with these instructions
When working with large datasets, it's often helpful to split data into separate sheets based on categories. For example:
Splitting data manually is time-consuming and prone to errors. Automating this task not only saves time but also ensures consistency and accuracy.
Let's start by looking at how most people might approach this task manually.
Steps to Manually Split Data:
Example:
Suppose you have a list of employees from different departments, and you want to create a separate sheet for each department.
Drawbacks:
VBA stands for Visual Basic for Applications. It's like having a personal assistant inside Excel that can perform tasks for you.
Benefits of Using VBA:
By writing a simple VBA script, you can automatically split your data into multiple sheets based on unique categories.
Before using VBA, it's important to format your data as an Excel Table.
Why Use Excel Tables?
How to Create an Excel Table:
Now, let's set up the VBA code that will do the heavy lifting.
Step 1: Access the Developer Tab
If you don't see the Developer tab in Excel:
Step 2: Enable the Personal Macro Workbook
The Personal Macro Workbook is a hidden workbook that loads whenever you open Excel. It stores macros that you can use in any workbook.
Step 3: Insert the VBA Code
[VBA Code Box]
Option Explicit
' *** Module Overview ***
' This module automates filtering data in a table and copying the filtered results
' to new worksheets.
'
' ### Subroutines and Functions ###
'
' - Sub Filter_Table_To_Sheets:
' - Prompts the user to select a column to filter by.
' - Filters the table based on unique values in the selected column.
' - Creates new sheets for each unique value, copying the filtered data to them.
' - Handles user input for sorting and manages existing sheets with matching names.
'
' - Sub SortArray:
' - Sorts an array of values in either ascending or descending order using a
' simple sorting algorithm.
'
' - Function GetUniqueArray:
' - Extracts unique values from a specified range and returns them in an array.
'
' - Function CleanSheetName:
' - Cleans up sheet names by truncating to Excel's 31 character limit and
' replacing invalid characters to make them valid Excel sheet names.
'
' - Function EnsureUniqueSheetName:
' - Ensures that a sheet name is unique by adding a numeric suffix if needed.
'
' - Function SheetExists:
' - Checks if a worksheet with a given name already exists in the workbook.
'
' *** End of Module Overview ***
Sub Filter_Table_To_Sheets()
Dim selectedCell As Range
Dim selectedTable As ListObject
Dim ws As Worksheet
Dim filterColumn As Range
Dim uniqueValues() As Variant
Dim i As Long
Dim newSheet As Worksheet
Dim copyRange As Range
Dim headerRange As Range
Dim existingSheetNames As Collection
Dim sheetName As Variant
Dim userResponse As VbMsgBoxResult
Dim cleanedSheetName As String
Dim sortOrder As String
' Step 1: Ask the user to select a cell in the column they want to filter by
On Error Resume Next
Set selectedCell = Application.InputBox("Please select a cell in the column you want to filter by:", Type:=8)
On Error GoTo 0
' Check if the user selected a cell
If selectedCell Is Nothing Then
MsgBox "No cell was selected. Exiting.", vbExclamation
Exit Sub
End If
' Step 2: Check if the selected cell is part of a table
On Error Resume Next
Set selectedTable = selectedCell.ListObject
On Error GoTo 0
If selectedTable Is Nothing Then
MsgBox "The selected cell is not part of a table. Please select a valid table cell.", vbExclamation
Exit Sub
End If
' Determine the column to filter by based on the selected cell
Set filterColumn = selectedTable.ListColumns(selectedCell.Column - selectedTable.Range.Column + 1).DataBodyRange
' Step 3: Get all unique values in the selected column
uniqueValues = GetUniqueArray(filterColumn)
' Step 4: Prompt the user to choose the sorting order (1 = A-Z, 2 = Z-A, 3 = Original)
sortOrder = Application.InputBox("Choose sorting order: 1 = A-Z, 2 = Z-A, 3 = Original", Type:=1)
' Step 5: Handle the user's choice and sort accordingly
Select Case sortOrder
Case "1"
Call SortArray(uniqueValues, True)
Case "2"
Call SortArray(uniqueValues, False)
Case "3"
' No sorting, keep original order
Case Else
' Default to A-Z and notify the user
MsgBox "Invalid choice, defaulting to A-Z sorting.", vbInformation
Call SortArray(uniqueValues, True)
End Select
' Step 6: Check for existing sheets with names matching the unique values
Set existingSheetNames = New Collection
For i = LBound(uniqueValues) To UBound(uniqueValues)
cleanedSheetName = CleanSheetName(CStr(uniqueValues(i)))
If SheetExists(cleanedSheetName) Then
existingSheetNames.Add cleanedSheetName
End If
Next i
' Step 7: Ask the user if it's okay to delete the existing sheets
If existingSheetNames.Count > 0 Then
userResponse = MsgBox("There are existing sheets with the same names as the values in the chosen column. " &_
"Would you like to delete these sheets before proceeding?", vbYesNo + vbExclamation, "Delete Sheets")
If userResponse = vbYes Then
For Each sheetName In existingSheetNames
Application.DisplayAlerts = False ' Disable the prompt for deleting the sheet
ActiveWorkbook.Worksheets(sheetName).Delete
Application.DisplayAlerts = True ' Re-enable alerts after deletion
Next sheetName
Else
MsgBox "Process aborted. No sheets were deleted.", vbInformation
Exit Sub
End If
End If
' Step 8: Get the header row of the table (if it exists)
Set headerRange = selectedTable.HeaderRowRange
' Step 9: Create new sheets for each unique value and copy the filtered data
Application.ScreenUpdating = False
For i = LBound(uniqueValues) To UBound(uniqueValues)
cleanedSheetName = CleanSheetName(CStr(uniqueValues(i)))
' Ensure unique sheet names
cleanedSheetName = EnsureUniqueSheetName(cleanedSheetName)
' Apply filter based on the unique value
selectedTable.Range.AutoFilter Field:=filterColumn.Column - selectedTable.Range.Column + 1, Criteria1:=uniqueValues(i)
' Identify the visible range after filtering
On Error Resume Next ' Handle case where no rows are visible
Set copyRange = selectedTable.DataBodyRange.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If Not copyRange Is Nothing Then
' Create a new sheet and copy the filtered data
Set newSheet = ActiveWorkbook.Worksheets.Add(After:=ActiveWorkbook.Worksheets(ActiveWorkbook.Worksheets.Count))
newSheet.Name = cleanedSheetName
' Copy the header row to the new sheet
If Not headerRange Is Nothing Then
headerRange.Copy Destination:=newSheet.Range("A1")
End If
' Copy the filtered data to the new sheet
copyRange.Copy Destination:=newSheet.Range("A2")
' Auto-fit columns in the new sheet
newSheet.Columns.AutoFit
End If
Next i
Application.ScreenUpdating = True
' Clear the filter on the original table
selectedTable.AutoFilter.ShowAllData
MsgBox "Filtered data copied to new sheets for each unique value.", vbInformation
End Sub
Sub SortArray(ByRef arr() As Variant, ascending As Boolean)
' Sorts an array either A-Z or Z-A
Dim i As Long, j As Long
Dim temp As Variant
' Perform a simple bubble sort on the array
For i = LBound(arr) To UBound(arr) - 1
For j = i + 1 To UBound(arr)
If (ascending And arr(i) > arr(j)) Or (Not ascending And arr(i) < arr(j)) Then
' Swap values in the array
temp = arr(i)
arr(i) = arr(j)
arr(j) = temp
End If
Next j
Next i
End Sub
Function GetUniqueArray(rng As Range) As Variant()
' Function to retrieve unique values from a range and store them directly in an array
Dim cell As Range
Dim uniqueValues() As Variant
Dim isUnique As Boolean
Dim i As Long, j As Long
Dim currentValue As Variant
' Initialize the uniqueValues array with an initial size of 1
ReDim uniqueValues(1 To 1)
i = 0 ' This will keep track of the number of unique values
' Loop through each cell in the range
For Each cell In rng
currentValue = cell.value
If currentValue <> "" Then
' Check if the value is already in the uniqueValues array
isUnique = True
For j = 1 To i
If uniqueValues(j) = currentValue Then
isUnique = False
Exit For
End If
Next j
' If the value is unique, add it to the array
If isUnique Then
i = i + 1
ReDim Preserve uniqueValues(1 To i)
uniqueValues(i) = currentValue
End If
End If
Next cell
' Return the array with unique values
GetUniqueArray = uniqueValues
End Function
Function CleanSheetName(sheetName As String) As String
' Truncate the sheet name to 31 characters
sheetName = Left(sheetName, 31)
' Replace invalid characters with underscores
sheetName = Replace(sheetName, "/", "_")
sheetName = Replace(sheetName, "\", "_")
sheetName = Replace(sheetName, "?", "_")
sheetName = Replace(sheetName, "*", "_")
sheetName = Replace(sheetName, ":", "_")
sheetName = Replace(sheetName, "[", "_")
sheetName = Replace(sheetName, "]", "_")
' Remove apostrophes at the beginning or end of the name
If Left(sheetName, 1) = "'" Then sheetName = Mid(sheetName, 2)
If Right(sheetName, 1) = "'" Then sheetName = Left(sheetName, Len(sheetName) - 1)
' Ensure the name is not blank
If sheetName = "" Then sheetName = "Sheet"
' Avoid the reserved word "History"
If UCase(sheetName) = "HISTORY" Then sheetName = "History_Sheet"
CleanSheetName = sheetName
End Function
Function EnsureUniqueSheetName(sheetName As String) As String
Dim originalName As String
Dim counter As Integer
originalName = sheetName
counter = 1
' Keep adding numbers until a unique name is found
While SheetExists(sheetName)
sheetName = originalName &"_" &counter
counter = counter + 1
Wend
EnsureUniqueSheetName = sheetName
End Function
Function GetUniqueValues(rng As Range) As Collection
' Function to retrieve unique values from a range
Dim cell As Range
Dim uniqueValues As New Collection
Dim item As Variant
On Error Resume Next
For Each cell In rng
If cell.value <> "" Then
' Attempt to add the item to the collection
uniqueValues.Add cell.value, CStr(cell.value)
End If
Next cell
On Error GoTo 0
Set GetUniqueValues = uniqueValues
End Function
Function SheetExists(sheetName As String) As Boolean
' Function to check if a sheet with a given name exists
Dim ws As Worksheet
On Error Resume Next
Set ws = Worksheets(sheetName)
SheetExists = Not ws Is Nothing
On Error GoTo 0
End Function
Note: Ensure you include the supporting functions (SortArray, GetUniqueArray, CleanSheetName, EnsureUniqueSheetName, SheetExists) as they are essential for the macro to work. Include them in the same module after the main subroutine.
With the code in place, you're ready to run the macro.
Steps to Run the Macro:
What Happens Next?
To make running the macro even easier, you can add a custom button to the Excel Ribbon.
Steps to Add a Custom Button:
Using the Button:
Now that you see how it’s possible to split an Excel table to many sheets using VBA, why not take your skills to the next level? If you’re ready to unlock the full potential of Excel, check out my online VBA course.
Over 500 students have already transformed their Excel abilities with this course, and it's received excellent reviews on Trustpilot. Whether you’re new to VBA or looking to sharpen your skills, this course is designed to help you automate your Excel tasks with confidence and ease.
Don't miss out on this opportunity to supercharge your Excel productivity. Click here to enroll and start your journey today!
Hi, I'm Victor!
Are you struggling with complex Excel tasks? Feeling overwhelmed by spreadsheets that are hard to use?
Many people believe mastering Excel is about learning shortcuts, functions, and formulas. But this overlooks the importance of building practical, real-world applications. It's not just about knowing the tools. It's about using them effectively.
That's where I come in. You'll get a unique perspective to Excel training from me. I have over 20 years of experience at Deloitte and two global tech companies. And I know what can make a difference in your career.
Let me help you integrate Excel into your professional life. Starting today. Read one of my articles, watch one of my videos. Then apply the new technique to your work. You'll see the difference immediately!
Download FREE Excel Workbook
Step 1: Sign up for free Click Here
Step 2: Log in for access Click Here
Step 3: Download file Excel Table Splitter (VBA).zip
Discover the PROVEN Blueprint for transforming your Excel skills, supercharging your productivity, and standing out in your career! My course helps you to learn Excel VBA and save hours of time even if you have zero prior experience with programming.
Solve tricky Excel problems and take your work to the next level! Get customized solutions for your unique needs. Save time and gain insights with truly expert Excel solutions from only $97 per task.
Get a clear overview of your project progress using the Excel project timeline. Use it to communicate the big picture, track task progress, and stay on top of your project goals. Stay organized with our project timeline!
Our cheat sheets provide quick and easy reference to commonly used Excel VBA concepts and code snippets.
Unlock new levels of productivity and efficiency with our cheat sheets, and write VBA code like a pro in no time.
RECOMMENDED READING
Are you looking to upskill and stay ahead of the curve? Excel is a powerful tool that keeps growing in demand. We round up the best online courses for learning Excel.
Are you looking to up your spreadsheet game? Excel is an invaluable tool that can help you stay organized and save time. From data analysis to budgets, Excel can do it all!
Today, having Excel skills is more critical than ever. Those who know how to use Excel are more likely to find higher-paying jobs. And get promoted faster.