Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
查看: 25938|回复: 23

[分享] WithEvents关键字的浅显理解

[复制链接]
发表于 2011-4-6 07:25 | 显示全部楼层 |阅读模式
本帖最后由 wbzxz 于 2011-4-16 09:22 编辑

关于WithEvents关键字,VBA的帮助非常简单,虽然翻阅了不少资料,但是对WithEvents的理解还是似懂非懂,理解的很不透彻。在这里我仅仅把这些天来的学习心得与大家分享,抛砖引玉,如果您对WithEvents有深层次的理解,也请您一同分享,向您学习。
废话少说,言归正传。


1.WithEvents关键字用于哪些语句?
通过VBA帮助,我们知道WithEvents只用于声明变量的语句:

WithEvents 关键字用于下列上下文:
Dim 语句
Private 语句
Public 语句
这三个语句都是用来声明变量的,我们知道了WithEvents关键字肯定是与定义变量有关。

2.WithEvents关键字是干什么用的?
WithEvents,从这个单词本身上看,应该是“和事件有关”的意思(嘿嘿,我猜的啊)。一提到事件,我们就会联想到对象;既然WithEvents关键字用于Dim,Private,Public语句,那就肯定与变量有关系;以上两点结合到一起,肯定WithEvents关键字是和对象变量有关系啦。
我的理解是这样的:
当你需要使用某个对象的事件时,定义对象变量的时候,就要用到WithEvents关键字。
举个例子:
Dim app as Application无法使用application对象事件
Dim WithEvents app as Application可以使用application对象事件



3.使用 WithEvents 关键字的限制条件:  
(1)WithEvents 变量不能是派生对象变量。也就是说,不能把它声明为 As Object(当声明该变量时必须指定类名)。
举个例子
错误的写法:Dim WithEvents app as Object
正确的写法:Dim WithEvents app as Application

(2)不能把 WithEvents 变量声明为 As New。必须明确地创建事件源对象,并将它赋给 WithEvents 变量。
举个例子
假设已经定义了一个叫做MyClass的类模块
错误的写法:  Dim WithEvents cls as New MyClass
正确的写法:Dim WithEvents cls as MyClass
                   Set cls=New MyClass

(3)不能在标准模块中声明 WithEvents 变量。只能在类模块、窗体模块以及其它定义类的模块中声明。
VBA工程中包含的模块,除了标准模块,剩下的都可以看做是类模块(包括窗体模块,ThisWorkbook,Sheet,类模块等等)。所以说我们只要记住,在标准模块中,不能使用WithEvents关键字就行。

(4)虽然WithEvents是Dim,Public,Private语句的关键字,但是,一定要记住,不要在过程里面中用WithEvents关键字进行对象变量的声明,因为微软绝对不会同意,呵呵。


excel精英培训的微信平台,每天都会发送excel学习教程和资料。扫一扫明天就可以收到新教程
 楼主| 发表于 2011-4-6 07:27 | 显示全部楼层
本帖最后由 wbzxz 于 2011-4-7 00:07 编辑

4.WithEvents应用范例1一显式使用对象事件
我们知道,Excel可以监视不少对象的事件,如Workbook,Worksheet,UserFrom等等,通常输入事件过程的代码时,首先从代码编辑器的左边下拉列表中选择对象,然后从代码编辑器右边下拉列表中选择事件,如下图所示。 image001.png

但是有些对象,如Application对象,是无法这样输入事件过程的,只有使用了WithEvents定义了对象变量,然后将Application对象引用赋值给对象变量之后,才可以像上图一样使用。下面我们举个例子来说明一下。

例子说明:利用Application的WindowResize事件,当我们调整工作薄窗口大小的时候,弹出对话框。

代码编写位置:我们在Sheet1文档模块中编写(你也可以在Sheet2,Sheet3,ThisWorkbook等模块中编写,效果是一样的)

编写过程:
(1)声明变量,定义对象变量app:
Private WithEvents app As Application
(2)声明过程,将Application对象的引用赋值给app:
Sub test()  Set app = ApplicationEnd Sub
这个时候,我们就可以通过代码编辑器的左右下拉列表框选择Application对象的事件过程啦(不过是以app对象变量的形式出现的),如下图所示:
image003.png

(3)编写事件过程代码:
Private Sub
app_WindowResize(ByVal Wb As Workbook, ByVal Wn As Window)  MsgBox "你改变了工作薄窗口的大小"
End Sub

运行方法:运行test过程,然后改变工作簿的大小,就会弹出提示框。

代码:
  1. Option Explicit

  2. Private WithEvents app As Application ‘ 定义对象变量

  3. Sub test()
  4.   Set app = Application ‘将Application对象的引用赋值给对象变量app:
  5. End Sub

  6. ‘编写事件过程
  7. Private Sub app_WindowResize(ByVal Wb As Workbook, ByVal Wn As Window)
  8.   MsgBox "你改变了工作薄窗口的大小"
  9. End Sub
复制代码

显式使用对象事件.rar (7.92 KB, 下载次数: 266)
回复

使用道具 举报

 楼主| 发表于 2011-4-6 07:28 | 显示全部楼层
本帖最后由 wbzxz 于 2011-4-7 00:10 编辑

5. WithEvents应用范例2一为多个模块编写通用事件

例子说明:建立一个窗体,里面放了四个CommandButton控件,点击控件,弹出CommandButton的Catpion名,本来应该为每个CommandButton事件编写一个事件过程,现在只要编写一个事件过程即可。


代码分为两部分,一个是窗体模块UserForm1的代码,一个是类模块MyClass的代码:


(1)类模块代码与解释(类模块名:MyClass)
  1. Option Explicit
  2. ‘ 定义CommandButton的对象变量cmd,使用WithEvents关键字,用来引用CommandButton对象的事件,cmd变量作为MyClass的属性
  3. Public WithEvents cmd As CommandButton

  4. ‘ 为cmd对象编写Click事件过程(这里就是编写的通用事件)
  5. Private Sub cmd_Click()
  6.   MsgBox cmd.Caption  ‘弹出对话框,显示cmd对象的Caption名
  7. End Sub
复制代码


(2)窗体模块代码与解释(窗体名UserForm1)
  1. Option Explicit
  2. ‘ 定义MyClass类的数组对象变量
  3. Dim cls(1 To 4) As New MyClass

  4. ‘ 在窗体初始化中编写代码
  5. Private Sub UserForm_Initialize()
  6.   Dim i As Integer
  7.   Dim ct As MSForms.Control  ‘ 定义MSForms.Control类的对象变量ct
  8.   i = 1

  9. ‘ 利用Controls集合,遍历窗体中每个控件
  10.   For Each ct In Me.Controls ‘在这里,me代表窗体对象UserForm1   
复制代码



回复

使用道具 举报

 楼主| 发表于 2011-4-6 07:30 | 显示全部楼层
本帖最后由 wbzxz 于 2011-4-7 00:14 编辑


6. WithEvents应用范例2—在一个对象中为另一个对象编写事件


这一个实例个人感觉有些牵强,因为我也不知道什么地方会用到他。所以我也不解释太多,只贴出代码与大家共享。


例子说明:在Sheet2模块中编写Sheet1的Activate事件,运行Sheet2里面的过程后,再激活Sheet1表,弹出Msgbox消息框。


代码与简单解释如下(在Sheet2表中):


Option Explicit
‘ 定义WorkSheet类的对象变量sh1,利用WithEvents关键字,可以引用WorkSheet对象的事件
Dim WithEvents sh1 As Worksheet

‘ 编写一个过程,将对Sheet1对象的引用赋值给对象变量Sh1,因为定义WithEvents的时候使用了WithEvents关键字,所以这个过程编写完后,在代码编辑器的对象和事件下拉列表框中可以找到Sheet1的事件
Sub test()
  Set sh1 = Sheet1
End Sub

‘为Sheet1对象的Activate事件过程编写代码
Private Sub sh1_Activate()
  MsgBox "我是通过Sheet2表编写的事件激活的"
End Sub

我们可以看出来,这些代码都是写在了Sheet2模块中,但确实实现了为Sheet1对象编写事件过程的功能。

在一个对象中为另一个对象编写事件.rar (7.88 KB, 下载次数: 112)
回复

使用道具 举报

发表于 2011-4-6 18:04 | 显示全部楼层
谢谢分享  
回复

使用道具 举报

 楼主| 发表于 2011-4-7 00:13 | 显示全部楼层
本帖最后由 wbzxz 于 2011-4-7 00:15 编辑

心得更新完毕,请大家指点,谢谢。
回复

使用道具 举报

发表于 2011-4-7 09:46 | 显示全部楼层
可以打包下载啊.
回复

使用道具 举报

 楼主| 发表于 2011-4-16 09:23 | 显示全部楼层
稍微更新了一点东西。
回复

使用道具 举报

发表于 2012-3-27 23:12 | 显示全部楼层
来学习下               
回复

使用道具 举报

发表于 2012-12-14 11:20 | 显示全部楼层
学习了,收获不少,谢谢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-4-25 10:28 , Processed in 0.287044 second(s), 9 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表