' 28'超出堆栈空间。 Worksheet_Change和Application.ScreenUpdating

时间:2014-04-21 17:49:58

标签: excel vba excel-vba stack-overflow

提前感谢您提供的任何清晰度。

在包含许多模块和工作表的Excel工作簿中,在SHEET2的VBA代码的底部,有一个子例程:

Private Sub Worksheet_Change(ByVal Target As Range)

Dim TargetCells As Range

Set TargetCells = Range("B1000:B1029")

If Not Application.Intersect(TargetCells, Range(Target.Address)) Is Nothing Then
   Call SpecificSubRoutine
End If

End Sub

我对此代码的理解是,它会监视整个工作表以进行任何更改。如果ANYTHING在工作表上的任何位置发生更改,则会运行If语句。如果对工作表所做的任何更改都发生在指定的TargetCells范围之外,则If语句将失败,但是此Sub仍然会在工作表上每次更改ANYTHING时尝试验证If语句。

现在,您可能会猜到我的问题是堆栈溢出。 (运行时错误'28':超出堆栈空间)

每当Worksheet_Change Sub运行时,如果对工作表的更改是在TargetCells范围内进行的,则会调用填充单元格的SpecificSubRoutine,从而触发Worksheet_Change每次SpecificSubRoutine填充任何单元格的子。 (SpecificSubRoutine也调用不同的模块,当然会填充单元格,当然会触发Worksheet_Change Sub)

不太好。

此外,整个应用程序中的大多数子例程都包含在Application.ScreenUpdating = False / Application.ScreenUpdating = True中,我错误地认为这会限制Worksheet_Change被调用一次的次数,紧接在Application.ScreenUpdating = True / SpecificSubRoutine之后{1}}跑。

重要提示: TargetCells或其调用的子程序都不会填充Worksheet_Change范围内的单元格。我不是那个暗淡的......

以下是我的问题:

  1. 有没有办法缩小触发TargetCells Sub的范围,以便只有Application.ScreenUpdating范围内的更改会触发它? (而不是在工作表中的任何地方进行更改)
  2. 有没有办法做我错误认为Worksheet_Change会做的事情? (在一次批量更新中更改工作表,而不是几乎每一步触发更改)
  3. 另外,作为一个额外的好奇心,有没有办法让End观看2个特定范围(而不是整个表?)知道如何做到这一点将是最重要的,并可能解决所有问题在这张表上。
  4. 我的直觉是在SpecificSubRoutine的最后一部分添加一个Worksheet_Change,或者在它调用的任何/所有子程序的末尾添加Application.ScreenUpdating,但我不确定这会绕过循环遍历{{1}}多次,因为{{1}}没有像我想象的那样批量更新。

    想法?

1 个答案:

答案 0 :(得分:1)

第1部分:否 - 事件处理程序响应工作表上的所有更改:任何对响应更改的过滤都必须在处理程序本身中进行。

第2部分:@simoco回答

第3部分(并纳入了simoco的建议):

Private Sub Worksheet_Change(ByVal Target As Range)

    Application.EnableEvents=False

    If Not Application.Intersect(Me.Range("B1000:B1029"), Target) Is Nothing Then
       Call SpecificSubRoutine
    End If

    If Not Application.Intersect(Me.Range("D1000:D1029"), Target) Is Nothing Then
       Call SomeOtherSpecificSubRoutine
    End If

    Application.EnableEvents=True

End Sub