由于我遇到了同样的问题,我按照 Chip Pearson 的说明进行了工作,并将为您提供更全面的指南。
我也非常鼓励您通过Chip Pearson's great summary 阅读有关事件的方式。我知道要消化的内容很多,但它会极大地帮助您了解我们在这里的实际工作。
作为概述,这些是我们将要执行的步骤:
- 为我们的事件处理程序添加一个类模块(这是实际事件处理代码所在的位置)
- 向我们的 personal.xlsb 的
ThisWorkbook 模块添加一个事件处理程序来连接我们的事件处理程序类
- 享受无限的事件处理循环,因为我们更改了
Target.Value :-P(可选)
让我们开始吧。
1。添加类模块
首先,我们需要创建一个舒适的广场来放置我们所有的事件处理程序。我们将为此使用一个类模块,因为它提供了一些不错的结构,并且您可以立即知道在哪里寻找您的应用程序级事件处理程序。
在您的personal.xlsb 的VBA 项目中,通过在项目浏览器中右键单击 创建一个新类 -> 插入 -> 类模块.
通过在属性窗格中更改名称,将类重命名为 CAppEventHandler。
将下面列出的源代码(设置部分和事件处理部分)添加到您刚刚创建的类中。 (请务必阅读 cmets,因为它们为我们正在做的事情和原因添加了一些额外的信息。)
2。添加初始化事件处理程序
现在我们需要确保在打开 personal.xlsb 时“激活”我们的事件处理程序(因此无论何时打开 Excel :))。
为此,请双击您的 ThisWorkbook 模块并添加以下代码。
现在您实际上已经可以开始测试您的事件处理了。您唯一需要事先做的事情(为了触发“连接”过程)就是重新启动 Excel。
注意事项
- 我在事件处理程序的开头添加了对当前工作表名称的检查 - 因此请确保您的工作表名为“MySheet”:)
- 您可以在处理程序中设置断点并观察它的运行情况,就像任何其他 VBA 代码一样
还有一点警告(又名 3. 享受无限的事件处理循环)
当我对此进行测试时,我天真地使用Target.Value = "It wooooorks!" 作为我们更改右侧工作表上的右侧单元格时要执行的代码。 那不好。
有关如何防止此类事件循环,请参阅代码的最后一个 sn-p(也取自 Chip's post)。
源代码
在CAppEventHandler 类中(设置)
Option Explicit
' Declare our own reference to the Application object
' WithEvents is needed to capture the events of the application object
' (Note: The events 'bubble up' from the Worksheet to the Workbook and
' finally to the Application.
' So event handlers in the Sheet module are executed first
' (if any handlers are declared), then the ones in the Workbook
' module (again, if they are declared) and finally the ones
' in the Application module.)
Private WithEvents App As Application
' Whenever a new object of a class is instantiated, the _Initialize-Sub is called,
' that's why we use this Sub to get the reference to the current Application object
Private Sub Class_Initialize()
Set App = Application
End Sub
在CAppEventHandler 类中(实际事件处理)
' Here is the actual code executed whenever the event reaches the Application level
' (see above for the order of 'bubbling up' of the events) and hasn't been marked
' as handled before
Private Sub App_SheetChange(ByVal Sh As Object, ByVal Target As Range)
If Sh.Name <> "MySheet" Then
Exit Sub
End If
Dim rngKeyCells As Range
Set rngKeyCells = Sh.Range("A5")
If Intersect(rngKeyCells, Target) Is Nothing Then
Exit Sub
End If
' Do our actual work
MsgBox "It wooooorks!", vbInformation
' Note: If you want to change the contents of your keyCells, you will
' have to make sure to prevent an infinite event loop (i.e. using
' Application.EnableEvents = False because otherwise changing
' the value in your macro will trigger the event again
End Sub
在ThisWorkbook 模块中
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' The following code must be placed in the "ThisWorkbook" module of your personal.xlsb
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Option Explicit
Private OurEventHandler As CAppEventHandler
Private Sub Workbook_Open()
' Since we declared so in our _Initialize-Sub this wire-up the current
' Application object in our EventHandler class
Set OurEventHandler = New CAppEventHandler
End Sub
如何防止事件循环
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
Target.Value = Target.Value + 1
Application.EnableEvents = True
End Sub
(来自Chip Pearson's comprehensive post on events)