Home » excel » excel – How to end infinite "change" loop in VBA

excel – How to end infinite "change" loop in VBA

Posted by: admin March 9, 2020 Leave a comment

Questions:

I have a problem with visual basic. I want to make a macro/function that will multiply a number I enter by 3 and give a result in the same cell. I tried something like this:

Sub Worksheet_Change(ByVal Target As Range)
    If Target.Address = "$Q$21" Then
        Target.Value = Target.Value * 3
    End If
End Sub

but it doesn’t work – I’m getting results like “xE25” because it keeps multiplying.

I’d like it to stop after first iteration or work only when I press “enter” not with every change in the cell.
It’s quite easy to put a result in different cell, but it’s not my point.

—–Edit:
I edited “If” line to :
If (Target.Column = 5 Or Target.Column = 11 Or Target.Column = 17 Or Target.Column = 23) And (Target.Row >= 19 And Target.Row <= 24) And Target.Value <> "" Then
so it would work on all cells that I need. After that, the best solution is the way given by @Chrismas007, because it doesn’t prompt an error when trying to delete data in few cells at once.

How to&Answers:

With error handling to ensure .EnableEvents goes back to True:

Sub Worksheet_Change(ByVal Target As Range)
    On Error GoTo CleanExit
    If Target.Address = "$Q$21" Then
        Application.EnableEvents = False
        Target.Value = Target.Value * 3
    End If
CleanExit:
    Application.EnableEvents = True
    On Error GoTo 0
End Sub

Answer:

When a Worksheet_Change event macro changes a value, you need to set Application.EnableEvents to false or risk triggering another event and having the macro run on top of itself.

Sub Worksheet_Change(ByVal Target As Range)
    If Target.Address = "$Q$21" Then
        Application.EnableEvents = False
        Target.Value = Target.Value * 3
        Application.EnableEvents = True
    End If
End Sub

While I would usually involve some error control in order that the .EnableEvents was always reset to true, the above should get you started.

Answer:

You need to disable events to prevent recursion:

Sub Worksheet_Change(ByVal Target As Range)
    If Target.Address = "$Q$21" Then
        application.enableevents = false
        Target.Value = Target.Value * 3
        application.enableevents = true
    End If
End Sub

Just as an alternative, you can also use your own variable rather than tinkering with EnableEvents, though it will mean your code responds twice even though it doesn’t actually do anything the second time round:

Dim bSkipEvents as Boolean
    Sub Worksheet_Change(ByVal Target As Range)
        If bSkipEvents then exit sub
        If Target.Address = "$Q$21" Then
            bSkipEvents = True
            Target.Value = Target.Value * 3
            bSkipEvents = False
        End If
    End Sub

This is also the sort of approach you need with userforms and most events for activex controls on worksheets.