等到 Excel RefreshAll (Ctrl+Alt+F5) 完成 - VBA

Wait until Excel RefreshAll (Ctrl+Alt+F5) finishes - VBA

我 运行 遇到了一个竞争条件问题,我有两个 QueryTable,每个 QueryTable 都有自己的 AfterRefresh 事件。每个 AfterRefresh 事件都会进行一些复制粘贴以及一些计算。

现在,当用户在 Excel 中单击全部刷新 (Ctrl+Alt+F5) 时,我希望每个 AfterRefresh 处理程序都执行,但只有在所有 QueryTable 刷新完全完成之后。

我在 Whosebug 上进行了搜索,someone suggested

Activeworkbook.RefreshAll
DoEvents

但是,这是假设我们以编程方式触发 RereshAll。就我而言,全部刷新是通过 Excel 中的内置全部刷新 (Ctrl+Alt+F5) 按钮完成的。因此,在我的案例中,我看不到可以插入 DoEvents 的位置(除非我创建自己的“全部刷新”按钮,但我想避免这样做)。

我试图搜索 "Excel VBA mutex",但没有找到任何特别的东西。那么如何确保在每个 AfterRefresh 处理程序发生之前完成所有刷新?

感谢阅读!

更新:为了帮助调试..这是我的 VBA 代码。

我有一个名为 AutoOpen

的模块
Dim S As New DataCopy
Dim U As New DataCopy

Sub Auto_Open()
    Set S.qt = ThisWorkbook.Sheets(1).QueryTables(2)
    S.myWorkbookName = ThisWorkbook.Name
    S.sWorksheetProcessName = "ProcessS"
    S.sWorksheetDataColumnStart = 1
    S.sWorksheetDataColumnEnd = 5
    Set U.qt = ThisWorkbook.Sheets(1).QueryTables(1)
    U.myWorkbookName = ThisWorkbook.Name
    U.sWorksheetProcessName = "ProcessU"
    U.sWorksheetDataColumnStart = 6
    U.sWorksheetDataColumnEnd = 10
End Sub

我还有一个名为 DataCopy

的 Class 模块
Public WithEvents qt As QueryTable
Public myWorkbookName As String
Public sWorksheetProcessName As String
Public sWorksheetDataColumnStart As Integer
Public sWorksheetDataColumnEnd As Integer

Private Sub qt_AfterRefresh(ByVal Success As Boolean)
    DataCopier
End Sub

Private Sub DataCopier()
    'Debug.Print sWorksheetProcessName & "," & Application.CalculationState
    Dim LastNRows As Integer
    Dim sWorksheetDataName As String

    ' How many rows to copy
    LastNRows = 297
    sWorksheetDataName = "Data"

    Application.ScreenUpdating = False

    ' Clear content in process tab
    With Workbooks(myWorkbookName).Worksheets(sWorksheetProcessName)
        .Range(.Cells(4, 1), .Cells(.Cells(Rows.Count, 1).End(xlUp).Row, 6)).ClearContents
    End With

    ' Copy to process Tab
    With Workbooks(myWorkbookName).Worksheets(sWorksheetDataName)
        LastRow = .Cells(Rows.Count, 1).End(xlUp).Row
        FirstRow = LastRow - LastNRows
        If FirstRow < 2 Then
            FirstRow = 2
        End If
        .Range(.Cells(FirstRow, sWorksheetDataColumnStart), .Cells(LastRow, sWorksheetDataColumnEnd)).Copy _
             Destination:=Workbooks(myWorkbookName).Worksheets(sWorksheetProcessName).Range("A4")
    End With

    Debug.Print (sWorksheetProcessName & "," & sWorksheetDataColumnStart & "," & sWorksheetDataColumnEnd)

    Application.ScreenUpdating = True
End Sub

由于竞争条件,只有一个 AfterRefresh 处理程序成功复制'n'粘贴..另一个不起作用,直到我再次单击“全部刷新”按钮 (Ctrl+Alt+F5)

将查询更改为不允许后台刷新,并且在刷新之前不会放弃控制

如果 DoEvents 在显式 VBA 触发器 Activeworkbook.RefreshAll 之后工作,那么 DoEvents 之前你想要的代码事件处理程序中的 运行 应该涵盖刷新由 Ctrl+Alt+F5 触发的情况。因此,每个事件处理程序都以 DoEvents.

行开头