Enabling VBA code in Excel to receive and handle chart events is not very straight forward to do. Fortunately there are quite a few useful guides available for this, e.g. Jon Peltier and David J. Brett.
I recently had to do some custom VBA coding in Excel 2010 and a complete working demo would have been immensely useful. So here is it for anyone that might want to hit the ground running, so to say.
Get the example workbook
First of all you can download the example workbook here (it's macro enabled).
To view the code open the VBA Editor (Alt+F11).
How it is organized
The Class Module CEventChart
This is the main logic where you should put most of your code. This class module acts as the receiver that Excel calls when the charts receive events. Here you need to put the event functions you want to handle (there are examples in there on how to handle both the Activate and Calculate event).
Option Explicit
' Declare object of type "Chart" with events
' This object will hold the Chart instance that is currently being manipulated
Public WithEvents EvtChart As Chart
' *********** The Excel event functions go below this line, avoid having too much custom code in these functions
' rather have the event functions call them as private functions (e.g. like MyGreatFunction below)
Private Sub EvtChart_Activate()
' Executed whenever the chart is enabled (e.g. users selects it)
' TODO: Here comes your logic...
MyGreatFunction
End Sub
Private Sub EvtChart_Calculate()
' Disable screen updating while the subroutine is run.
Application.ScreenUpdating = False
' TODO: Here comes your logic...
MyGreatFunction
'Enable screen updating again
Application.ScreenUpdating = True
End Sub
' + any other evens you want to subscribe to, see: https://msdn.microsoft.com/en-us/library/office/ff822192.aspx
'************* Your private functions go below this line
Private Sub MyGreatFunction()
' You can access the chart object here by using the EvtChart object
Debug.Print "Chart: " + EvtChart.Name
End Sub
Module ChartEventHookups
This module handles the nitty gritty details of connecting/disconnecting the chart events in your workbook. You should not need to modify this code at all and it can be left as is.
Option Explicit
Dim clsEventChart As New CEventChart
Dim clsEventCharts() As New CEventChart
' *************************************************
' This function connects all chart objects in the currently active sheet to the event enabled
' class module CEventChart. This class module contains functions to handle event callbacks raised
' by the chart object when either the user or excel interacts with it.
Sub EnableEventsForAllCharts()
' Enable events on sheet if it is a chart sheet
If TypeName(ActiveSheet) = "Chart" Then
Set clsEventChart.EvtChart = ActiveSheet
End If
' Enable events for all charts embedded on a sheet
' Works for embedded charts on a worksheet or chart sheet
If ActiveSheet.ChartObjects.Count > 0 Then
ReDim clsEventCharts(1 To ActiveSheet.ChartObjects.Count)
Dim chtObj As ChartObject
Dim chtnum As Integer
chtnum = 1
For Each chtObj In ActiveSheet.ChartObjects
Set clsEventCharts(chtnum).EvtChart = chtObj.Chart
chtnum = chtnum + 1
Next ' chtObj
End If
End Sub
' *************************************************
' Unhook the event classes from the charts
Sub DisableEventsForAllCharts()
' Disable events for all charts previously enabled together
Dim chtnum As Integer
On Error Resume Next
Set clsEventChart.EvtChart = Nothing
For chtnum = 1 To UBound(clsEventCharts)
Set clsEventCharts(chtnum).EvtChart = Nothing
Next ' chtnum
End Sub
Excel Object Sheet2 (Charts)
This code should be placed in all worksheets that contain charts you want to receive events for. What this code does is simply connect the events when the sheet is activated first and then disconnect the events when another sheet is activated. This helps save resources and speed up calculations.
Option Explicit
'****************************************************************
' When the worksheet is selected hook up the event classes.
' If the chart source data has changed in the mean time then the Calculate event will be raised
Private Sub Worksheet_Activate()
EnableEventsForAllCharts
End Sub
'****************************************************************
'When the worksheet is deselected disable the events
Private Sub Worksheet_Deactivate()
DisableEventsForAllCharts
End Sub
Excel Object ThisWorkbook
This code handles hooking the chart events up correctly when the workbook is first opened if the workbook is opened with the chart sheet active.
Option Explicit
'****************************************************************
' When the workbook is first opened then the charts in the active sheet must
' be connected immediately otherwise out of date data might be displayed (in case the book closed unexpectedly before)
Private Sub Workbook_Open()
' Disable screen updating while the subroutine is run.
Application.ScreenUpdating = False
EnableEventsForAllCharts
'Enable screen updating again
Application.ScreenUpdating = True
End Sub
Get the example workbook
Again, you can download the example workbook here (it's macro enabled).
To view the code open the VBA Editor (Alt+F11).
Developer & Programmer with +15 years professional experience building software.
Seeking WFH, remoting or freelance opportunities.