3

I need to Filter/Show data on the visible cells only on my dataset.
The using of AutoFilter is very fast, But it has a downside that it show any hidden rows on the respective criteria. .
Although I am using arrays and Application optimization on the below code , but it gets very slow if the range starts to be bigger.
With just 100 rows, it finished on 1.12 sec and with 1000 rows it finished on 117.47 sec !
In advance, I am grateful for all your support.

Option Explicit
Option Compare Text
 
Sub Filter_on_Visible_Cells_Only()
 
   Dim t: t = Timer
 
   Dim ws1 As Worksheet, ws2 As Worksheet
   Dim rng1 As Range, rng2 As Range
   Dim arr1() As Variant, arr2() As Variant
   Dim i As Long, HdRng As Range
   Dim j As Long, k As Long
 
   SpeedOn
 
   Set ws1 = ThisWorkbook.ActiveSheet
   Set ws2 = ThisWorkbook.Sheets("Platforms")
 
    Set rng1 = ws1.Range("D3:D" & ws1.Cells(Rows.Count, "D").End(xlUp).Row)     'ActiveSheet
    Set rng2 = ws2.Range("B3:B" & ws2.Cells(Rows.Count, "A").End(xlUp).Row)     'Platforms
 
    arr1 = rng1.Value2
    arr2 = rng2.Value2
 
   For i = 1 To UBound(arr1)
 
    If ws1.Rows(i + 2).Hidden = False Then                       '(i + 2) because Data starts at Row_3
 
    For j = LBound(arr1) To UBound(arr1)
    For k = LBound(arr2) To UBound(arr2)
 
      If arr1(j, 1) <> arr2(k, 1) Then
 
         addToRange HdRng, ws1.Range("A" & i + 2)                'Make a union range of the rows NOT matching criteria...
 
      End If
 
      Next k
     Next j
    End If
  Next i
 
      If Not HdRng Is Nothing Then HdRng.EntireRow.Hidden = True      'Hide not matching criteria rows.
 
    Speedoff
 
   Debug.Print "Filter_on_Visible_Cells, in " & Round(Timer - t, 2) & " sec"
 
End Sub
 
Private Sub addToRange(rngU As Range, rng As Range)
    If rngU Is Nothing Then
        Set rngU = rng
    Else
        Set rngU = Union(rngU, rng)
    End If
End Sub
 
Sub SpeedOn()
    With Application
       .Calculation = xlCalculationManual
       .ScreenUpdating = False
       .EnableEvents = False
       .DisplayAlerts = False
    End With
End Sub
Sub Speedoff()
    With Application
      .Calculation = xlCalculationAutomatic
      .ScreenUpdating = True
      .EnableEvents = True
      .DisplayAlerts = True
    End With
End Sub
6
  • Quick question: Your goal is, to use the autofilter on visible rows only? So, if you have a criteria on autofilter (vba) you want to filter that and the hidden rows should be hidden after using it? Because I don't see any autofilter use in your code. But, what if you use a simple loop through all the rows and save the hidden ones in a range object and hide them after usage of autofilter. The problem here is, that doing something on a not linked range object is terribly slow in excel/vba
    – Pearli
    Commented Oct 30, 2022 at 15:08
  • @Pearli ,autofilter code not found, because I already set it by excel interface.and yes, my goal is to use the autofilter on visible rows only
    – Waleed
    Commented Oct 30, 2022 at 15:19
  • There's something wrong with your logic. Unless all the visible data in both columns is equal, If arr1(j, 1) <> arr2(k, 1) Then will capture all rows (if the data_is_ all the same it will capture no rows, so it's all or nothing). Please edit to explain what your intended logic is for hiding rows. Commented Oct 30, 2022 at 17:43
  • That said, the reason it's slow for larger ranges is you have 3 nested for loops. For 1000 visible rows that's 1000,000,000 iterations. There will be far more optimal ways to do this, (depending on your answer to my last comment ( Commented Oct 30, 2022 at 17:46
  • @chris neilsen ,If you mean visible data in both columns (Rng1 & Rng2), Then it's not the same on count , I am using Rng2 as a criteria range. The logic of my code is to hide rows which are not matched my Range_Criteria (Note: There are already hidden rows on my date and I do not want it to be shown If I used directly Autofilter.
    – Waleed
    Commented Oct 30, 2022 at 18:38

2 Answers 2

1

Ok, if you want to use this, you have to use the autofilter with vba as well. There is no event which fires on usage of the autofilter through the excel UI (except you work with some help of formulas in hidden worksheets, like described here Link).

But if you want to use it in vba, you could simply use this, this should help and if i try it on that 167 cells, it works pretty fast:

Sub m()
    Dim rngTemp As Range
    For Each c In Range("a1:a167")
        If c.EntireRow.Hidden Then
            If rngTemp Is Nothing Then
                Set rngTemp = c
            Else
                Set rngTemp = Union(rngTemp, c)
            End If
        End If
    Next c
    
    Range("A1:A167").AutoFilter Field:=1, Criteria1:="10"   ' your autofilter values
    
    rngTemp.EntireRow.Hidden = False
    
End Sub
1

Compare Values Using Application.Match

Sub Filter_on_Visible_Cells_Only()
 
    Dim t: t = Timer
    
    Dim sws As Worksheet, srg As Range
    Dim dws As Worksheet, drg As Range, dCell As Range, hdrg As Range
    
    SpeedOn
    
    Set sws = ThisWorkbook.Sheets("Platforms")
    Set srg = sws.Range("B3", sws.Cells(sws.Rows.Count, "B").End(xlUp))
    
    Set dws = ThisWorkbook.ActiveSheet
    Set drg = dws.Range("D3", dws.Cells(dws.Rows.Count, "D").End(xlUp))
    Set drg = drg.SpecialCells(xlCellTypeVisible)
    
    For Each dCell In drg.Cells
        If IsError(Application.Match(drg.Value, srg, 0)) Then
            addToRange hdrg, dCell
        End If
    Next dCell
    
    If Not hdrg Is Nothing Then hdrg.EntireRow.Hidden = True
    
    Speedoff
    
    Debug.Print "Filter_on_Visible_Cells, in " & Round(Timer - t, 2) & " sec"
 
End Sub
3
  • I tried on 4k visible rows and the code finished in 12 sec, But all the visible rows drg persisted as it is and no hidden rows after using Match
    – Waleed
    Commented Oct 31, 2022 at 6:29
  • Sorry, I never noticed that you used A with B3. I fixed it by replacing A with B. Also, not related, the first method's signature should be Private Sub addToRange(ByRef rngU As Range, ByVal rng As Range) making it clear that rngU is being built.
    – VBasic2008
    Commented Oct 31, 2022 at 10:35
  • I was already replaced A with B before trying the code, anyhow your code has no effect ( no offense at all). After debugging, I found that hdrg = Nothing
    – Waleed
    Commented Oct 31, 2022 at 11:35

Not the answer you're looking for? Browse other questions tagged or ask your own question.