Learn

Macro 60: Create a New Sheet for Each Item in an AutoFilter

Macro 60: Create a New Sheet for Each Item in an AutoFilter

One of the most common tasks an Excel user is confronted with is separating a data set into separate

sheets. For instance, if you have a set of data that has rows for the east, west, south, and north

regions of the U.S., you may be asked to create a new sheet for the east data, a new sheet for the

west data, a new sheet for the south, and one for the north. In these situations, you would normally

have to manually filter each region, and then copy and paste the data into new sheets. This can be

quite a painful exercise if you have to do it one time. If you have to perform this same exercise on an

ongoing basis? Well, let’s just say it can be difficult to come to work.

The good news is that you can use a macro to do the heavy lifting for you.

How it works

The basic premise of this macro is in itself simple. We start with a data set that contains an AutoFilter

(similar to the one shown in Figure 5-6).

Figure 5-6: Start with a data set that has an AutoFilter applied.

We point the macro to the field that is used to separate the data into separate sheets. In this case, we

need to create a separate sheet for each region. As you can see in Figure 5-6, the Region field is the

first field in the AutoFiltered data set.

The macro goes through this field, capturing the unique data items in this field (North, South, East,

West). Then one at a time, it uses each unique data item as the filter criteria on the AutoFilter, effec-

tively filtering the data for that item.

Each time a region is filtered, the macro copies the filtered range and pastes the data into a new

sheet. After the data is pasted, it names the sheet the same name as the filter criteria.

This macro is a little tough to look at first glance, so take the time to walk through each step

in detail.

Sub Macro60()

‘Step 1: Declare your Variables

Dim MySheet As Worksheet

Dim MyRange As Range

Dim UList As Collection

Dim UListValue As Variant

Dim i As Long

‘Step 2: Set the Sheet that contains the AutoFilter

Set MySheet = ActiveSheet

‘Step 3: If the sheet is not auto-filtered, then exit

If MySheet.AutoFilterMode = False Then

Exit Sub

End If

‘Step 4: Specify the Column # that holds the data you want filtered

Set MyRange = Range(MySheet.AutoFilter.Range.Columns(1).Address)

‘Step 5: Create a new Collection Object

Set UList = New Collection

‘Step 6: Fill the Collection Object with Unique Values

On Error Resume Next

For i = 2 To MyRange.Rows.Count

UList.Add MyRange.Cells(i, 1), CStr(MyRange.Cells(i, 1))

Next i

On Error GoTo 0

‘Step 7: Start looping in through the collection Values

For Each UListValue In UList

‘Step 8: Delete any Sheets that may have been previously created

On Error Resume Next

Application.DisplayAlerts = False

Sheets(CStr(UListValue)).Delete

Application.DisplayAlerts = True

On Error GoTo 0

‘Step 9: Filter the AutoFilter to match the current

Value MyRange.AutoFilter Field:=1,

Criteria1:=UListValue

‘Step 10: Copy the AutoFiltered Range to new Sheet

MySheet.AutoFilter.Range.Copy

Worksheets.Add.Paste

ActiveSheet.Name = Left(UListValue, 30)

Cells.EntireColumn.AutoFit

‘Step 11: Loop back to get the next collection Value

Next UListValue

‘Step 12: Go back to main Sheet and removed filters

MySheet.AutoFilter.ShowAllData

MySheet.Select

End Sub

1. Step 1 starts the macro by declaring five variables. MySheet is a worksheet variable that is used

to identify the sheet in which the AutoFiltered data resides. MyRange is a range variable that

holds the range of our main filter field (the Region field in this scenario). UList is a Collection

object that helps us extract the unique items from our main filter field. UListValue holds the

individual unique items as we enumerate through them. Finally, the i variable serves as a simple

counter for our MyRange variable.

2. Step 2 sets the MySheet variable to hold the sheet in which the AutoFilter resides. It’s

important to do this because we need to refer back to this sheet throughout the macro.

Here, we are assuming the macro will be fired from the sheet that holds the AutoFilter, so we

use ActiveSheet.

You can also alter the macro to explicitly use a sheet name instead of ActiveSheet, like

Set MySheet = Sheets(“YourSheetName”). This is safer because you have no risk

of unintentionally firing the macro from the wrong sheet. But it essentially ensures that the

macro only works for the sheet you explicitly specified.

3. Step 3 checks the AutoFilterMode property to see if the sheet even has AutoFilters

applied. If not, it exits the procedure.

4. If the macro reaches Step 4, we have determined that there is indeed an AutoFilter applied in

MySheet.

Now we need to capture the column number that holds the items that will be used to parse

our data set into separate sheets. As you can see, in Figure 5-6, the region column is the first

column in our AutoFilter range. So we set the MyRange field to Columns(1) of the

AutoFilter range. This is important! We eventually use the specified column to create a

unique list of items with which we parse our data. When you implement this macro in your

environment, you need to change the column number used to match the field you need to

parse.

5. Step 5 initializes the UList Collection object. A Collection object is a container that

can hold an array of unique data items.

In fact, a Collection object can only hold unique data. If you try to fill it with non-unique

data, it throws an error. Because of this, it makes for an excellent way to quickly find and

store a list of unique data items.

We use the collection object to hold a unique list of items from our MyRange variable. In this

scenario, because our MyRange variable points to the Region column, the Collection

object eventually holds a unique list of regions (East, North, South, West).

6. Step 6 fills the UList Collection object with the unique data items in MyRange.

To do so, it uses the i variable to loop through the rows of the MyRange column. You’ll notice

that we start i at 2; this is because row 1 contains the header label (Region). We don’t want to

include the header label as one of the unique items in our collection object.

On each loop, the macro tries to add the current cell to the UList collection. The syntax to

add an item to a collection is

CollectionName.Add ItemName, UniqueKeyIdentifier

In this case, we are adding each cell in MyRange as both the item name and unique key

identifier. Because the UList collection throws an error if the data items are not unique, we

wrap the entire section in On Error Resume Next and On Error Goto 0. This

ensures that if duplicate items are added, the UList collection ignores them. At the end of

the loop, we have a unique list of all the data items in MyRange. Again, in this scenario, this

means we have a unique list of regions (East, North, South, West).

7. Step 7 works exclusively with the UList collection. This collection holds the unique list of

items we use as both the filter criteria for our AutoFilter and the Sheet names for our newly

created sheets. The macro starts looping through the list with the UListValue variable.

8. Each time we run this macro, a new sheet is added for each unique item in our target filter

field, with sheet names to match. If we run this macro more than one time, an error may be

thrown because we will be creating a sheet that already exists. To ensure this doesn’t hap-

pen, Step 8 deletes any sheet whose name matches the UListValue data item.

9. Step 9 uses the UListValue to filter the AutoFilter. We are dynamically passing the

UListValue as the Criteria for Field1:

MyRange.AutoFilter Field:=1, Criteria1:=UListValue

The field number here is very important! Because the Region field is the first field (see Figure

5-6), we are specifying Field 1. When you implement this macro in your environment, you

need to change the field number to match the field you need to parse.

10. Each AutoFilter object has a Range property. This Range property returns the rows to

which the AutoFilter applies, meaning it returns only the rows that are shown in the filtered

data set. Step 10 uses the Copy method to capture the newly filtered rows and paste the

rows to a new sheet. The macro then names the sheet to match UListValue.

Note that we are wrapping UListValue in the Left function. Specifically, we are telling

Excel to limit the name of the sheet to the left 31 characters in the UListValue. We do this

because the limit for sheet names is 31 characters. Anything longer than 31 characters

throws an error.

11. Step 11 loops back to get the next value from the UList collection.

12. The macro ends by jumping to the original AutoFiltered data and clearing all filters.

You may be wondering how to create a new workbook for each item in an AutoFilter.

This is a relatively easy change. Simply replace the code in Step 10 with this code.

‘Step 10: Copy the AutoFiltered Range to new Workbook

ActiveSheet.AutoFilter.Range.Copy

Workbooks.Add.Worksheets(1).Paste

Cells.EntireColumn.AutoFit

ActiveWorkbook.SaveAs _

Filename:=”C:\Temp\” & CStr(UListValue) & “.xlsx”

ActiveWorkbook.Close

C:Temp folder. If you like, you can change this to suit your needs.

How to use it

To implement this macro, you can copy and paste it into a standard module:

1. Activate the Visual Basic Editor by pressing ALT+F11 on your keyboard.

2. Right-click the project/workbook name in the Project window.

3. Choose InsertModule.

4. Type or paste the code.

learn
We will be happy to hear your thoughts

Leave a reply

Share knowledge
Learn
Logo
Enable registration in settings - general