44

当我在 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()事件时遇到过类似的崩溃,任何人都可以指出正确的方向来解决这个问题吗?

4

3 回答 3

81

我在使用时推荐这个Worksheet_Change

  1. 不需要工作表名称。在工作表代码模块中,非限定范围引用引用该工作表。也就是说,使用Me限定词更清楚。如果您尝试使用另一张工作表,请使用该工作表限定范围引用。

  2. 每当您使用事件时,如果您将数据写入任何单元格Worksheet_Change,请始终切换事件。Off这是必需的,以便代码不会重新触发 Change 事件,并进入可能的无限循环

  3. 每当您关闭事件时,请使用错误处理将其重新打开,否则如果出现错误,代码将不会在下次运行。

尝试这个

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.CountLong值可能会在 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. 例如,如果 Cell 发生更改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再次使用。例如,如果 range 发生更改A1:A10,则以下代码将触发

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
于 2012-12-13T14:11:54.980 回答
14

Excel 崩溃了,而不是 VBA 函数。
事件未被禁用,调用堆栈被 OnChange 事件的无限循环填充。
一个有助于发现此类错误的小建议:在事件的第一行设置一个断点,然后按 F8 逐步执行它。

于 2013-01-08T06:28:43.710 回答
0

这个解决方案也很好:

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
于 2018-08-17T17:52:54.023 回答