Excel AfterRefresh事件的VBA

我正在使用以下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和End With之后尝试调用子程序,但都没有成功。

谢谢。

请确保您的QueryTable_AfterRefresh子被放置在模块中,但在Sheet / Workbook下,与此处相同: https : //stackoverflow.com/a/14646261/1953175此外,您不需要调用event,remove .AfterRefresh (Success)从您的代码。

最近我遇到了同样的问题,很难find一个好的答案。 我意识到这个线程是旧的,但有一个体面的替代scheme发布的其他解决scheme。

您可以使用的一种模式是将QueryTablecallback事件保存在单独的类模块中,而不是embedded到工作表中。 这允许更多的模块化,可重用的代码。 当您的Excel工作簿具有多个QueryTable时,它变得特别有用。

以下是在类模块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 

这种方法的一个警告是,如果这是asynchronous运行并保持不变,则不会调用AfterRefresh。 这样做的原因是对查询表的引用将在模块完成执行时消失,这可能在查询完成之前完成。 为了解决这个问题,你可以通过设置来同步运行它

  qt.Refresh False 

但是,这不是最好的方法,但如果您不介意在子模块中的任何其他代码运行之前等待查询将工作。 看到这个post的一个非常好的答案Excel VBA的替代品- 刷新完成后 ,KazJaw QueryTable AfterRefresh函数不被调用 。

希望这会有所帮助,因为这是写入这些embedded在工作表中的事件处理程序的好select

演示获得这个工作所需的最低代码的github回购可以在这里find。

正如其他答案中提到的那样,确保您抓住事件的关键因素是:

  1. 在文件顶部(我selectThisWorkbook文件)的任何子程序/方法之外声明事件处理类模块types的全局variables。

  2. 添加一个Workbook_Open事件处理程序并在那里实例化该variables,以便它立即可用并将保持在作用域中 (因为它是全局的)。

  3. 在那个时候,或者在你有兴趣的QueryTable的任何下游点,将QueryTable传递给全局实例来连接它的事件。

(当时有人指着我这个方向回答了这个问题 ,我花了几个试图自己弄清楚。)