刷新所有不触发QueryTable的BeforeRefresh事件 - 为什么?

时间:2017-06-13 20:39:29

标签: excel vba excel-vba events triggers

如标题所述:我发现单击功能区上的“全部刷新”按钮不会触发QueryTable的BeforeRefresh事件。为什么会这样?有没有办法改变这种行为?

奇怪的是,完全触发了同一个QueryTable的AfterRefresh事件!

为了分析这种行为,我在两个工作表中创建了两个表:

  1. 简单,未链接的表名为Source
  2. Destination表关联的名为Source的表。使用Microsoft Query和Excel Files作为数据源创建连接。
  3. 然后,我按如下方式创建了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 one。

    我准备了一个可以重现所描述行为的最小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是包含(Name)表的工作表的Destination属性的值。

    可以看出,Destination是一个私有字段,但似乎垃圾收集器并不关心:我可以右键单击刷新Destination表我想要的时间以及之前和之后的MsgBoxes 总是弹出。然而,刷新所有从不(甚至一次)触发BeforeRefresh事件,但总是触发AfterRefresh一个。

1 个答案:

答案 0 :(得分:1)

Option Explicit
Public tc as TestClass
Sub Test()
    Set tc = New TestClass
    tc.Init Worksheets("SomeSheet").ListObjects(1).QueryTable
End Sub
  • 只有在选项卡Excel GUI中使用刷新选项时,才会触发BeforeRefresh。当您使用这个时,两个事件都会适当地触发。
  • 当您在Excel GUI的查询标签中使用刷新选项时,只会触发第二个事件。

原因是QueryTable 在使用查询刷新选项时触发了此BeforeRefresh事件,原因是您实际上并未刷新QueryTable本身,而是基础查询。

  • BeforeRefresh事件发生在查询表的任何刷新之前。 Here
  • 查询完成或取消后发生AfterRefresh事件。 Here

当你这样做时:

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实际上刷新了工作簿中的查询,而不是查询表。同样的答案也适用。

简而言之:它的表现与预期一致。