QueryTable class events not working for QueryTables within ListObjects

MoshiM

Active Member
Joined
Jan 31, 2018
Messages
439
Office Version
  1. 2016
Platform
  1. Windows
I found the following class file and have edited it to run certain procedures after a background refresh of a QueryTable has completed.

The class events work properly if the QueryTable supplied isn't contained within a ListObject (ie: created via VBA) but fail to trigger if they are. I've tried using Worksheet_Change events to compare the changed range compared to the range of the ListObject but it seems to trigger for some ListObjects but not for others.

Class file:
VBA Code:
Private Event_Storage As New Collection

Private WithEvents MyQueryTable As Excel.QueryTable

Friend Sub HookUpQueryTable(Query_Info As Variant)

    Event_Storage.Add Query_Info

    Set MyQueryTable = Query_Info(0)

End Sub

Private Sub MyQueryTable_AfterRefresh(ByVal Success As Boolean)

Dim Query_Object As QueryTable, Workbook_Target As Workbook, Procedure_2_Run As String, Variables As Worksheet, _
Y As Long, AR As Variant, Result As Variant, FNL As Variant, Z As Long, L As Long

    If Success Then

        'Determine which query just refreshed
        For Y = 1 To Event_Storage.Count
 
            AR = Event_Storage(Y)
     
            If AR(0) Is MyQueryTable Then 'IF the refresh querytable is found within collection
     
                Set Query_Object = AR(0)
                Procedure_2_Run = AR(1)
                Set Workbook_Target = AR(2)
                Set Variables = AR(3)
         
                #If Mac Then
             
                    If InStr(1, Query_Object.Name, "Time") > 0 Then
                 
                        With Query_Object
                 
                            With .ResultRange
                                Result = .Value2
                                .ClearContents
                            End With
                 
                        End With
             
                        With Variables.ListObjects("Time_Zones").DataBodyRange.Cells(1, 1)
                            .Resize(UBound(Result, 1), UBound(Result, 2)).Value2 = Result
                        End With
                           
                    End If
         
                #Else
         
                #End If
         
                Event_Storage.Remove (Y)
         
                If InStr(1, Query_Object.Name, "Schedule") > 0 Then 'Schedule Procedures
         
                    Application.Run "'" & Workbook_Target.Name & "'!" & Procedure_2_Run, True
                         
                ElseIf InStr(1, Query_Object.Name, "Time") > 0 Then
         
                    Application.Run "'" & Workbook_Target.Name & "'!" & Procedure_2_Run
             
                End If
         
                Exit For
         
            End If
     
        Next Y
 
    End If

End Sub

My usage of the class file:

Code:
Private Sub Time_Zones_Refresh()

Dim QT As QueryTable, Query_Events As New ClassQTE

#If Mac Then

    Dim Query_Exists As Boolean, TB As String, Result() As Variant

    For Each QT In sheet1.QueryTables
        'Debug.Print QT.Name
        If InStr(1, QT.Name, "Time_Z") > 0 Then
            Query_Exists = True
            Exit For
        End If
    Next QT

    If Not Query_Exists Then 'Create Query

        TB = "https://docs.google.com/spreadsheets/d/1ubpPnoj7hQkMkwgLpFwOwmFftWI4yN3jMihEshVC89A/export?format=csv&id=1ubpPnoj7hQkMkwgLpFwOwmFftWI4yN3jMihEshVC89A&gid=0"
 
        Set QT = sheet1.QueryTables.Add(Connection:="TEXT;" & TB, Destination:=sheet1.Range("A1"))
 
        With QT
            .TextFileCommaDelimiter = True
            .WorkbookConnection.Name = "Time_Zones_R"
            .Name = "Time_Z"
            .RefreshStyle = xlOverwriteCells
            .RefreshOnFileOpen = False
            .BackgroundQuery = False
            .RefreshStyle = xlOverwriteCells
        End With
 
    End If

#Else

    Set QT = Variable_Sheet.ListObjects("Time_Zones").QueryTable

#End If

    Query_Events.HookUpQueryTable Array(QT, "Release_Schedule_Refresh", ThisWorkbook, sheet2)
                                        '0            1                   2               3
    QT.Refresh True 'Background refresh

End Sub
 
Last edited:

Excel Facts

Do you hate GETPIVOTDATA?
Prevent GETPIVOTDATA. Select inside a PivotTable. In the Analyze tab of the ribbon, open the dropown next to Options and turn it off
Updated Usage:

Still having the same problem with background Queries for QueryTables Within Listobjects [They were created via Power Query] not triggering the After Refresh Event but do when not a background Query or when the QueryTable wasn't created with Power Query.

Class File
VBA Code:
Private WithEvents MyQueryTable As Excel.QueryTable

Friend Sub HookUpQueryTable(Query_T As QueryTable, Procedure_2_Run As String, WB As Workbook, _
                                    VAR As Worksheet, Non_ListObject_QueryTable As Boolean, _
                                    Optional Weekly_Data_Sheet As Worksheet)
      
Dim Query_Info As Variant

Query_Info = Array(Query_T, Procedure_2_Run, WB, VAR, Non_ListObject_QueryTable, Weekly_Data_Sheet)

WB.Event_Storage.Add Query_Info, Procedure_2_Run 'Workbook_Object.Collection

Set MyQueryTable = Query_T      'Query Table
  
End Sub


Private Sub MyQueryTable_AfterRefresh(ByVal Success As Boolean)

Dim Query_Object As QueryTable, QT_Workbook As Workbook, Procedure_2_Run As String, Variables As Worksheet, _
Y As Long, Weekly_WS As Worksheet, Non_ListObject_QueryTable As Boolean

Set QT_Workbook = MyQueryTable.Parent.Parent

    If Success Then
      
        'Determine which query just refreshed
        For Y = 1 To QT_Workbook.Event_Storage.Count
      
            AR = QT_Workbook.Event_Storage(Y)
          
            If AR(0) Is MyQueryTable Then           'Loop until the refreshed Query is found
          
                Set Query_Object = AR(0)            'Query that was refreshed
                Procedure_2_Run = AR(1)             'Procedure to run with parameter
                Set Variables = AR(3)               'Optional addition Saved Variables worksheet
                Non_ListObject_QueryTable = AR(4)   'Boolean that determines if QueryTable is wrapped in a listobject
                Set Weekly_WS = AR(5)               'Data sheet that contains weekly refreshable data
              
                Select Case Procedure_2_Run
              
                    Case "Time_Zones_Refresh", "Release_Schedule_Refresh"
                  
                        Application.Run "'" & QT_Workbook.Name & "'!" & Procedure_2_Run, Query_Object, Non_ListObject_QueryTable
                  
                    Case "MAC_Update_Check"
                  
                        Application.Run "'" & QT_Workbook.Name & "'!" & Procedure_2_Run, Query_Object
                      
                End Select
                      
                QT_Workbook.Event_Storage.Remove (Y) 'remove Query array from collection
              
                Exit For
              
            End If
          
        Next Y
      
    End If
  
End Sub

Using the Class

Code:
Private Sub Time_Zones_Refresh(Optional QT As QueryTable, Optional Non_ListObject_QueryTable As Boolean)

Dim Query_Events As New ClassQTE, QT_Method As Boolean, ListOB_RNG As Range, Result As Variant, _
Query_Exists As Boolean, URL As String

'After Background Query has finished run this procedure again using an event but supply a QueryTable
'To skip the refresh portion, do additional parsing if needed and then start the next background Query

If QT Is Nothing Then

    #If Mac Then
  
        QT_Method = True
      
    #Else
  
        If Application.Version < 16# Then 'IF excel version is prior to Excel 2016 then
      
            If Not IsPowerQueryAvailable Then QT_Method = True 'Check if Power Query is available
          
        End If
      
    #End If
  
    If QT_Method Then
      
        For Each QT In QueryT.QueryTables           'Determine if QueryTable Exists
            If InStr(1, QT.Name, "Time_Z") > 0 Then 'Instr method used in case Excel appends a number to the
                Query_Exists = True                 'QueryTable Name
                Exit For
            End If
        Next QT
      
        If Not Query_Exists Then 'Create QueryTable
      
            URL = "https://docs.google.com/spreadsheets/d/1ubpPnoj7hQkMkwgLpFwOwmFftWI4yN3jMihEshVC89A/export?format=csv&id=1ubpPnoj7hQkMkwgLpFwOwmFftWI4yN3jMihEshVC89A&gid=0"
          
            Set QT = QueryT.QueryTables.Add(Connection:="TEXT;" & URL, Destination:=QueryT.Range("A1"))
          
            With QT
                .Name = "Time_Z"
                .WorkbookConnection.Name = "Time_Zone_Info"
                .TextFileCommaDelimiter = True
                .RefreshOnFileOpen = False
                .BackgroundQuery = True
                .RefreshStyle = xlOverwriteCells
                .AdjustColumnWidth = False
            End With
          
        End If
      
    Else
  
        Set QT = Variable_Sheet.ListObjects("Time_Zones").QueryTable
      
    End If
    '[  Query Object, Procedure to Call after refresh,  Workbook Object, Variable Worksheet ,
    '   Querytable ListObject boolean,Optional Worksheet ]
  
    Query_Events.HookUpQueryTable QT, "Time_Zones_Refresh", ThisWorkbook, Variable_Sheet, QT_Method, Weekly
                                  '0                1                    2               3         4         5
    QT.Refresh True

Else 'Queries have been refreshed

    Set ListOB_RNG = Variable_Sheet.ListObjects("Time_Zones").DataBodyRange 'Destination range
  
    If Non_ListObject_QueryTable Then 'store range in array and clear contents
  
        With QT.ResultRange
      
            Result = .Value2
            .ClearContents
          
        End With
      
    End If
  
    With ListOB_RNG
  
        If Non_ListObject_QueryTable Then .Cells(1, 1).Resize(UBound(Result, 1), UBound(Result, 2)).Value2 = Result
      
        .Rows(3).Value2 = Array("Local Time", Now)
      
    End With
  
    Call Release_Schedule_Refresh

End If
  
End Sub
 
Upvote 0
Which version of Excel are you using?
 
Upvote 0

Forum statistics

Threads
1,223,162
Messages
6,170,431
Members
452,326
Latest member
johnshaji

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