如标题所述:我发现单击功能区上的“全部刷新”按钮不会触发 QueryTable 的 BeforeRefresh 事件。为什么会这样呢?有没有办法改变这种行为?
奇怪的是,同一个 QueryTable 的 AfterRefresh 事件被完美触发!
为了分析此行为,我在两个工作表中创建了两个表:
- 简单的、未链接的表,称为
Source
- 名为
Destination
的表链接到Source
表。连接是使用 Microsoft Query 和 Excel 文件作为数据源创建的。
然后,我创建了 TestClass
,如下所示:
Option Explicit
Private WithEvents qt As QueryTable
Public Sub Init(pQt As QueryTable)
Set qt = pQt
End Sub
Private Sub qt_BeforeRefresh(Cancel As Boolean)
MsgBox "BeforeRefresh"
End Sub
Private Sub qt_AfterRefresh(ByVal Success As Boolean)
MsgBox "AfterRefresh"
End Sub
最后,我创建、初始化并存储了 TestClass
的实例。
右键单击Destination
表并选择“刷新”可得到预期结果:MsgBox 显示两次,确认触发了刷新前和刷新后事件。
但是,单击功能区上的“全部刷新”会导致仅显示一个 MsgBox:AfterRefresh 一个。
我准备了一个最小的 Excel 文件来重现所描述的行为。可以在这里下载:RefreshAllNotTriggeringBeforeRefresh.xlsm
编辑 1:响应 Rik Sportel's question关于如何创建和初始化 TestClass
实例。
这是 ThisWorkbook
对象的相关部分:
Option Explicit
Private Destination As New TestClass
Private Sub Workbook_Open()
Destination.Init WS_Destination.ListObjects("Destination").QueryTable
End Sub
其中 WS_Destination
是包含 Destination
表的工作表的 (Name)
属性的值。
正如人们所看到的,Destination
是一个私有(private)字段,但垃圾收集器似乎并不关心:我可以右键单击刷新Destination
表多次,并且 Before- 和 After- MsgBoxes 总是弹出。然而,“Refresh All”从不(甚至一次)不会触发 BeforeRefresh 事件,但总是触发 AfterRefresh 事件。
最佳答案
Option Explicit
Public tc as TestClass
Sub Test()
Set tc = New TestClass
tc.Init Worksheets("SomeSheet").ListObjects(1).QueryTable
End Sub
- BeforeRefresh 仅在您使用表格选项卡 Excel GUI 中的刷新选项时才会触发。当您使用此事件时,两个事件都会适当触发。
- 当您使用 Excel GUI 的查询选项卡中的刷新选项时,只会触发第二个事件。
原因是,在使用查询刷新选项时,QueryTable没有触发此 BeforeRefresh 事件,因为您实际上并未刷新 QueryTable 本身,而是刷新基础查询。
当你这样做时:
Option Explicit
Public tc as TestClass
Sub Test()
Set tc = New TestClass
tc.Init Worksheets("SomeSheet").ListObjects(1).QueryTable
Worksheets("SomeSheet").ListObjects(1).QueryTable.Refresh
End Sub
您将看到这两个事件都正确触发。
编辑: RefreshAll 实际上刷新工作簿中的查询,而不是查询表。同样的答案也适用。
简而言之:它的行为符合预期。
关于vba - Refresh All 没有触发 QueryTable 的 BeforeRefresh 事件 - 为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44531126/