我正在使用 VBA 开发一个 Excel (2010+) 应用程序,并且遇到了一个问题,即一旦查询完成执行,就不会调用 AfterRefresh 事件函数。
我还没有找到很多像样的资源或文档来说明如何在类模块中触发这个事件函数。在收到对有关 QueryTables 的较早问题的响应(在此处找到Excel VBA AfterRefresh)后,我决定使用类模块设计路线,而不是将事件处理程序放入工作表中。
这是我的名为 CQtEvents 的类模块的代码
Option Explicit
Private WithEvents mQryTble As Excel.QueryTable
Private msOldSql As String
' 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
Public Property Let OldSql(ByVal sOldSql As String): msOldSql = sOldSql:
End Property
Public Property Get OldSql() As String: OldSql = msOldSql:
End Property
Private Sub Class_Initialize()
MsgBox "CQtEvents init"
End Sub
' Resets the query sql to the original unmodified sql statement
' This method is invoked when the Refresh thread finishes executing
Private Sub mQryTble_AfterRefresh(ByVal Success As Boolean)
' Problem is here
' This function is never called :( Even if the query successfully runs
Me.QryTble.CommandText = Me.OldSql
End Sub
这是创建此类的实例,找到相关的 QueryTable,然后调用 Refresh 的代码的快速快照
Option Explicit
Sub RefreshDataQuery()
'Dependencies: Microsoft Scripting Runtime (Tools->References) for Dictionary (HashTable) object
'From MGLOBALS
cacheSheetName = "Cache"
Set cacheSheet = Worksheets(cacheSheetName)
Dim querySheet As Worksheet
Dim interface As Worksheet
Dim classQtEvents As CQtEvents
Set querySheet = Worksheets("QTable")
Set interface = Worksheets("Interface")
Set classQtEvents = New CQtEvents
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 '''
Dim sqlQueryString As String
sqlQueryString = qt.CommandText
Set classQtEvents.QryTble = qt
classQtEvents.OldSql = sqlQueryString ' Cache the original query string
QueryBuilder.BuildSQLQueryStringFromInterface interface, sqlQueryString
' Test message
MsgBox sqlQueryString
qt.CommandText = sqlQueryString
If Not qt Is Nothing Then
qt.Refresh
Else
' ... Error handling code here...
End If
''' CLEAN UP '''
' Free the dictionary
Set qtDict = Nothing
End Sub
这里也是模块结构的截图http://imgur.com/8fUcfLV
我对可能是什么问题的第一个想法是按值传递 QueryTable。我不是最有经验的 VBA 开发人员,但我认为这会创建一个副本并在不相关的表上调用事件。但是,情况并非如此,通过引用传递也不能解决问题。
由于数据正确显示并刷新,查询也被确认成功运行。
编辑 我将 BeforeRefresh 事件函数添加到 CQtEvents 类模块并确认调用 Refresh 后调用此函数
Private Sub mQryTble_BeforeRefresh(Cancel As Boolean)
MsgBox "Start of BeforeRefresh"
End Sub
如何更改此代码从 QTableModule 的 RefreshDataQuery() 子例程获取我的 QueryTable,以便在成功运行查询时调用 AfterRefresh 函数?