如果您使用全局標誌來指示正在發生哪種處理,則可以在不必禁用事件的情況下解決此問題。
從您的設計說明中不完全清楚爲什麼您需要同時處理Worksheet_Change
事件和Workbook_SheetChange
事件。但是,很好地瞭解每個事件何時會發生一定的幫助。在你的情況下,如果你改變Sheet1上的單元格,你會得到Sheet1的Worksheet_Change
事件,然後得到Workbook_SheetChange
事件。這會在您更改任何工作表時發生。
下面的示例說明了如何處理處理以保持一切順利,並且不會踩到您通過VBA進行的更改以及手動進行的更改。這個例子有很多部分,所以請在家裏跟着...
首先,我們需要建立兩個Public
東西:一個工作簿全局標誌和一個工作簿全局子例程來執行處理。所以在VBA代碼模塊(Module1
),我們有以下代碼:
'------ Module1 --------
Option Explicit
Public MyCustomMacroInProgress As Boolean
Public Sub DistributeChangeToSheets()
Debug.Print "Entering DistributeChangeToSheets... "
MyCustomMacroInProgress = True
Debug.Print "=== setting MyCustomMacroInProgress = " & MyCustomMacroInProgress
'--- loop to fire change events in the other worksheets for testing
Dim ws As Variant
For Each ws In ThisWorkbook.Sheets
If ws.Name <> "Sheet1" Then
ws.Range("A1") = 1
End If
Next ws
MyCustomMacroInProgress = False
Debug.Print "=== setting MyCustomMacroInProgress = " & MyCustomMacroInProgress
Debug.Print "Leaving DistributeChangeToSheets"
End Sub
(請注意,使用Option Explicit
到處大大有助於您的代碼)
通過建立一個公共全局標誌(MyCustomMacroInProgress
)您現在可以在任何模塊以及任何類和任何工作表中檢查此標誌。通過在模塊中創建Sub DistributeChangeToSheets
並將其公開,您可以基本上從您可能需要的任何始發工作表中應用此類處理。我的示例僅適用於Sheet1中的更改。
所以現在到主要更改捕手 - Sheet1。在您的工作表Sheet1的代碼,我有
Option Explicit
'--- in Sheet1
Private Sub Worksheet_Change(ByVal Target As Range)
Debug.Print "In " & Target.Parent.Name;
Debug.Print ": Worksheet_Change event fired ";
Debug.Print " - changed cell " & Target.Address
DistributeChangeToSheets
End Sub
我打印的Debug
報表無所不在,所以它更容易跟隨,其中處理是怎麼回事。您可以看到,在Sheet1中,我們正在打印我們所在的位置,然後調用子模塊DistributeChangesToSheets
(來自Module1)。
我的例子只有三個工作表,所以在另一片模塊的代碼很簡單:
Option Explicit
'--- in Sheet2
Private Sub Worksheet_Change(ByVal Target As Range)
Debug.Print "In " & Target.Parent.Name;
Debug.Print ": Worksheet_Change event fired ";
If Not MyCustomMacroInProgress Then
Debug.Print " - process change event normally"
Else
Debug.Print " - skip normal change event processing"
End If
End Sub
而且
Option Explicit
'--- in Sheet3
Private Sub Worksheet_Change(ByVal Target As Range)
Debug.Print "In " & Target.Parent.Name;
Debug.Print ": Worksheet_Change event fired ";
If Not MyCustomMacroInProgress Then
Debug.Print " - process change event normally"
Else
Debug.Print " - skip normal change event processing"
End If
End Sub
在例如現在把所有這些一起,鍵入一個值成Sheet1上的任何單元格。眼前的窗口現在顯示以下輸出:
In Sheet1: Worksheet_Change event fired - changed cell $B$2
Entering DistributeChangeToSheets...
=== setting MyCustomMacroInProgress = True
In Sheet2: Worksheet_Change event fired - skip normal change event processing
In Sheet2: Workbook_SheetChange event fired - skip normal change event processing
In Sheet3: Worksheet_Change event fired - skip normal change event processing
In Sheet3: Workbook_SheetChange event fired - skip normal change event processing
=== setting MyCustomMacroInProgress = False
Leaving DistributeChangeToSheets
In Sheet1: Workbook_SheetChange event fired - process change event normally
從輸出中,你可以看到表和工作簿事件都遵循事件模式 - 讓您得到兩個事件時,工作表被改變(Worksheet_Change
和Workbook_SheetChange
)。通過在Sheet1上設置全局標誌(來自DistributeChangeToSheets
之內),通過使用If
語句,可以禁止在此類處理期間對所有其他工作表進行更改處理。
這可能涉及到您的部分重新編碼,但以有序的方式處理您的事件可以使處理流程更清晰一些。
難道是ws2的改變嗎?您可以將代碼移動到工作簿中,並使用傳入的sheetname變量來確定是否運行上述操作。像'ws2.cells(lastline,target.column).value = target.value'可能更簡單。 –
你真正寫在這裏的是你對「怪異行爲」的自我診斷。如果您向我們提供了所有相關代碼,例如您在表單1等中的實際操作,我們可能會提供幫助。事件是一個應用程序範圍的參數,所以我不知道你爲什麼說你「在*第一個工作表上禁用了*」?請更清楚一點 – Wolfie
很簡單:我只有一個工作簿。在本工作手冊中,我有34個工作表。首先,我正在執行一些計算,然後,我將這些結果粘貼到其他33張表上。問題是我有一個'Workbook_SheetChange'事件對這個粘貼作出反應。我不知道爲什麼,因爲在粘貼之前,我正在這樣做:'Application.EnableEvents = False'。我不希望啓動'Workbook_SheetChange'事件。如果你知道爲什麼... –