title: VBA Raising event on another class
body: <p>I am trying to implement the suggestions from <a href="https://codereview.stackexchange.com/a/235295/197645">this post in codereview</a></p>
  
  <p><strong>Objective:</strong></p>
  
  <p>Manage what happens when users interact with Excel Tables (ListObjects)</p>
  
  <p>The idea at the end is to have custom events for different tables. e.g. When you add a row to table1 the custom AddEvent1 is raised, and when you do the same to table2, AddEvent2 is raised.</p>
  
  <p>There would be only one class to manage the events and one to hold the tables and their information.</p>
  
  <hr>
  
  <p><strong>So the process suggested is to:</strong></p>
  
  <ol>
  <li>Add the listobject to a class called <code>Table</code></li>
  <li>That class would listen to the events on the parent sheet (<code>Change</code> and <code>SelectionChange</code>)</li>
  <li>When a change event is fired, trigger a custom event from a class <code>TableManager</code> that handles those events (events like <code>adding</code>, <code>updating</code> or <code>deleting</code> rows)</li>
  </ol>
  
  <hr>
  
  <p><strong>EDIT #1:</strong></p>
  
  <p>Adjusted the code:</p>
  
  <ul>
  <li>The <code>Create</code> function now returns an instance of a <code>Table</code></li>
  <li>And the property <code>Set SourceTable</code> now sets the <code>listObjectParentSheet</code> field to the corresponding value</li>
  </ul>
  
  <p>But still the <code>Table Manager</code> doesn't listen to the event raised in  <code>listObjectParentSheet_Change</code></p>
  
  <hr>
  
  <p><strong>Components:</strong></p>
  
  <p>1) A Sheet with an Excel Table (ListObject) and the following code behind:</p>
  
  <pre><code>Private Sub Worksheet_Activate()
  
      Dim myTable As Table
      Dim myTableManager As TableManager
  
      Set myTable = Table.Create(Me.ListObjects(1))
  
      Set myTableManager = New TableManager
  
      Set myTableManager.TableInstance = myTable
  
  End Sub
  </code></pre>
  
  <p>2) Class <code>Table</code> (with a predeclared id set to true using <a href="http://rubberduckvba.com/" rel="nofollow noreferrer">rubberduck</a>)</p>
  
  <pre><code>'@Folder("VBAProject")
  
  Option Explicit
  '@PredeclaredId
  
  Private Type TTable
      SourceTable As ListObject
  End Type
  
  Private this As TTable
  
  Private WithEvents listObjectParentSheet As Excel.Worksheet
  
  Public Event AddEvent()
  
  Public Property Get SourceTable() As ListObject
      Set SourceTable = this.SourceTable
  End Property
  
  Public Property Set SourceTable(ByVal value As ListObject)
      Set this.SourceTable = value
      Set listObjectParentSheet = value.Parent
  End Property
  
  Public Property Get Self() As Table
      Set Self = Me
  End Property
  
  Public Function Create(ByVal EvalSourceTable As ListObject) As Table
      With New Table
          Set .SourceTable = EvalSourceTable
          Set Create = .Self
      End With
  End Function
  
  Private Sub listObjectParentSheet_Change(ByVal Target As Range)
      If Not Intersect(Target, SourceTable.DataBodyRange) Is Nothing Then
          MsgBox listObjectParentSheet.Name &amp; " " &amp; Target.Address
          RaiseEvent AddEvent
      End If
  End Sub
  </code></pre>
  
  <p>3) Class <code>TableManager</code></p>
  
  <pre><code>Option Explicit
  
  Private WithEvents m_table As Table
  
  Public Property Get TableInstance() As Table
      Set TableInstance = m_table
  End Property
  
  Public Property Set TableInstance(ByRef tableObject As Table)
      Set m_table = tableObject
  End Property
  
  Private Sub m_table_AddEvent()
      MsgBox "Adding something"
  End Sub
  </code></pre>
  
  <hr>
  
  <p><strong>Question/issue:</strong></p>
  
  <p>I haven't figure out how to fire the "AddEvent" in the <code>TableManager</code> class. I know I have messed up some concepts of instantiating the classes, but I don't know what I am doing wrong.</p>
  
  <hr>
  
  <p><strong>Expected result:</strong></p>
  
  <p>When user changes any cell of the listobject, show the message box "Adding something" when the <code>AddEvent</code> is raised</p>
  
  <hr>
  
  <p>Any help would be really appreciated.</p>
  
  <p><strong>EDIT #2</strong></p>
  
  <p>Final code thanks to Mat's answer:</p>
  
  <p>Sheet: <code>Sheet1</code>:</p>
  
  <pre><code>Private Sub Worksheet_Activate()
      With TableManager
          Set .TableEvents = Table.Create(Sheet1.ListObjects(1))
      End With
  End Sub
  </code></pre>
  
  <p>Module: <code>ListObjectUtilities</code> </p>
  
  <pre><code>Option Explicit
  
  Public Function GetCellRow(ByVal EvalTable As ListObject, ByVal EvalCell As Range) As Long
  
      If Intersect(EvalCell, EvalTable.DataBodyRange) Is Nothing Then Exit Function
  
      GetCellRow = EvalCell.Row - EvalTable.HeaderRowRange.Row
  
  End Function
  
  Public Function GetCellColumn(ByVal EvalTable As ListObject, ByVal EvalCell As Range) As Long
  
      If Intersect(EvalCell, EvalTable.DataBodyRange) Is Nothing Then Exit Function
  
      GetCellColumn = EvalCell.Column - EvalTable.HeaderRowRange.Column + 1
  
  End Function
  </code></pre>
  
  <p>Class: <code>ITable</code></p>
  
  <pre><code>Option Explicit
  
  Public Property Get SourceTable() As ListObject
  End Property
  </code></pre>
  
  <p>Class: <code>Table</code></p>
  
  <pre><code>'@Folder("VBAProject")
  '@PredeclaredId
  Option Explicit
  
  Private WithEvents TableSheet As Excel.Worksheet
  
  Private Type TTable
      SourceTable As ListObject
      LastRowCount As Long
      LastColumnCount As Long
  End Type
  
  Private this As TTable
  
  Public Event Changed(ByVal cell As Range)
  Public Event AddedNewRow(ByVal newRow As ListRow)
  Public Event AddedNewColumn(ByVal newColumn As ListColumn)
  
  Implements ITable
  
  Public Function Create(ByVal Source As ListObject) As ITable
      With New Table
          Set .SourceTable = Source
          Set Create = .Self
      End With
  End Function
  
  Public Property Get Self() As Table
      Set Self = Me
  End Property
  
  Public Property Get SourceTable() As ListObject
      Set SourceTable = this.SourceTable
  End Property
  
  Public Property Set SourceTable(ByVal value As ListObject)
      ThrowIfSet this.SourceTable
      ThrowIfNothing value
      Set TableSheet = value.Parent
      Set this.SourceTable = value
      Resize
  End Property
  
  Friend Sub OnChanged(ByVal Target As Range)
      RaiseEvent Changed(Target)
  End Sub
  
  Friend Sub OnAddedNewRow(ByVal newRow As ListRow)
      RaiseEvent AddedNewRow(newRow)
  End Sub
  
  Friend Sub OnAddedNewColumn(ByVal newColumn As ListColumn)
      RaiseEvent AddedNewColumn(newColumn)
  End Sub
  
  Private Sub ThrowIfNothing(ByVal Target As Object)
      If Target Is Nothing Then Err.Raise 5, TypeName(Me), "Argument cannot be a null reference."
  End Sub
  
  Private Sub ThrowIfSet(ByVal Target As Object)
      If Not Target Is Nothing Then Err.Raise 5, TypeName(Me), "This reference is already set."
  End Sub
  
  Private Sub Resize()
      With this.SourceTable
          this.LastRowCount = .ListRows.Count
          this.LastColumnCount = .ListColumns.Count
      End With
  End Sub
  
  Private Sub TableSheet_Change(ByVal Target As Range)
  
      If Intersect(Target, SourceTable.DataBodyRange) Is Nothing Then Exit Sub
  
      Select Case True
      Case this.SourceTable.DataBodyRange.Columns.Count &gt; this.LastColumnCount
          OnAddedNewColumn SourceTable.ListColumns(ListObjectUtilities.GetCellColumn(this.SourceTable, Target))
      Case this.SourceTable.DataBodyRange.Rows.Count &gt; this.LastRowCount
          OnAddedNewRow SourceTable.ListRows(ListObjectUtilities.GetCellRow(this.SourceTable, Target))
      Case Else
          OnChanged Target
      End Select
      Resize
  End Sub
  
  Private Property Get ITable_SourceTable() As ListObject
      Set ITable_SourceTable = this.SourceTable
  End Property
  </code></pre>
  
  <p>Class: <code>TableManager</code></p>
  
  <pre><code>'@Folder("VBAProject")
  '@PredeclaredId
  Option Explicit
  Private WithEvents MyTable As Table
  
  Public Property Get TableEvents() As Table
      Set TableEvents = MyTable
  End Property
  
  Public Property Set TableEvents(ByVal value As Table)
      Set MyTable = value
  End Property
  
  Private Sub MyTable_AddedNewColumn(ByVal newColumn As ListColumn)
      MsgBox "Added new column " &amp; newColumn.Range.Column
  End Sub
  
  Private Sub MyTable_AddedNewRow(ByVal newRow As ListRow)
      MsgBox "Added new row " &amp; newRow.Range.Row
  End Sub
  
  Private Sub MyTable_Changed(ByVal cell As Range)
      MsgBox "Changed " &amp; cell.Address
  End Sub
  </code></pre>
  
  <p><a href="https://1drv.ms/x/s!ArAKssDW3T7wnL1MpifPKsQQayr7fQ?e=EuofSs" rel="nofollow noreferrer">Sample file</a></p>