是否有方法以编程方式清除EXCEL VBA事件队列?在EXCEL VBA中,当一个工作表单元格被更改,然后用户按ENTER键提交单元格编辑时,在工作表级别会发生两个事件。它们是:•私有子Worksheet_Change(ByVal目标范围)•私有子Worksheet_SelectionChange(ByVal目标作为范围)
不可避免地,这两个事件被记录在一个队列中,并将优先级赋予Worksheet_Change,然后执行Worksheet_SelectionChange。由于单元格内容已更改,将触发Change事件。然后触发SelectionChange事件,因为用户按下ENTER键,将选择更改为已编辑单元格下的单元格。这两个步骤生成两个事件。
我编写了这段代码,用于捕获特定单元格中的更改,并且我需要完全避免以下事件,Worksheet_SelectionChange,以便在Worksheet_Change子终止后运行。这是因为在我的SelectionChange子中还有其他重要的工作要完成,当单元格内容被修改时,它们不能干预。
当然,必须有一种方法来防止SelectionChange发生。我试图找到某种VBA函数,可以在Worksheet_Change子内清空EXCEL事件队列列表。目前似乎不存在。我也试着利用应用程序。EnableEvents = False,但这只会在两个事件都被添加到队列后生效,这不会阻止等待SelectionChange事件在Change事件之后执行。
问题:是否有办法以编程方式清除EXCEL VBA事件队列?
类似于Application的某种函数。clearventqueue,以防止任何后续未实现事件的执行。这个函数可以在Change子线程中调用,它将阻止任何其他等待事件的执行。如何在VBA中实现这样的功能?
Dim NewLocation As Range
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
Set NewLocation = Target.Offset(0, 1) ' At this location a work is written in the cell
NewLocation.Select ' Here the selection is changed and EXCEL trigger a third event, SelectionChange
Debug.Print "still in change event", NewLocation.Row, Target.Value
Application.EnableEvents = True
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Debug.Print "selectionchange event", Target.Row, Target.Value
End Sub
这段代码将显示,当用户向单元格输入一个新值时,将会发生3个事件。
- 第一个SelectionChange事件引起的行:NewLocation。选择
- 第二个Change事件,因为用户更改了单元格并按ENTER
- 第三个另一个选择由用户按ENTER引起的更改,以便焦点移到单元格下面(只是暂时的,直到代码命令NewLocation.Select.
我试图避免执行第三个SelectionChange。这是不可避免的,因为使用应用程序。EnableEvents = False只能在EXCEL捕获第一个ENTER步骤后生效。所以当EnagleEvents设置为OFF时,只会发生两个事件。理想情况下,我甚至会要求取消之前的SelectionChange事件。
Application.EnableEvents = False
NewLocation.Select
Application.EnableEvents = True
将阻止Select
触发另一个事件
编辑:似乎没有任何方法来清除事件队列,所以你能做的最好的可能是忽略Selection_Change
事件后立即发生的Change
事件处理程序退出:
Option Explicit
Dim NewLocation As Range
Dim tChange As Double
Private Sub Worksheet_Change(ByVal Target As Range)
Set NewLocation = Target.Offset(0, 1) ' At this location a work is written in the cell
Application.EnableEvents = False
NewLocation.Select
Application.EnableEvents = True
Debug.Print "still in change event", NewLocation.Row, Target.Value
tChange = Timer 'note exit time
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Timer - tChange > 0.05 Then 'is this immediatley following exit from a Change event?
Debug.Print "selectionchange event", Target.Row, Target.Value, Timer - tChange
Else
Debug.Print "Skipped handling selection change"
End If
End Sub