|
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件 ★ 免费下载 ★ ★ 使用帮助★
本帖最后由 hehex 于 2012-10-24 22:27 编辑
经过反复单步追踪代码,我基本上懂得激发事件的过程了:
Option Explicit
Sub Edit()
Dim var As String
Let var = "wjh"
Range("C6").Value = var
End Sub
Private Sub Worksheet_Change(ByVal Target As Range) 【代码20】
'=〉这里添加一句代码
debug.print Target.value ' 意思是在立即窗口打印引发事件的Target 对象的值
If Application.Intersect(Target, Range("C3:C65536")) Is Nothing Or Target.Count > 1 Then 【代码1】
Exit Sub 【代码2】
End If 【代码3】
Dim i As Integer
i = 3
Do While Cells(i, "I").Value <> "" 【代码4】
If UCase(Target.Value) = Cells(i, "I").Value Then
Rem Application.EnableEvents = False
Target.Value = Cells(i, "I").Offset(0, 1).Value 【代码5】
Target.Offset(0, -1).Value = Date 【代码6】
Target.Offset(0, 1) = Cells(i, "I").Offset(0, 2).Value 【代码7】
Target.Offset(0, 2) = Cells(i, "I").Offset(0, 3).Value 【代码8】
Target.Offset(0, 3).Select 【代码9】
Application.EnableEvents = True 【代码10】
Exit Sub 【代码11】
End If
i = i + 1
Loop
End Sub【代码21】
Okay, 我们来单步执行这段代码,从Sub edit() 开始,第一次激活事件的时候,你会发现 Target.value="wjh",这点也是我们需要的,就是所谓的助记符。这次激活事件我们称为事件A,一路往下执行,
到代码5这里,因为Rem Application.EnableEvents = False, 所以代码5激活了事件。这次激活我们称为事件B激活事件后,立刻返回了事件sub 的开头就是
Private Sub Worksheet_Change(ByVal Target As Range) 【代码20】 这里,跟踪Target.value 里面的值是"文具盒",因为是更新的值在C 列,符合条件所以事件开头的if 判断不会拦截。
所以代码继续执行到do while 循环里的第2个if 判断,由于"文具盒" 是全称不是助记符,因此每次if 判断都是False, 直接执行End if 直到循环结束到事件结束。事件B 结束了。
戏骨来了,那么你的问题是为什么程序没有到此结束呢,因为事件A还没有结束,还要继续执行,所以执行代码6,代码6再次激活了事件,我们称为事件C,激活事件C 的Target.value 是当前日期,这个不在C 列在B 列,因此被事件的第一个IF 所拦截执行Exit Sub 事件C结束了,但是事件A 还没有结束,还要继续执行下一句就是代码7,代码7激活了事件D,代码8激活事件E 这2个都和事件C 是完全一样的,当事件E 结束的时候,事件A 还没有结束,但是后面的语句不会再激活事件了,就一路执行下去直到事件A 结束,再返回Sub edit() 中,赋值的下一条语句直到程序结束。
由上面分析可以知道,VBA 的事件激活是先激活事件程序,在激活事件结束之后再返回激活点的下一条语句继续执行。这个有点像堆栈,后进先出。
感谢楼主的深入探索精神,由此也纠正了我以前的错误认识。{:soso_e117:}{:soso_e120:}{:soso_e182:}
|
评分
-
1
查看全部评分
-
|