等到 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
.
行开头
我 运行 遇到了一个竞争条件问题,我有两个 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
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
.