Problem: I have found many postings (including Microsoft\'s own support site) containing information on how to run a macro when certain cells change in Exce
Since I faced the same problem, I worked my way through Chip Pearson's instructions and will provide you with a more comprehensive guide.
I can also really encourage you to read your way through Chip Pearson's great summary on events. I know it's a lot to digest, but it will greatly help you understand what we actually do here.
As an overview, these are the steps we are going to perform:
ThisWorkbook
module to wire-up our event handler classTarget.Value
:-P (optional)Let's get started.
First, we need to create a cozy plaze to put all our event handlers. We will use a class module for this, since it provides some nice structure and you immediately know where to look for your application level event handlers.
In your personal.xlsb
's VBA project create a new class by right clicking in the project browser -> insert -> class module.
Rename the class to CAppEventHandler by changing the name in the properties pane.
Add the source code listed below (both the setup part and the event handling part) to the class you just created. (Make sure to read the comments, because they add some additional information to what we are doing and why.)
Now we need to make sure our event handlers are "activated" when our personal.xlsb
is opened (so anytime you open Excel :)).
To do this, double click your ThisWorkbook
module and add the code below.
Now you are actually already good to go and can test your event handling. The only thing you will have to do beforehand (in order to trigger the "wiring-up" process) is restart Excel.
And a word of warning (aka 3. Enjoy infinite event handling loops)
When I tested this, I naively usedTarget.Value = "It wooooorks!"
as the code to be executed if we changed the right cell on the right sheet. That was not good.
See the last snippet of code (also taken from Chip's post) for how to prevent such an event loop.
CAppEventHandler
class (setup)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
class (actual event handling)' 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
module'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' 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
(from Chip Pearson's comprehensive post on events)