问题
thanks in advance for any clarity you can offer.
In an Excel Workbook with many modules and worksheets, at the bottom of the VBA code for SHEET2, there is this Subroutine:
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
My understanding of this code is that it watches the entire sheet for ANY changes. If ANYTHING is changed, anywhere on the sheet, it runs the If statement. The If statement fails in the event that any of the changes made to the sheet take place outside of the specified TargetCells
range, but this Sub still tries to validate the If statement EVERY time ANYTHING is changed on the sheet.
Now, you might be able to guess that my problem is some stack overflow. (Run-time error '28': Out of Stack Space)
Whenever the Worksheet_Change
Sub runs, if the changes to the sheet were made inside of the TargetCells
range, it calls SpecificSubRoutine
which populates cells, which triggers the Worksheet_Change
Sub for every time SpecificSubRoutine
populates ANY cell. (SpecificSubRoutine
also calls different modules, which of course populate cells, which of course trigger the Worksheet_Change
Sub)
Not so good.
Also, most of the subroutines throughout the application are wrapped in Application.ScreenUpdating = False
/ Application.ScreenUpdating = True
, which I mistakenly thought would limit the number of times Worksheet_Change
is called to once, immediately after Application.ScreenUpdating = True
runs.
NOTE OF IMPORTANCE: Neither SpecificSubRoutine
nor any of the Subroutines called by it populate cells in the TargetCells
range. I'm not quite that dim...
Here are my questions:
- Is there a way to narrow the scope of what triggers the
Worksheet_Change
Sub, so that only changes in theTargetCells
range triggers it? (instead of changes anywhere in the sheet) - Is there a way to do what I mistakenly thought that
Application.ScreenUpdating
would do? (make changes to the sheet all in one bulk update, as opposed to triggering a change with nearly every step) - Also, as an extra curiosity, is there a way to have
Worksheet_Change
watch 2 specific ranges (instead of the whole sheet?) Knowing how to do this would be paramount, and would likely solve all of the problems on this sheet.
My intuition is to add an End
to the last part of SpecificSubRoutine
, or to the end of any/all of the Subroutines called by it, but I'm just not sure this will circumvent the looping through Worksheet_Change
multiple times, since Application.ScreenUpdating
doesn't bulk update like I thought.
Ideas?
回答1:
Part 1: No - the event handler responds to all changes on the sheet: any filtering in how you respond to that change must occur in the handler itself.
Part 2: answered by @simoco
Part 3 (and incorporating simoco's suggestion):
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
来源:https://stackoverflow.com/questions/23202751/28-out-of-stack-space-worksheet-change-and-application-screenupdating