VBA anomaly when filtering table from Worksheet_Calculate

Jerry Sullivan

MrExcel MVP
Joined
Mar 18, 2010
Messages
8,787
When the user filters Table1, my objective is to have Table2 on the same sheet filtered so that both tables have the same ID items visible.

Since VBA doesn't have an event that is triggered when a table is filtered, I'm using the Worksheet_Calculate event which is triggered due to the presence a SUBTOTAL formula that counts visible rows in Table1.

The problem is that VBA doesn't seem to be able to AutoFilter Table2 if Worksheet_Calculate is triggered as a result of filtering Table1.

Here's a simplified example to illustrate the problem...


Excel 2016 (Windows) 32 bit
ABCDEF
1Table1
2IDNameMeasure
3#111Name1277Test4
4#222Name2155Formula:5
5#333Name3296
6#444Name4109
7Subtotal:837
8
9Table 2
10IDNameMeasure
11#111Name1637
12#222Name2476
13#333Name3454
14#444Name4127
15Subtotal:1694
Sheet1
Cell Formulas
RangeFormula
F4=F3+1
C7=SUBTOTAL(9,Table1[Measure])
C15=SUBTOTAL(9,Table2[Measure])


Note: My finished code will read the visible items' IDs in Table1 into an array. I've removed that step for this example to demonstrate that isn't causing the anomaly.

Code:
'--worksheet code in Sheet1
Private Sub Worksheet_Calculate()
 Application.EnableEvents = False
 SyncFiltersByID
 Application.EnableEvents = True
End Sub

Code:
'--code in Module1
Sub SyncFiltersByID()
 Dim vVisibleItemList As Variant
 
 '--simplified for this example- will read Table1 in final code
 vVisibleItemList = Array("#111", "#333", "#444")

 '--sync Table2 to list of IDs in Table1
 With Sheet1.ListObjects("Table2").Range
   .AutoFilter Field:=1, _
      Criteria1:=Array(vVisibleItemList), Operator:=xlFilterValues
 End With

End Sub

If I enter any value in cell B21, Worksheet_Calculate is triggered and the code successfully filters Table2 to show ID's 111,222, and 444.

If I filter Table1, Worksheet_Calculate is triggered and the code unexpectedly applies the filters intended for Table2 to the ID field of Table1!

If I Cut and Paste Table2 into Sheet2 (and modify the code to reference it on Sheet2), when Table1 is filtered, the code successfully filters Table2 to show ID's 111,222, and 444.

The code will also work if I eliminate the Worksheet_Calculate and require the user to push a button to call SyncFiltersByID.

The best workaround I've found is to add a Slicer to the ID field of Table2, and sync the tables through the Slicer. I'll go with that unless someone can suggest a better solution. Note that the Tables do not use the same data source, so they can't be sync'd by slicers alone.

TIA
 
Last edited:

Excel Facts

Move date out one month or year
Use =EDATE(A2,1) for one month later. Use EDATE(A2,12) for one year later.
Use something to give you control over worksheet_calculate

Option1 - Simplest way is to ask the user
Code:
Private Sub Worksheet_Calculate()
    Application.EnableEvents = False
       If MsgBox("Sync?", vbYesNo) = 5 Then SyncFiltersByID
    Application.EnableEvents = True
End Sub


Option2 - Use a boolean variable
I have not refined this but have tested in principle and it does work

1. Add boolean variable at top of module1
Code:
Public [COLOR=#ff0000]Trigger[/COLOR] As Boolean
Sub SyncFiltersByID()
'your macro
End Sub

2. Use that to control worksheet_calculate
In sheet1's module
Code:
Private Sub Worksheet_Calculate()
    Application.EnableEvents = False
       If Not [COLOR=#ff0000]Trigger[/COLOR] = False Then SyncFiltersByID
    Application.EnableEvents = True
End Sub

3. Use something to flip the value between TRUE and Fale
- this is the tricky bit :eeek:

My first thought was something along these lines ....
Code:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Trigger = True
    If Not Intersect(Target, Me.ListObjects("Table2").Range) Is Nothing Then Trigger = False
    If Not Intersect(Target, Me.ListObjects("Table1").Range) Is Nothing Then Trigger = False
End Sub
But this only works if a cell in either table is selected BEFORE the table is filtered
- filtering does not trigger selection change

Perhaps you can think of a more appropriate trigger
 
Last edited:
Upvote 0
A development on using the Boolean variabble Tigger

To get around filter not triggering anything
- use an active-x label and use its MouseMove event
- I have tested the method and it works

How?
- Add an active-x label and make it the same width as Table1 and the same height as header row
- Place it over the header ow
- (Later you can make it transparent and remove text etc - leave visible whilst testing!)
- Use MouseMove event to move the Label away(allowing tablle to be manually filtered) and sets Trigger to FALSE
- Filtering the table triggers worksheet_calculate but Sync macro does not run
- worksheet_calculate moves the label back over the table and sets Trigger to TRUE

You may want to replicate for Table2

Code
In sheet1's module
Code:
Private Sub Label1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
[I][COLOR=#008080]'move label away and set boolean variable[/COLOR][/I]
    Label1.Left = Me.ListObjects("Table1").Range(1).Left + 500
    Trigger = False
End Sub

Private Sub Worksheet_Calculate()
[I][COLOR=#008080]'use boolean to determine if other macro runs[/COLOR][/I]
    Application.EnableEvents = False
       If Trigger Then SyncFiltersByID
    Application.EnableEvents = True
[I][COLOR=#008080]'place label over headings and reset boolean[/COLOR][/I]
    Label1.Left = Me.ListObjects("Table1").Range(1).Left
    Label1.Top = Me.ListObjects("Table1").Range(1).Top
    Trigger = True
End Sub

In module1
Code:
Public Trigger As Boolean
Sub SyncFiltersByID()
 your macro
End Sub
 
Last edited:
Upvote 0
Hi Yongle,

Thank you for all the thought you put into this. :)

Were you able to replicate the problem that I described? Using my original code, if I manually filter Table1 then this part of the code applies filters to Table1 instead of Table2...


Code:
 '--sync Table2 to list of IDs in Table1
 With Sheet1.ListObjects("Table2").Range
   .AutoFilter Field:=1, _
      Criteria1:=Array(vVisibleItemList), Operator:=xlFilterValues
 End With


The suggestions that you offered are creative, but after the added confirmation/trigger toggle steps, they still run the same line of autofilter code where the problem of filtering the wrong table occurs.

It's possible that this is a problem specific to my version/build of Excel. I hadn't considered that, so I'd appreciate very much if you can check to see if you get this same anomaly I described when running the code in my OP.
 
Upvote 0
I must have misunderstood :confused:

Exactly what is the problem you are trying to fix?
 
Last edited:
Upvote 0
My OP wasn't as clear as it could have been.

The code is supposed to filter Table2 when Table1 is filtered. It doesn't. It applies additional filters to Table1.
 
Upvote 0
I get exactly the same as you, using 2013.
Also if I switch the code to filter table1 & manually filter table2, then table2 filters get changed not table1
 
Upvote 0
I get exactly the same as you, using 2013.
Also if I switch the code to filter table1 & manually filter table2, then table2 filters get changed not table1

Hi Fluff, Thank you for confirming that you get the same behavior with xl2013.
 
Upvote 0
Just been playing around with it & using this
Code:
   Set Tbl = Sheet22.ListObjects("Table2")
   With Tbl.Range
      Debug.Print .Address
      .AutoFilter 1, Array(vVisibleItemList), xlFilterValues
   End With
It gives me the correct range for Table2, but still filters Table1 :confused:
 
Upvote 0
Just been playing around with it & using this
Code:
   Set Tbl = Sheet22.ListObjects("Table2")
   With Tbl.Range
      Debug.Print .Address
      .AutoFilter 1, Array(vVisibleItemList), xlFilterValues
   End With
It gives me the correct range for Table2, but still filters Table1 :confused:

Yes, I had tested that too. :confused:

I also tried adding a statement to Select a cell in Table2 prior to the filter statement, thinking that maybe Excel couldn't filter the table if another table was selected. That didn't work either and Table1 was still filtered.
 
Upvote 0

Forum statistics

Threads
1,224,823
Messages
6,181,177
Members
453,021
Latest member
Justyna P

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top