VBA для Excel AfterRefresh Event

Я использую следующий запрос QueryTable. После выполнения .Refresh процедура VBA завершается. Запрос работает, но мне нужно выполнить код после его завершения.

Событие .AfterRefresh похоже на то, что мне нужно, но я не могу заставить его выполнить.

With ActiveSheet.QueryTables.Add(Connection:="URL;" & sUrl, Destination:=ActiveSheet.Range("a1"))

             .RefreshStyle = xlOverwriteCells
             .SaveData = True
             .Refresh
             .AfterRefresh (Success)
End With

Это вспомогательный элемент AfterRefresh, который не выполняется.

Sub QueryTable_AfterRefresh(Success As Boolean)

        If Success Then
                 Debug.Print "Success"
        Else
                 Debug.Print "Failed"
        End If
End Sub

Что необходимо для запуска подпрограммы после выполнения запроса? Я попробовал вызов подпрограммы после .Refresh и после окончания, но не работал.

Спасибо.

+2
источник поделиться
3 ответа

Пожалуйста, убедитесь, что ваш QueryTable_AfterRefresh юг помещен НЕ в модуль, но в разделе Sheet/Workbook, так же, как здесь: fooobar.com/questions/549959/... Более того, вы не нужно вызывать событие, удалите .AfterRefresh (Success) из вашего кода.

+3
источник

Я столкнулся с этой проблемой в последнее время, и было очень сложно найти хороший ответ. Я понимаю, что эта ветка устарела, но есть достойная альтернатива другому размещенному решению.

Один шаблон, который вы можете использовать, сохраняет события обратного вызова QueryTable в отдельном Class Module вместо встроенного в рабочий лист. Это позволяет использовать более модульный, многоразовый код. Это становится особенно полезным, если в книге Excel много запросов QueryTables.

Вот что может выглядеть модуль класса в модуле класса CQtEvents

Option Explicit

Private WithEvents mQryTble As Excel.QueryTable
' Add variables you may want to cache here such at the query or connection settings

' Properties
Public Property Set QryTble(ByVal QryTable As QueryTable): Set mQryTble = QryTable:
End Property
Public Property Get QryTble() As QueryTable: Set QryTble = mQryTble:
End Property
' Add other potential properties here

Private Sub Class_Initialize()
    ' Constructor
    MsgBox "CQtEvents init"
End Sub

Private Sub mQryTble_BeforeRefresh(ByVal Cancel as Boolean)
    'Insert logic you want to run before a refresh
End Sub   

Private Sub mQryTble_AfterRefresh(ByVal Success As Boolean)
    'Insert logic you want to run after a refresh

End Sub

Ключевое замечание, приведенное выше, - это ключевое слово WithEvents и объявления/определения для BeforeRefresh и AfterRefresh.

Ниже приведен код, который может выглядеть так, чтобы использовать модуль класса, определенный выше.

Option Explicit

Sub RefreshDataQuery()
'Dependencies: Microsoft Scripting Runtime (Tools->References) for Dictionary (HashTable) object

Dim querySheet As Worksheet
Dim classQtEvents As CQtEvents

Set querySheet = Worksheets("QTable")
Set interface = Worksheets("Interface")
Set classQtEvents = New CQtEvents ' Instantiate the Class

Dim qt As QueryTable
Dim qtDict As New Scripting.Dictionary

Set qtDict = UtilFunctions.CollectAllQueryTablesToDict
Set qt = qtDict.Item("Query from fred2")

''' Building SQL Query String '''
qt.CommandText = "Select * From someTable" 

If Not qt Is Nothing Then
    qt.Refresh False ' See link at bottom of post for alternatives to this
Else
    ' ... Error handling code here... 
End If


''' CLEAN UP '''

' Free the dictionary
Set qtDict = Nothing

End Sub

Одно из предостережений с этим подходом заключается в том, что AfterRefresh не будет вызываться, если он выполняется асинхронно и остается как есть. Причиной этого является ссылка на таблицу запросов, которая исчезнет, ​​когда модуль завершит выполнение, которое, вероятно, завершится до завершения завершения запроса. Чтобы обойти это, вы можете запустить его синхронно, установив

 qt.Refresh False

Однако это не лучший подход, но он будет работать, если вы не возражаете ждать запроса до того, как будет запущен какой-либо другой код в Sub Module. См. Это сообщение для действительно хорошего ответа на альтернативы этой Excel VBA - функция QueryTable AfterRefresh, которая не вызывается после того, как Refresh завершает KazJaw.

Надеюсь, это поможет, поскольку это хорошая альтернатива написанию этих обработчиков событий, встроенных в рабочий лист.

+3
источник
другие ответы

Связанные вопросы


Похожие вопросы

Ниже приведено описание gythub repo, демонстрирующего минимальный код, необходимый для получения этой работы здесь.

Как упоминалось в других ответах, ключевыми факторами, позволяющими вам поймать событие, являются:

  • Объявите глобальную переменную типа вашего класса обработки событий вне любых подпрограмм/методов в верхней части файла (я выбрал файл ThisWorkbook).

  • Добавьте обработчик события Workbook_Open и создайте экземпляр этой переменной, чтобы он был доступен сразу и остался в области видимости (поскольку он глобальный).

  • В этот момент или в любой нисходящей точке, когда у вас есть интересующая вас QueryTable, передайте этот QueryTable глобальному экземпляру, чтобы связать его события.

(Мне потребовалось пару попыток выяснить это сам, когда кто-то указал мне в этом направлении как ответ на этот вопрос.)

0
источник

Посмотрите другие вопросы по меткам или Задайте вопрос