ImageVerifierCode 换一换
格式:DOC , 页数:34 ,大小:433.50KB ,
资源ID:5154349      下载积分:10 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.docduoduo.com/d-5154349.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录   微博登录 

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Excel VBA 类模块入门.doc)为本站会员(weiwoduzun)主动上传,道客多多仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知道客多多(发送邮件至docduoduo@163.com或直接QQ联系客服),我们立即给予删除!

Excel VBA 类模块入门.doc

1、Excel VBA 类模块入门教程示 例 一 示 例 二 集 合 示 例VBA 类:隐者的秘密 前言 写下这个题目,可能会让很多朋友疑惑,笔者先埋下一个关子,很快我会让您知道这个标题的寓意。 这份礼物送给现在想学习类知识或曾经学过但因为各种原因没有“修成正果”的朋友,我期望的结果是这篇文章后,您可以在类模块中像在标准模块中写代码一样熟练,我也期望不至于太乏味而使您没有耐心看完整篇文章,或者说期望您学习的过程是轻松愉悦的,但愿我可以做到。文章构划为 8 部分: 1什么是类 2为什么要学习类 3类的预备知识 4创建类属性 5创建类方法 6创建类事件 7一个完整的类实例 8未完的结尾 什么是类在我们

2、身边,相同或相似的物品无处不在,从生活用品,到工业产品,通常它们都是由同一个可以称为“模具”的东西生产出来。 理解类,一般要先从对象谈起,但由于从不同的角度,有不同的理解,从而也有不同的关于类的定义,本文不去探讨一个完整并且公认的类概念,在这一部分后,只要你有一个基本的判断并且在遇到时知道是类就可以了。在上面的这个例子中,一个“模具”就是一个“类”,而由它生产出的每一个产品,就是一个“对象”。看下面的 VBA 语句: Dim tx1 As Textbox 不用解释它的意思吧,这里我们用到一个类 Textbox 定义了一个对象 tx1,再来看: Dim tx1 As Textbox Dim tx

3、2 As Textbox 又定义了一个对象 tx2,如果你不嫌烦,我还可以继续下去。对象增加了,但 As 后的 Textbox 没有变,它可以无限制的使用下去。 类是一个隐者,上面 Textbox 是 VBA 已经给我们准备好的一个类,我们无法知道 VBA 是怎么准备的(它的真身被隐藏了),但我们可以知道对象 tx1 怎么用。VBA 把对对象的使用划分为三种,属性、方法和事件(后面预备知识我们再提)。 然而,Textbox 是一个类,仍然不是本文要说的类,因为它是 VBA 已经给我们准备好了的,我们要做的,只是知道如何使用它而已。本文要介绍的,是利用 VBA 已经给我们提供的资源,来构建我们自

4、己的类,姑且可称之为自定义类。这需要在 VBE 下,通过插入类模块,然后向类模块中写入代码来完成。这就是你常常听说的类,本文的主题就是这个包含代码的模块!通过这个模块,可以提供给我们一个和 VBA 提供给我们的诸如 Textbox 功能性质完全相同的类,然后,再由我们自己象使用 Textbox 一样使用! 类是一个隐者,她把自己藏在所有模块的最后,甚至在多数情况,她从不出场。现在,她挂着神秘的微笑,向你走来,你要拒绝吗为什么要学习类模块二、 类通常被认为是学习 VBA 的难点之一,之所以如此,因为相对于制造一个标准模块或用户窗体,我们可以找到的类的学习资源少之又少,甚至很多 VB 的书籍也只有

5、缪缪字语(在后面的预备知识,我们再提另一个重要的原因)。从技术角度上看,类的构建,不象窗体,VBA 的类也不象有些语言提供了可视的设计界面,感性上那样直接,隐者!她是不可视的设计,所有的构建都是通过在类模块中写代码来实现的。 1学习是一种兴趣的追求 俗语云:学的千千万,用的有几何?又曰:书到用时方恨少。林语堂先生将做学问划分为三重境界,第二重说“为伊消得人憔悴,衣带渐宽终不悔”,大多数朋友,包括本人,都不是专业程序员,学习程序只是一种兴趣和爱好,就好象有人喜欢修炼网游一样,对喜欢程序的人,不断地学习和提高,也是一种追求优秀的态度,并且乐意享受这个追求的过程。模块、控件、链接库和类构成软件工程开

6、发的四大技术,而类技术是控件和链接库技术的基础,我们不得不学。 2类有什么用 如你前面看到的我们使用 Textbox 类,类可以创建大量性质相近的对象,减轻我们的程序量,简洁代码并提高效率。 类定义后,在其它模块中使用时,我们就可以暂时忘记或不必考虑它内部复杂的细节,让我们变得轻松,VBA 虽然不能真正封装类的形式,但在这里,我们可以封装它的概念。 这并不是类的全部好处,其它的,留着朋友们用的时候慢慢体会吧。 类挂着神秘的微笑,已经走到你的大门口,开门迎接她吧,你还等什么?类的预备知识 广义上讲,所有 VBA 的知识,包括语句、函数以及为我们提供的标准类甚至第三方的资源都可以在类中被使用。本文

7、无法也不准备逐一探讨,这里只说一些最密切最基本的,但即使这样,笔者仍然不能把这些点的知识都写到,甚至因为对问题解释清晰或符合逻辑的需要,采用非规范的表述,对专门问题的全面理解,请读者注意参考有关标准帮助文档并加以甄别。 1从构建者的角度理解对象 上一回我们提到,类被认为是 VBA 难点还有一个原因,这就是我们的思想!VBA 提供了大量的现成的类,我们几乎不再需要去构建自己的类,这种结果,我们熟练地习惯了从使用者的角度去理解类的实例:对象,包括它的属性、方法和事件。但是,现在你还要尝试做一个提供者,这和你作为使用者时的思考方法是完全不同的,甚至是革命性的。这种角色的转位是痛苦的,它需要你放弃你原

8、本可以自豪地解释出对象以及它的属性、方法、事件的定义,它们原本是如此逻辑地被划分,如此清晰,但现在,类模块中的一切,彼此交织,你会发现它们都模糊了!是需要你忘掉所有固执的“招势”的时候了,当你心中无剑时,转位也就完成了,隐者变得清晰了,她是如此美丽。且慢,在你完全忘掉前,让我们最后再看一眼它们的样子,呵呵,如果你实在忘不掉,你就提醒一下自己构建者的身份吧。下面是通常情况下关于对象、属性、方法、事件的基本表述,如果你以前没了解过,则应当找些资料先认真地理解它们,然后再按照上面的提示去做。 对象是由类创建的一个实例,它是类的实体化。 对象的引用和操作被逻辑上划分为不重叠的三个部分: 属性是指对象的

9、特性。以前面的 Textbox 为例,有长度,高度,框中显示的文字等等。 方法是指对象的某个操作。如让 Textbox 成为当前的焦点(即光标移动到它上面)。 事件是指对象对外部动作的响应。如我们用鼠标点击 Textbox 时,会产生一个 Click 事件,改变它的值,则产生一个 Change 事件变量的作用域 变量因为声明的位置和方式不同,从而有不同的作用域。作用域是指变量在多大范围内能被代码识别。可以划分为过程级、模块级和全局变量。 过程级变量在过程中声明,这里过程指的是一个 Sub 或 Function,也包括后面提到到属性过程。通常用 Dim 或 Static进行声明。Dim 声明的变

10、量,只在该过程执行时存在,过程结束,变量的值也就消失了。Static 声明的变量称为静态变量,这个值在整个程序运行期间都存在。 模块级变量对整个模块的所有过程都有效,但对其它模块不可用。可以在模块顶部声明。声明模块级变量用 Private关键字和直接使用 Dim 没有区别。但推荐使用 Private 进行声明,因为这样可以方便地与后面的全局变量区分开来。 全局变量是对整个 VBA 工程的所有过程都有效的变量,使用 Public 关键字在标准模块的顶部来声明。 在类模块中,对变量作用域的理解要注意下面两点: (a )由于类是生成对象的模具,每生成一个对象,相当于产生了一个副本,这个副本就是对象的

11、“真身”,副本间是相互独立的,从而,模块级的变量只作用于副本自身。 (b)类模块中使用 Public 关键字,只有当对象变量是这个类的实例时,才能被访问。 过程和函数 变量、过程(Sub)、函数( Function)是我们在标准模块中使用的最基本的构件,在类摸块中,它们仍然是最基本和重要的角色。对于它们,你已经再熟悉不过,之所以前面还要花这么多文字,是为了突出它的重要,也是想让你放松一下,哦,我花了很短的时间已经看了这么多(我也写了这么多!)。 过程和函数并无实质的区别,当需要返回值时,就使用 Function,如果不需要返回任何结果,随你的爱好,但这时推荐你使用 Sub,因为这样更符合微软的

12、本意。过程(Sub )、函数(Function)也有作用域,在标准模块中通过使用 Private 和 Public 关键字(可以省略 Public 关键字,因为它是默认的),可以划分为模块级和全局级,以决定它是在当前的模块有效还是整个工程有效。 同变量一样,在类模块中使用 Public 关键字,只有当引用对象变量是这个类的实例时,才能被访问通用内部控件 Control(s) VBA 提供 Control 类作为一般内部控件类型,当使用 Dim Ct As Control 声明了一个变量后,就可以将任何控件赋给该变量,而不管具体的类型,因为在类的使用通常是处理大量相近的对象,所以这种特性非常有用

13、。在实际使用时,我们多是通过容器控件的 Controls 属性来返回一个 Control 的集合对象。 Dim Ct As Control For Each Ct In Me.Controls If TypeName(Ct) = “CommandButton“ Then MsgBox Ct.Caption Next 上面这段代码可以遍历窗体的所有控件并报告找到的命令按钮。集合 Collection Collection 是我们在使用类时最常用到的对象。一个 Collection 对象代表一组相关的项目,虽然它的成员并不被强制要求是同一类型的的,但请记住,这通常并不能给我们带来额外的方便,相反,

14、我们通常是用来收集同一类型的数据。 建立集合的方法和建立其它对象一样,如: Dim col As New Collection 集合建立后,可以使用 Add 方法添加成员,用 Remove 方法删除成员,用 Item 方法从集合中返回特定成员。 Private Sub CommandButton1_Click() Dim col As New Collection Dim i% Dim ct As Control For Each ct In Me.Controls If Left(ct.Name, 7) = “TextBox“ Then col.Add ct Next ct For i =

15、col.Count To 1 Step -1 MsgBox “下面删除成员“ & col.Item(i).Name col.Remove i Next i End Sub 上面的代码先将窗体上所有的 TextBox 加入到集合中,然后再删除掉。Count 属性返回集合的成员数量,Remove 方法后面的参数是集合成员的索引号。成员的索引号通常是按照加入的顺序自然编号,从 1 开始,但可以在加入时使用 Add 方法的参数进行改变。Add 方法的完整语法是: object.Add item, key, before, after item 必需的。任意类型的表达式,指定要添加到集合中的成员。 ke

16、y 可选的。唯一字符串表达式,指定可以使用的键字符串,代替位置索引来访问集合中的成员。 before/after 可选的。表达式,指定集合中的相对位置。 下面语句向集合增加一个对象 TextBox1,并定义该成员的关键字为 tx1。 col.Add TextBox1, “tx1“ 然后,下面两句都可以向集合中增加一个 TextBox2,并把它放在成员 TextBox1 的前面。 col.Add TextBox2, , col.Count col.Add TextBox2, , “tx1“ 第一句中,因为只有一个成员,所以 col.Count 也是索引号使用事件的 WithEvents 变量 W

17、ithEvents 不是一个单独的语句,为了使用对象的事件,需要在声明该对象时使用 WithEvents 关键字。例如: Dim WithEvents app As Application 将上面的语句写入 ThisWorkBook 的模块,可以看到在通用框中出现了一个变量 app: 此主题相关图片如下:在通用框选择 app 后,左边的声明框便会显示 app 的事件。 此主题相关图片如下:需要注意的是,使用 WithEvents 只是声明了对象变量,而并不实际生成对象,为了生成真实的对象,你仍然需要在声明后向生成其它对象一样,使用 Set 语句进行指定。此外,WithEvents 变量不能是通

18、用类变量如 Object,而必须指定类名,也不能把 WithEvents 变量声明为 As New。不能在标准模块中使用 WithEvents初识类模块现在,请打开你的 VBE,主菜单-插入-类模块。 插入了一个类模块,也就建立了一个类。类模块的名字就是类的名字。你现在看到的,她的名字叫“类 1”,这是 VBA 按她姐妹排行给她取的的,是的,VBA 一贯如此,你早就熟悉了这种规则,现在,在标准模块或其它模块中输入Dim As 的时候,提示框中她已经出现了。但我知道,有件事你正耿耿于怀,“类 1”,太没个性了,想改成自己要的名字吧。很容易,和你改标准模块的名字一样,打开属性窗口,看到了吧,第一行

19、就是她的名字,随你的意愿修改吧。 此主题相关图片如下:你或许已经注意到,在名字下面,只有一个属性:Instancing,其值也只有两个选项:Private 和 PublicNotCreatable。事实上,你完全可以忽略这个 Instancing,就象你完全忽略条件编译指令一样,因为在 VBA 中我们几乎用不到它们,而只需维持她的默认值即可。至少我是这样认为的,但我给不了您充足的理由,而只是个人的一种狭隘经历。既然提到了,就简单说明一下: Instancing 属性决定该“类”在其它工程中是否可以被使用。我们知道,标准模块中的 Public 过程,可以保存在宏工作簿甚至直接被另一工作簿的工程调

20、用,但类中的代码是不可分割的整体,所以必须整体决定是否允许外用。当 Instancing 属性设为 Private(默认)时,不允许其它工程访问。当设置为 PublicNotCreatable 时,只有在自己的工程创建了该类的对象时,其它工程才允许使用这个对象,注意,仅仅是在本工程中创建的对象,而不能用她在其它工程中创建对象。 隐者已经来到你的身边,透过薄薄的面纱,你似乎已看到她神秘的微笑。站起身来,走过去吧!创建类属性 让我们想一下作为类的使用者时,我们是如何操作对象的属性的,对象属性的操作不外乎读和写两种。当我们要给对象的某个属性赋值时,我们会: TextBox1.Text=”abc” 当

21、我们要读取对象的属性时, S= TextBox1.Text 现在,看看作为类的提供者需要怎样做。 我们将“类 1”改名为“MyClass”并为它创建一个名称为x 的字符型属性。 1使用 Public 变量创建类属性 在类模块中写下行代码: Public x$ 是的,就这么简单,通常情况下,只需要这么简单使用 Property 过程创建类属性 Private s$ Public Property Get x() As String x = s End Property Public Property Let x(ByVal c As String) s = c End Property 我们可以

22、省去上面默认的 Public。但看上去还是有点麻烦哦,不仅需要两个公共过程,而且还要一个辅助的私有变量 s和一个参数 c。在类模块中, Property 过程把对属性的读写分开了,说一下 Property 过程的工作机制,当标准模块中的代码读取对象的属性时,便会触发存在的 Property Get 过程,或者说 Property Get 过程提供了属性的读功能,同样, Property Let 过程提供了写属性。这样,上面的两个过程(当然在模块中没有先后的要求),可以只有一个,或者虽然两个都有,但却不全是 Public,从而提供出去的属性是只读或只写(呵呵,没见过只写哈)。仅仅是为了提供只读或

23、只写的属性,代码就从一行变成了七行?!这样的理由,你不会信服, VBA 中的类通常是提供给我们自己使用的!如果它确实是只读的,我们自觉地去只读就是了!我们使用 Property 过程还有其它理由,最基本的一条,我们可以利用这个“过程”来做我们想做的事。看一看: Public Property Let x(ByVal c As String) s = Format(c, “0000“) End Property 这里我们只是简单的利用了一下,更多的在后面你会看到。此外,谁会保证有一天你不使用 VB 给别人提供类呢,这个技术可是通用的。提供一段标准模块的测试代码,来看看我们上面构建的类属性,你自己

24、试试吧。 Sub aTest() Dim mc As New MyClass mc.x = “123“ Debug.Print mc.x End Sub 就象我们给普通变量和对象变量赋值的方式不同一样,对象变量是使用 Set 赋值的。对“对象”属性,VBA 提供了 Property Set 来代替构建 “普通”属性使用的 Property Let。来看一段代码: Private tx As Object Property Get x() As Object Set x = tx End Property Property Set x(ByVal o As Object) Set tx = o

25、End Property 和前面的比较一下,除了多一个 Set,实在没有什么不同。 告诉你一个小秘诀,你可以按照 Function 去记住 Property Get 的用法,按照 Sub 去记住 Property Let /Set。属性的初始值 我们常常希望,当一个对象建立的时候,它的某些属性会被自动赋予一个初始值,这样,对具有最常见的属性值的对象可以减少重复性的赋值工作。这需要借助于类的构建函数来完成。 在类模块代码窗口的“通用”框中点击向下的小三角箭头,选择“Class”,右面声明框中可以看到两个选项,“Initialize”和“Terminate”,我们对它们应该不陌生,很多对象都有这两

26、个事件,Initialize 事件当对象建立时发生,Terminate 事件在对象对释放时发生。由于类是静态存在的,它并不是真正的对象,所以在类模块中,它们通常被称为构建函数和析构函数,或构建过程和析构过程。对它们的理解和你在对象中的用法并没有什么不同。当一个对象被建立时,构建函数将被首先执行,同样,当对象释放后,将执行析构函数。 下面建立 MyClass,属性 x 初始值为”0001” 的全部测试代码: 类模块 MyClass 的代码 Option Explicit Private s$ Public Property Get x() As String x = s End Property

27、 Public Property Let x(ByVal c As String) s = c End Property Private Sub Class_Initialize() s = “0001“ End Sub 标准模块 1 的代码 Option Explicit Sub aTest() Dim mc As New MyClass Debug.Print mc.x End Sub 隐者为你揭开了第一层面纱,你隐约已看到她美丽的面厐,虽然还不是很清晰,但你知道,早晚会的创建类方法 放松一下,请拿出你家的紫砂壶,泡上一壶好茶,听我给你将类的方法的故事,你的茶品完了,我的故事也差不多就讲完

28、了。 1构建类的方法其实就是在类模块中写公共的 Sub 和 Function 现在我们给前面提到的 MyClass 创建一个方法 PutIntoActiveCell,功能是将 x 属性值写入活动单元格。 Public x$ Sub PutIntoActiveCell() ActiveCell = x End Sub 在标准模块中用下面的代码测试一下: Sub aTest() Dim mc As New MyClass mc.x = “abc“ mc.PutIntoActiveCell End Sub 这是本回要告诉你的全部吗?你还没有开始品茶吧?就这样了结束?这是最重要和基本的,但却不是全部。

29、 你是否有一种感觉,但你不能清楚地说出来? 端起你可爱的茶杯,品一口茶,我们继续。 类的方法环境 借用广为众知的一个名词“数据环境”,虽然不准确,但我实在想不出更好的称谓来代替,姑且这么叫吧。稍后你就会知道它的含义。 类可以象 VBA 提供给我们的很多标准类一样风光无限,所有的程序设计者都在工程中使用它,但更多时候,我们所构建的类只在特定的环境下被使用,类的方法环境是指包括类所在工程的其它成员在内的,可以调用的资源的集合。工作簿、工作表、窗体或其它,在类模块中,你可以象在标准模块中一样操作它们,千万不要因为换成了类模块而产生任何疑虑,作为类的创建者,你要让类模块中的代码象你在标准模块中一样亲近

30、它们,只要你认为必要。脱离了方法环境的、谨小慎微的、封闭的类实在没有什么意义。如果你预期方法环境在运行时可能会有变化,你要事先预知它们并象在标准模块中一样使用恰当的措施,比如你不能确定运行时活动工作表的名称(但你确定届时会是一个工作表),你可以使用 ActiveSheet。 我反复说“和标准模块一样”,就是想告诉你在类模块中创建方法时,对工程中其它成员的操作,和你已经熟悉的标准模块中的方式的实在没有什么不同,这一原则适用于类模块中所有代码(也许叫代码环境更准确些),而不仅仅是构建方法的代码。 现在,你知道了,你刚才的感觉到的是开放的方法环境。是的,以后你会更深地体会到,作为好的提供者,开放的思

31、维有多重方法的兄弟成员事件 类方法的执行需要在代码中以显性的方式指定,象上面的mc.PutIntoActiveCell,有时候,当最终操作者触发类对象成员(属性)的某个事件,需要在事件发生时产生一系列的操作,这时,我们要运用成员事件。成员事件和方法都是类提供的一系列代码的操作,倆兄弟的区别在于,成员事件无法也不必再由代码显性调用。 我们来看一个具有普遍意义的事例。 重要例 窗体 UserForm1 上有 5 个 CommandButton 控件(名称分别为默认 CommandButton 1- CommandButton 5)和 1 个 TextBox 控件(名称为 TextBox1)。要求当

32、各个 CommandButton 控件被点击时,它的按钮文字(Caption)会写入 TextBox1。 如果不用类,我们需要为 5 个 CommandButton 控件分别写5 个相同的 Click 事件代码。如: Private Sub CommandButton 1_Click() TextBox1 = CommandButton 1.Caption End Sub 下面是用类的成员事件方法的代码: 类模块 Cmds 的代码 Option Explicit Public WithEvents cmd As CommandButton Private Sub cmd_Click() Use

33、rForm1.TextBox1 = cmd.Caption End Sub 窗体 UserForm1 的代码 Option Explicit Dim co As New Collection Private Sub UserForm_Initialize() Dim i% Dim myc As Cmds For i = 1 To 5 Set myc = New Cmds Set myc.cmd = Me.Controls(“CommandButton“ & i) co.Add myc Next i Set myc = Nothing End Sub 仔细玩味上例的每一行代码,直至品完你壶中的茶

34、。呵呵,因为它实在很有用。最后提一下 Friend 关键字,虽然在VBA 中几乎没有什么用,但如果有一天你要制作 ActiveX部件,可能会用到它。之所以要有 Friend 关键字,是因为类的私有部分在类模块外是不可见的,但有时却需要从外面访问这些私有部分,这时,可以使用 Friend 关键字使属性和方法成为“友元成员”。友元成员在本工程中相当于 Public,但在工程外,它仍是 Private 。 隐者为你揭去了第二层面纱,你几乎已看清她美丽的面庞,她带着甜蜜的微笑,似乎在问:什么才是最美的期待?创建类事件 在 VBA 中,因为我们既是提供者,也是使用者,所以通过良好地构建类的属性和方法,已

35、可以满足我们需要全部的要求。我不再去解释这个观点,在本回后你自然会明白。从这个意义上讲,创建类事件实在没有必要。唯一的遗憾是,我们没有体会到作为创建者的全部乐趣,标准类给我们提供了各种事件,当然希望自己也可以做到,想象中这应当是一件激动人心的事,所以,追求快乐是创建类事件的重要理由,另一个理由,前面已经提到。 回到前面我们的 MyClass 类,我们将 x 属性改名为 Value 属性,虽然对属性、方法以及事件的命名,VBA 没有特别的限制,但建议您不要象我前面那样,随便取一个 x,可能的话,要尽量和标准类的成员(属性、方法以及事件)名称相一致。 现在我们为“使用”者提供一个“Change”事

36、件,不错,我们给它取名为“Change”,而不再是随意的“y”或其它(虽然也可以),这样,我也不用解释这个事件的用意了,呵呵。为了做到这一点,看看我们应该做什么。1第一步:使用 Event 语句声明事件 看一下类模块中现在的代码: Option Explicit Public Event Change(ByRef Cancel As Boolean) Private s$ Public Property Get Value() As String Value = s End Property Public Property Let Value(ByVal c As String) s = c

37、End Property Private Sub Class_Initialize() s = “abc“ 初始值 End Sub 和前面的代码比较,多出了一句: Public Event Change(ByRef Cancel As Boolean) 这就是 Event 语句,只此一句,我们已经为我们的类声明(我想使用“注册”一词是不是更妥切)了一个事件 Change。在看 Event 语句产生的效果前,先来看它的特性: (1)为了声明事件,Event 总是 Public 的,这好理解吧。 (2)事件可以不带参数,如 Public Event Change(),也可以带参数,如我们上面给出的

38、,但参数不能是命名参数,可选参数或数组参数。这里我只解释一下命名参数的含义。我们知道,事件可以因特定的用户事件而触发,也可以在代码中象方法一样指定执行,如下面的 CommandButton1_Click: Private Sub CommandButton2_Click() CommandButton1_Click End Sub 但在调用对象的方法时我们通常喜欢这样的方式: Selection.Sort Key1:=Range(“A2“), Order1:=xlAscending 这里 Key1、Order1 就是命名参数,命名参数的好处是我们不必记住它们的次序,调用时直接以名称和冒号后加等

39、于号指定它的值,但对事件的调用却不允许这样。 (3)事件没有返回值。 现在我们看一下,Event 为我们做了什么。 建立一窗体 UserForm1,添加一个 TextBox 控件(名称为 TextBox1),两个 CommandButton 控件(名称为 CommandButton1 和 CommandButton2),CommandButton1 的 Caption设置为“赋值”,CommandButton2 的 Caption 设置为“读值”,窗体的代码如下: Option Explicit Dim WithEvents mc As MyClass Private Sub CommandB

40、utton1_Click() mc.Value = TextBox1 赋值 End Sub Private Sub CommandButton2_Click() MsgBox “mc 当前的值为“ & mc.Value 读值 End Sub Private Sub UserForm_Initialize() Set mc = New MyClass End Sub 上面这段代码实现的是,当点击 CommandButton1 时便会将TextBox1 的值赋给 mc 的 Value,当点击 CommandButton2时便会显示 mc 当前的 Value 值。 来运行一下这个窗体,先点击 Com

41、mandButton2,此时显示“abc”,是 mc 的初始值,然后在 TextBox1 输入“123”,点击 CommandButton1,再点击 CommandButton2,显示“123”,说明赋值成功了。 呵呵,忘了,我们要做什么了!现在,请从 UserForm1 代码窗口的“通用”框中选择 mc,哇!我们声明的事件在右边“声明”框中已经出现了! 此主题相关图片如下:我们定义这个事件是希望当 mc 的值改变时响应的,现在就迫不及待地给它写一句代码吧: Private Sub mc_Change(ByRef Cancel As Boolean) If MsgBox(“要改变 mc 的值吗

42、?“, vbYesNo) = vbNo Then Cancel = True End Sub 上面这句代码你不会陌生吧,希望当用户选择了在改变时给用户一个确认的机会。 但是,现在点击 CommandButton1,却不会给你选择的机会,我们还有一步没有做。 使用 RaiseEvent 语句引发事件第二步:使用 RaiseEvent 语句引发事件 声明了事件后,我们要做的,便是找到所有与事件发生关联的地方,使用 RaiseEvent 语句引发事件,这里引发的含义相当于 Call,就是调用用户在事件中写的代码。在本例中,只有一个地方,就是 Property Let Value 过程中: Dim c

43、hyn As Boolean RaiseEvent Change(chyn) If chyn Then Exit Property 通过传递回的 chyn,决定是否执行后面的赋值语句。下面就是添加了 RaiseEvents 语句后的类模块的代码: Option Explicit Public Event Change(ByRef Cancel As Boolean) Private s$ Public Property Get Value() As String Value = s End Property Public Property Let Value(ByVal c As String) Dim chyn As Boolean RaiseEvent Change(chyn) If chyn Then Exit Property s = c End Property Private Sub Class_Initialize()

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报