如何结束 VBA 中的无限 "change" 循环

How to end infinite "change" loop in VBA

我对 Visual Basic 有疑问。我想制作一个 macro/function ,它将我输入的数字乘以 3 并在同一个单元格中给出结果。我试过这样的事情:

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

但它不起作用 - 我得到了像 "xE25" 这样的结果,因为它不断增加。

我希望它在第一次迭代后停止,或者仅在我按下 "enter" 时才工作,而不是在单元格中进行每次更改。
将结果放在不同的单元格中很容易,但这不是我的重点。


-----编辑:
我将 "If" 行编辑为:
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
所以它适用于我需要的所有细胞。之后,最好的解决方案就是@Chrismas007给出的方式,因为它在尝试一次删除几个单元格中的数据时不会提示错误。

Worksheet_Change 事件宏更改值时,您需要将 Application.EnableEvents 设置为 false 否则可能会触发另一个事件并让宏 运行 在其自身之上。

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

虽然我通常会涉及一些错误控制,以便 .EnableEvents 始终重置为 true,但以上应该可以帮助您入门。

您需要禁用事件以防止递归:

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

作为替代方案,您也可以使用自己的变量而不是修改 EnableEvents,尽管这意味着您的代码会响应两次,即使它第二次实际上没有做任何事情:

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

对于工作表上的 ActiveX 控件,用户窗体和大多数事件也需要这种方法。

通过错误处理确保 .EnableEvents 返回到 True:

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