Option Explicit
Sub FilterData()
'DMT32 Nov2018
Dim ws1Master As Worksheet, wsFilter As Worksheet
Dim Datarng As Range, objRange As Range
Dim FilterValue As Range, FilterCriteriaRange As Range, FilterTargetRange As Range
Dim Rowcount As Long, colcount As Long, SelectionCount As Long
Dim FilterCol As Long, FilterRow As Long, FirstCol As Long, LastCol As Long
Dim SheetName As String, Prompt As String
Dim arr As Variant, Item As Variant
'master sheet
Set ws1Master = ActiveSheet
Prompt = "Select Field Name(s) To Filter" & Chr(10) & _
"Hold Ctrl Key To Select More Than One Field Name"
'select the Column(s) filtering
top:
On Error Resume Next
Set objRange = Application.InputBox(Prompt, "Select Field Name(s)", , , , , , 8)
On Error GoTo 0
If objRange Is Nothing Then Exit Sub
FilterCol = objRange.Column
FilterRow = objRange.Row
With Application
.ScreenUpdating = False: .DisplayAlerts = False
End With
On Error GoTo progend
'add filter sheet & intialize variables
Set wsFilter = GetFilterSheet(objRange, SelectionCount, FilterCriteriaRange, FilterTargetRange)
With ws1Master
.Select
'add password if needed
.Unprotect Password:=""
Rowcount = .Cells(.Rows.Count, FilterCol).End(xlUp).Row
FirstCol = .Cells(FilterRow, FilterCol).End(xlToLeft).Column
LastCol = .Cells(FilterRow, FilterCol).End(xlToRight).Column
'check selection within data range
If objRange.Areas(SelectionCount).Column > LastCol Then
'raise custom error
Err.Raise 65000, "", "Filter Column Selection Is Outside Data Range.", "", 0
End If
'master sheet data range
'Set Datarng = .Range(.Cells(FilterRow, 1), .Cells(rowcount, colcount))
Set Datarng = .Cells(FilterRow, FirstCol).Resize(Rowcount, LastCol)
'extract Unique values from selected Filter Column(s) to filter sheet
Datarng.AdvancedFilter Action:=xlFilterCopy, copytorange:=FilterTargetRange, unique:=True
'count no records in filter sheet
Rowcount = wsFilter.Cells(wsFilter.Rows.Count, "A").End(xlUp).Row
'step thru each record
For Each FilterValue In wsFilter.Range("A2:A" & Rowcount)
'ignore blank cell in range
If Len(FilterValue.Value) > 0 Then
'get sheet name
arr = FilterValue.Resize(, SelectionCount).Value
'add the SheetName to criteria range
wsFilter.Cells(2, SelectionCount + 2).Resize(, SelectionCount).Value = arr
If IsArray(arr) Then
'two or more filter columns selected
For Each Item In arr
'build string name
SheetName = SheetName & Item & " "
Next
'trim name
SheetName = Trim(Left(Left(SheetName, Len(SheetName) - 1), 31))
Else
'single column
SheetName = Trim(Left(arr, 31))
End If
'if sheet exists
If Evaluate("ISREF('" & SheetName & "'!A1)") Then
'clear old data
Sheets(SheetName).Cells.Clear
Else
'add new sheet & name it
'(note: no check for illegal tab name characters)
Sheets.Add(after:=Worksheets(Worksheets.Count)).Name = SheetName
End If
'copy filtered data to named sheet
Datarng.AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=FilterCriteriaRange, _
copytorange:=Sheets(SheetName).Range("A1"), unique:=False
End If
'clear variable
SheetName = ""
Next
.Select
End With
progend:
'delete filter sheet
wsFilter.Delete
're-set properties
With Application
.ScreenUpdating = True: .DisplayAlerts = True: .StatusBar = False
End With
'report errors
If Err <> 0 Then MsgBox (Error(Err)), 16, "Error"
End Sub