为什么MS Excel在Worksheet_Change Sub过程中崩溃并关闭?

pdsfdshx  于 2023-01-03  发布在  其他
关注(0)|答案(3)|浏览(208)

当我在Excel工作表上运行VBA代码时,我遇到了Excel崩溃的问题。
我尝试在工作表更改时添加以下公式:

Private Sub Worksheet_Change(ByVal Target As Range)
   Worksheets("testpage").Range("A1:A8").Formula = "=B1+C1"
End Sub

运行此代码时,我收到一条消息,提示“excel遇到问题,需要关闭”,然后excel关闭。

如果我运行Worksheet_Activate()过程中的代码,它会正常工作,不会崩溃

Private Sub Worksheet_Activate()
   Worksheets("testpage").Range("A1:A8").Formula = "=B1+C1"
End Sub

但是我真的需要它在Worksheet_Change()过程中工作。
有人在使用Worksheet_Change()事件时遇到过类似的崩溃吗?有人能指出解决此问题的正确方向吗?

fykwrbwg

fykwrbwg1#

我建议在使用Worksheet_Change时这样做
1.您不需要工作表名称。在工作表代码模块中,未限定的范围引用指的是该工作表。也就是说,使用Me限定符会更清楚。如果您尝试使用另一个工作表,则使用该工作表限定范围引用。
1.无论何时使用Worksheet_Change事件,如果要向任何单元格写入数据,请始终切换Off事件。这是必需的,以免代码重新触发Change事件,从而进入可能的无限循环
1.每当您关闭事件时,请使用错误处理将其重新打开,否则如果您遇到错误,代码下次将不会运行。
试试这个

Private Sub Worksheet_Change(ByVal Target As Range)
    On Error GoTo Whoa
    
    Application.EnableEvents = False
    
    Me.Range("A1:A8").Formula = "=B1+C1"
    
Letscontinue:
    Application.EnableEvents = True
    Exit Sub
Whoa:
    MsgBox Err.Description
    Resume Letscontinue
End Sub

在处理此事件时,您可能还需要了解一些其他事项。
如果您想确保代码在多个单元格被更改时不会运行,则添加一个小检查

Private Sub Worksheet_Change(ByVal Target As Range)
    '~~> For Excel 2003
    If Target.Cells.Count > 1 Then Exit Sub
    
    '
    '~~> Rest of code
    '
End Sub

CountLarge是在Excel 2007中引入的,因为Target.Cells.Count返回的Long值可能会在Excel 2007中出错,因为总单元格数增加。

Private Sub Worksheet_Change(ByVal Target As Range)
    '~~> For Excel 2007
    If Target.Cells.CountLarge > 1 Then Exit Sub
    '
    '~~> Rest of code
    '
End Sub

要使用所有已更改的单元格,请使用以下代码

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim aCell As Range
    
    For Each aCell In Target.Cells
        With aCell
            '~~> Do Something
        End With
    Next
End Sub

要检测特定单元格中的更改,请使用Intersect。例如,如果单元格A1中发生更改,则将触发以下代码

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Me.Range("A1")) Is Nothing Then
        MsgBox "Cell A1 was changed"
        '~~> Your code here
    End If
End Sub

要检测特定范围集合中的更改,请再次使用Intersect

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Me.Range("A1:A10")) Is Nothing Then
        MsgBox "one or more Cells in A1:A10 range was changed"
        '~~> Your code here
    End If
End Sub
    • 注**:如果您之前收到错误并进行了上述更改,并且如果代码仍然不起作用,则可能是事件尚未重置。在Immediate Window中,键入Application.EnableEvents = True并按Enter键。这会将其重置为True。如果没有看到Immediate Window,然后按快捷键Ctl + G启动Immediate Window

bmvo0sr5

bmvo0sr52#

Excel崩溃了,而不是VBA函数。
事件未禁用,调用堆栈由OnChange事件的无限循环填充。
一个小建议,帮助找到这种类型的错误:在事件的第一行设置断点,然后按F8键逐步执行。

ljo96ir5

ljo96ir53#

这个解决方案也很好:

Option Explicit
Private Busy As Boolean
Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Busy Then
        Busy = True
        Range("A1:A8").Formula = "=B1+C1"
        Busy = False
    End If
End Sub

相关问题