Guest User

MS Excel autofilter helpers

a guest
Nov 3rd, 2016
125
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2. 'MS Excel autofilter helpers
  3. 'Bruce Leyden Aug 2015
  4. 'pastebin_vba@f.blackworx.co.uk
  5.  
  6. 'NB: This code will not compile for versions of XL prior to 2007.
  7. '(Not tested with Mac versions)
  8.  
  9. 'Suggested keyboard shortcuts:
  10. 'Ctrl+Shift+J - FilterBySelection
  11. 'Ctrl+Shift+K - ClearFiltersOnly
  12.  
  13. Sub ClearFiltersOnly()
  14. 'Alternative to built-in "clear all filters" command for XL2007 onwards.
  15. 'Removes autofilter criteria from current worksheet/table without removing sort criteria.
  16.  
  17. 'If worksheet contains multiple table objects, or at least one table plus a
  18. 'filtered basic range, intended target is located by testing current selection.
  19.  
  20. 'Takes no action and fails silently on any error condition.
  21.  
  22. 'Bruce Leyden Aug 2015
  23.  
  24. Dim xlcUserCalcMode As XlCalculation
  25. Dim shtTgt As Worksheet
  26. Dim rTest As Range
  27.  
  28.     On Error GoTo ClearFiltersOnly_Exit
  29.    
  30.     xlcUserCalcMode = Application.Calculation
  31.    
  32.     Set shtTgt = ActiveSheet
  33.    
  34.     If TypeName(Selection) = "Range" Then Set rTest = Selection.Cells(1) Else Set rTest = Nothing
  35.    
  36.     With shtTgt
  37.    
  38.         If .Type <> xlWorksheet Then Exit Sub
  39.        
  40.         If .ProtectContents And Not .Protection.AllowFiltering Then Exit Sub
  41.  
  42.         If .AutoFilterMode Then
  43.        
  44.             If .ListObjects.Count = 0 Then
  45.            
  46.                 Call ClearBasicFilter(shtTgt)
  47.                
  48.             Else
  49.            
  50.                 If Not ClearTableFilter(shtTgt, rTest) Then Call ClearBasicFilter(shtTgt)
  51.                
  52.             End If
  53.    
  54.         ElseIf .ListObjects.Count > 0 Then
  55.    
  56.             Call ClearTableFilter(shtTgt, rTest)
  57.        
  58.         End If
  59.        
  60.     End With
  61.  
  62. ClearFiltersOnly_Exit:
  63.     Err.Clear
  64.     Application.ScreenUpdating = True
  65.     Application.Calculation = xlcUserCalcMode
  66. End Sub
  67.  
  68. Private Sub ClearBasicFilter(shtTgt As Worksheet)
  69. Dim rFilt As Range
  70. Dim Index As Long
  71.  
  72.     On Error Resume Next
  73.    
  74.     Set rFilt = shtTgt.AutoFilter.Range
  75.  
  76.     Application.ScreenUpdating = False 'Prevent screen flicker
  77.    Application.Calculation = xlCalculationManual 'Prevent slowdown with lots of filtered data/formulae
  78.            
  79.     For Index = 1 To rFilt.Columns.Count
  80.         If shtTgt.AutoFilter.Filters(Index).On Then rFilt.AutoFilter Field:=Index
  81.         If Err.number <> 0 Then Err.Clear 'Shouldn't happen, but just in case
  82.    Next Index
  83.  
  84. End Sub
  85.  
  86. Private Function ClearTableFilter(shtTgt As Worksheet, Optional rTest As Range = Nothing) As Boolean
  87. Dim Index As Long
  88.  
  89.     ClearTableFilter = False
  90.    
  91.     Index = 1
  92.    
  93.     With shtTgt
  94.    
  95.         If Not rTest Is Nothing Then
  96.    
  97.             On Error GoTo NoMatchFound
  98.    
  99.             Do While Intersect(.ListObjects(Index).Range, rTest) Is Nothing
  100.                 Index = Index + 1
  101.             Loop
  102.            
  103.             On Error GoTo 0
  104.            
  105.         End If
  106.        
  107.         If .ListObjects(Index).ShowAutoFilter Then
  108.             Application.Calculation = xlCalculationManual 'Prevent slowdown with lots of filtered data/formulae
  109.            .ListObjects(Index).AutoFilter.ShowAllData
  110.         End If
  111.        
  112.     End With
  113.    
  114.     ClearTableFilter = True
  115.    
  116. NoMatchFound:
  117. End Function
  118.  
  119. Sub FilterBySelection()
  120. 'Filters current column by selection (same as right-click > filter > filter by selected cell's value)
  121. 'If autofilter not active on current region then it will be activated as a result of running this
  122. 'Bruce Leyden Aug 2015
  123.  
  124. Dim shtTgt As Worksheet
  125. Dim rTgt As Range
  126. Dim rTest As Range
  127. Dim Index As Long
  128.  
  129.     On Error GoTo FilterBySelection_Err
  130.    
  131.     Set shtTgt = ActiveSheet
  132.    
  133.     If TypeName(Selection) = "Range" Then Set rTest = Selection.Cells(1) Else Exit Sub
  134.    
  135.     Set rTgt = CurrentArea(shtTgt, rTest)
  136.      
  137.     If rTgt Is Nothing Then
  138.         Set rTgt = rTest.CurrentRegion
  139.         If rTgt.Rows.Count < 2 Then Exit Sub
  140.     End If
  141.    
  142.     With rTgt
  143.         Index = rTest.Column - .Column + 1
  144.         .AutoFilter Field:=Index, Criteria1:=rTest.Value
  145.     End With
  146.  
  147. FilterBySelection_Err:
  148. End Sub
  149.  
  150. Private Function CurrentArea(shtTgt As Worksheet, Optional rTest As Range = Nothing) As Range
  151. 'Returns the range or table range, within shtTgt, which rTest falls under
  152.  
  153. 'If rTest is omitted, then CurrentArea returns autofiltered range or table,
  154. 'ONLY if there is a single instance of either one or the other within shtTgt.
  155.  
  156. 'Fails silently (CurrentArea=Nothing) on error.
  157.  
  158. 'Bruce Leyden Aug 2015
  159.  
  160. Dim Index As Long
  161.  
  162.     Set CurrentArea = Nothing
  163.    
  164.     On Error GoTo CurrentArea_Err
  165.    
  166.     With shtTgt
  167.    
  168.         If rTest Is Nothing Then
  169.        
  170.             If .ListObjects.Count = 1 Xor .AutoFilterMode Then
  171.            
  172.                 If .AutoFilterMode Then
  173.                     Set CurrentArea = .AutoFilter.Range
  174.                 Else
  175.                     Set CurrentArea = .ListObjects(1).Range
  176.                 End If
  177.                
  178.             End If
  179.            
  180.         Else
  181.        
  182.             If .AutoFilterMode Then
  183.            
  184.                 If Not Intersect(rTest, .AutoFilter.Range) Is Nothing Then
  185.                     Set CurrentArea = .AutoFilter.Range
  186.                     Exit Function
  187.                 End If
  188.                
  189.             End If
  190.            
  191.             If .ListObjects.Count > 0 Then
  192.            
  193.                 For Index = 1 To .ListObjects.Count
  194.                     If Not Intersect(rTest, .ListObjects(Index).Range) Is Nothing Then
  195.                         Set CurrentArea = .ListObjects(Index).Range
  196.                         Exit Function
  197.                     End If
  198.                 Next Index
  199.                
  200.             End If
  201.            
  202.         End If
  203.        
  204.     End With
  205.        
  206. CurrentArea_Err:
  207. End Function
Add Comment
Please, Sign In to add comment