Search code examples
excelvbaformula

How can I run VBA code each time a cell gets its value changed by a formula?


How can I run a VBA function each time a cell gets its value changed by a formula?

I've managed to run code when a cell gets its value changed by the user, but it doesn't work when the value is changed due to a formula referencing another cell.


Solution

  • If I have a formula in cell A1 (e.g. = B1 * C1) and I want to run some VBA code each time A1 changes due to updates to either cell B1 or C1 then I can use the following:

    Private Sub Worksheet_Calculate()
        Dim target As Range
        Set target = Range("A1")
    
        If Not Intersect(target, Range("A1")) Is Nothing Then
        //Run my VBA code
        End If
    End Sub
    

    Update

    As far as I know the problem with Worksheet_Calculate is that it fires for all cells containing formulae on the spreadsheet and you cannot determine which cell has been re-calculated (i.e. Worksheet_Calculate does not provide a Target object)

    To get around this, if you have a bunch of formulas in column A and you want to identify which one has updated and add a comment to that specific cell then I think the following code will achieve that:

    Private Sub Worksheet_Change(ByVal Target As Range)
        Dim updatedCell As Range
        Set updatedCell = Range(Target.Dependents.Address)
    
        If Not Intersect(updatedCell, Range("A:A")) Is Nothing Then
           updatedCell.AddComment ("My Comments")
        End If
    
    End Sub
    

    To explain, for a formula to update, one of the input cells into that formula must change e.g. if formula in A1 is =B1 * C1 then either B1 or C1 must change to update A1.

    We can use the Worksheet_Change event to detect a cell change on the s/sheet and then use Excel's auditing functionality to trace the dependents e.g. cell A1 is dependent on both B1 and C1 and, in this instance, the code Target.Dependents.Address would return $A$1 for any change to B1 or C1.

    Given this, all we now need to do is to check if the dependent address is in column A (using Intersect). If it is in Column A we can then add comments to the appropriate cell.

    Note that this only works for adding comments once only into a cell. If you want to continue to overwrite comments in the same cell you would need to modify the code to check for the existance of comments first and then delete as required.