我遇到競爭條件問題,我有兩個QueryTables,每個都掛上了它自己的AfterRefresh事件。每個AfterRefresh事件都會執行一些copy'n'pasting以及一些計算。等待,直到Excel刷新全部(Ctrl + Alt + F5)完成 - VBA
現在,當用戶單擊刷新所有(Ctrl+Alt+F5)
在Excel中,我希望有每個AfterRefresh處理程序執行,但只有在所有QueryTable刷新完全完成後。
我做StackOverflow上進行搜索,並someone suggested
Activeworkbook.RefreshAll
DoEvents
然而,這是假設,我們以編程方式觸發RereshAll。在我的情況下,刷新全部是通過Excel中的內置刷新全部(Ctrl+Alt+F5)
按鈕完成的。因此,我沒有看到我可以在哪裏插入DoEvents
(除非我創建了我自己的「全部刷新」按鈕,但我想避免這樣做)。
我試圖搜索「Excel VBA互斥體」,但我沒有找到任何特別的東西。那麼,如何在每個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處理程序成功地copy'n'pasting。另一個不工作,直到我再次單擊刷新全部按鈕(Ctrl+Alt+F5)
。
也許每個'AfterRefresh'事件處理程序可以以'Activeworkbook.RefreshAll'結尾,後面跟着'DoEvents',也許有一些切換布爾公共變量來阻止回聲事件。 –
@JohnColeman,但用戶已經點擊了內置的全部刷新按鈕,所以如果我爲每個'AfterRefresh'添加'Activeworkbook.RefreshAll'並不意味着它實質上是刷新兩次? 其實,在第二個想法,因爲它是在'AfterRefresh'內,它會觸發無限循環刷新?因爲'AfterRefresh'會觸發另一次刷新,這會再次觸發'AfterRefresh' – Antony
現在我可以更清楚地看到問題了。也許在每個事件處理程序的開始處包含一個定時器循環,在循環體中帶有一個「DoEvents」。每個事件處理程序可以暫停幾秒鐘,同時允許刷新完成。它甚至可以像在每個處理程序的開始處包含一個「DoEvents」一樣簡單。你將需要某種kludge,因爲Excel並不是專爲多線程而設計的。另外 - 我不記得現在是什麼,我曾經遇到過連續需要兩個「DoEvents」的情況。作爲一個實驗開始2 @ –