I had been searching for a way to print an Excel sheet's Autofilter settings to the Immediate window and I came up with this. This allows a developer to quickly convert an end user's filter settings to VBA code. I would appreciate feedback from anyone who cares to test the code.
Option Explicit
Public ws As Worksheet
Public wsn As String
Public MyCrit As Variant
Public FirstCritRow As Long
Public MiddleCritRow As Long
Public LastCritRow As Long
Public c As Long
Public MyRank As Double
Sub PrintFilters()
'Peter Domanico, November 2017 - January 2018
'Prints Excel Autofilter settings as VBA code to Immediate Window
'This file contains 3 scripts. use this code in own module.
'Assign the primary script (PrintFilters) to Excel button or shortcut key
'Primary script (PrintFilters) calls subscripts TopTenSub and BottomTenSub
'performance
Application.ScreenUpdating = False
Application.DisplayAlerts = False
'sheet dims
Set ws = ActiveSheet '<~leave out "ThisWorkbook": causes errors with personal macro workbook
wsn = ws.Name
'rows and columns
Dim LastRow As Long
Dim AllRows As Long
Dim DataRows As Long
Dim LastCol As Long
LastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row
AllRows = ws.UsedRange.Rows.Count
DataRows = AllRows - 1
LastCol = ws.UsedRange.Columns.Count
'for use in xlTop10Items / xlBottom10Items
Dim VisRows As Long
VisRows = Application.WorksheetFunction.Subtotal(3, Range("A2:A" & LastRow))
'for use in xlFilterValues
Dim CritString As String
Dim AllCrit As Variant
Dim CritVar As Variant
'for use in xlFilterCellColor
Dim CondishCount As Long
Dim ClrString As String
'misc dims
Dim FltrCt As Long
'begin main procedure
FltrCt = 0 '<~ keeps count of active filters
For c = 1 To LastCol '<~loop through each column
On Error Resume Next '<~error handling
With ws.AutoFilter.Filters(c) '<~uses filtered range only
Select Case .Operator '<~detects operator type by value
Case Is = 0 '<~Equals
FltrCt = FltrCt + 1
If FltrCt = 1 Then Debug.Print "With " & "Sheets(" & Chr(34) & wsn & Chr(34) & Chr(41) & ".UsedRange"
Debug.Print vbTab & ".Autofilter Field:=" & c & Chr(44) & "Criteria1:=" & Chr(34) & .Criteria1 & Chr(34)
Case Is = 1 '<~xlAnd
FltrCt = FltrCt + 1
If FltrCt = 1 Then Debug.Print "With " & "Sheets(" & Chr(34) & wsn & Chr(34) & Chr(41) & ".UsedRange"
Debug.Print vbTab & ".Autofilter Field:=" & c & Chr(44) & "Criteria1:=" & Chr(34) & .Criteria1 & Chr(34) & Chr(44) & "Operator:=xlAnd" & Chr(44) & ("Criteria2:=" & Chr(34) & .Criteria2 & Chr(34))
Case Is = 2 '<~xlOr
FltrCt = FltrCt + 1
If FltrCt = 1 Then Debug.Print "With " & "Sheets(" & Chr(34) & wsn & Chr(34) & Chr(41) & ".UsedRange"
Debug.Print vbTab & ".Autofilter Field:=" & c & Chr(44) & "Criteria1:=" & Chr(34) & .Criteria1 & Chr(34) & Chr(44) & "Operator:=xlOr" & Chr(44) & ("Criteria2:=" & Chr(34) & .Criteria2 & Chr(34))
Case Is = 3 'xlTop10Items
FltrCt = FltrCt + 1
If FltrCt = 1 Then Debug.Print "With " & "Sheets(" & Chr(34) & wsn & Chr(34) & Chr(41) & ".UsedRange"
Debug.Print vbTab & ".Autofilter Field:=" & c & Chr(44) & "Criteria1:=" & VisRows & Chr(44) & "Operator:=xlTop10Items"
Case Is = 4 'xlBottom10Items
FltrCt = FltrCt + 1
If FltrCt = 1 Then Debug.Print "With " & "Sheets(" & Chr(34) & wsn & Chr(34) & Chr(41) & ".UsedRange"
Debug.Print vbTab & ".Autofilter Field:=" & c & Chr(44) & "Criteria1:=" & VisRows & Chr(44) & "Operator:=xlBottom10Items"
Case Is = 5 'xlTop10Percent
FltrCt = FltrCt + 1
If FltrCt = 1 Then Debug.Print "With " & "Sheets(" & Chr(34) & wsn & Chr(34) & Chr(41) & ".UsedRange"
MyCrit = Mid(.Criteria1, 3)
Call TopTenSub
Debug.Print vbTab & ".Autofilter Field:=" & c & Chr(44) & "Criteria1:=" & MyRank & Chr(44) & "Operator:=xlTop10Percent"
Case Is = 6 'xlBottom10Percent
FltrCt = FltrCt + 1
If FltrCt = 1 Then Debug.Print "With " & "Sheets(" & Chr(34) & wsn & Chr(34) & Chr(41) & ".UsedRange"
MyCrit = Mid(.Criteria1, 3)
Call BottomTenSub
Debug.Print vbTab & ".Autofilter Field:=" & c & Chr(44) & "Criteria1:=" & MyRank & Chr(44) & "Operator:=xlBottom10Percent"
Case Is = 7 '<~xlFilterValues
FltrCt = FltrCt + 1
If FltrCt = 1 Then Debug.Print "With " & "Sheets(" & Chr(34) & wsn & Chr(34) & Chr(41) & ".UsedRange"
For Each CritVar In .Criteria1
AllCrit = AllCrit & Chr(44) & Chr(34) & Mid(CritVar, 2) & Chr(34)
CritString = AllCrit
CritString = Replace(CritString, Chr(44), "", 1, 1)
Next
Debug.Print vbTab & ".Autofilter Field:=" & c & Chr(44) & "Criteria1:=Array(" & CritString & ")," & "Operator:=xlFilterValues"
AllCrit = Nothing
Case Is = 8 '<~xlFilterCellColor
FltrCt = FltrCt + 1
If FltrCt = 1 Then Debug.Print "With " & "Sheets(" & Chr(34) & wsn & Chr(34) & Chr(41) & ".UsedRange"
ClrString = ws.Cells(LastRow, c).Interior.Color '<~ filters by manually applied cell fill color
Debug.Print vbTab & ".Autofilter Field:=" & c & Chr(44) & "Criteria1:=" & ClrString & Chr(44) & "Operator:=xlFilterCellColor"
CondishCount = ws.Cells(LastRow, c).FormatConditions.Count
If CondishCount > 0 Then Debug.Print Chr(39) & CondishCount & Chr(32) & "conditional formats detected in column" & Chr(32) & c
Case Is = 9 '<~xlFilterFontColor
FltrCt = FltrCt + 1
If FltrCt = 1 Then Debug.Print "With " & "Sheets(" & Chr(34) & wsn & Chr(34) & Chr(41) & ".UsedRange"
ClrString = ws.Cells(LastRow, c).Font.Color '<~ filters by manually applied cell fill color
Debug.Print vbTab & ".Autofilter Field:=" & c & Chr(44) & "Criteria1:=" & ClrString & Chr(44) & "Operator:=xlFilterFontColor"
Case Is = 11
FltrCt = FltrCt + 1
If FltrCt = 1 Then Debug.Print "With " & "Sheets(" & Chr(34) & wsn & Chr(34) & Chr(41) & ".UsedRange"
MyCrit = .Criteria1
If MyCrit = 33 Then MyCrit = "xlFilterAboveAverage"
If MyCrit = 34 Then MyCrit = "xlFilterBelowAverage"
Debug.Print vbTab & ".Autofilter Field:=" & c & Chr(44) & "Criteria1:=" & MyCrit & Chr(44) & "Operator:=xlFilterDynamic"
End Select
End With
Next c
'close With statement
If FltrCt > 0 Then Debug.Print "End With"
'performance and cleanup
ws.Select
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
Sub TopTenSub()
'set sheets
Dim wb As Workbook
Set wb = ActiveWorkbook
Dim TempSheet As Worksheet
Set ws = wb.Sheets(wsn)
Dim LastRow As Long
'duplicate source sheet
On Error Resume Next
wb.Sheets("PeteDTempData").Delete
wb.Sheets(wsn).Copy After:=wb.Sheets(wsn)
wb.ActiveSheet.Name = "PeteDTempData"
Set TempSheet = wb.Sheets("PeteDTempData")
'sort
TempSheet.UsedRange.AutoFilter
LastRow = TempSheet.Cells(Rows.Count, 1).End(xlUp).Row
TempSheet.Sort.SortFields.Add Key:=Range("A2:A" & LastRow) _
, SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
With TempSheet.Sort
.SetRange Range("A1:A" & LastRow)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
'number range
Dim j As Long
Dim i As Long
Dim CountCol As Long
CountCol = TempSheet.UsedRange.Columns.Count + 1
j = 1
For i = 2 To LastRow
TempSheet.Cells(i, CountCol) = j
j = j + 1
Next i
'find first MyCrit
FirstCritRow = TempSheet.Columns(c).Find(What:=MyCrit, LookAt:=xlWhole).Row
'find last MyCrit
LastCritRow = TempSheet.Columns(c).Find(What:=MyCrit, LookAt:=xlWhole, SearchDirection:=xlPrevious).Row
'find middle MyCrit
MiddleCritRow = WorksheetFunction.Average(FirstCritRow, LastCritRow)
MiddleCritRow = Round(MiddleCritRow, 0)
'calculate percent
With TempSheet
MyRank = .Cells(MiddleCritRow, CountCol) / (LastRow - 1)
MyRank = MyRank * 100
MyRank = Round(MyRank, 0)
End With
'delete temp sheet
TempSheet.Delete
ws.Select
End Sub
Sub BottomTenSub()
'set sheets
Dim wb As Workbook
Set wb = ActiveWorkbook
Dim TempSheet As Worksheet
Set ws = wb.Sheets(wsn)
Dim LastRow As Long
'duplicate source sheet
On Error Resume Next
wb.Sheets("PeteDTempData").Delete
wb.Sheets(wsn).Copy After:=wb.Sheets(wsn)
wb.ActiveSheet.Name = "PeteDTempData"
Set TempSheet = wb.Sheets("PeteDTempData")
'sort
TempSheet.UsedRange.AutoFilter
LastRow = TempSheet.Cells(Rows.Count, 1).End(xlUp).Row
TempSheet.Sort.SortFields.Add Key:=Range("A2:A" & LastRow) _
, SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
With TempSheet.Sort
.SetRange Range("A1:A" & LastRow)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
'number range
Dim j As Long
Dim i As Long
Dim CountCol As Long
CountCol = TempSheet.UsedRange.Columns.Count + 1
j = 1
For i = 2 To LastRow
TempSheet.Cells(i, CountCol) = j
j = j + 1
Next i
'find first MyCrit
FirstCritRow = TempSheet.Columns(c).Find(What:=MyCrit, LookAt:=xlWhole).Row
'find last MyCrit
LastCritRow = TempSheet.Columns(c).Find(What:=MyCrit, LookAt:=xlWhole, SearchDirection:=xlPrevious).Row
'find middle MyCrit
MiddleCritRow = WorksheetFunction.Average(FirstCritRow, LastCritRow)
MiddleCritRow = Round(MiddleCritRow, 0)
'calculate percent
With TempSheet
MyRank = .Cells(MiddleCritRow, CountCol) / (LastRow - 1)
MyRank = 1 - MyRank
MyRank = MyRank * 100
MyRank = Round(MyRank, 0)
End With
'delete temp sheet
TempSheet.Delete
ws.Select
End Sub