


下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、实用标准文案Excel VBA类模块入门教程示例一示例二集合示例文档VBA类:隐者的秘密刖言写下这个题目,可能会让很多朋友疑惑,笔者先埋下一个 关子,很快我会让您知道这个标题的寓意。这份礼物送给现在想学习类知识或曾经学过但因为各种 原因没有“修成正果”的朋友,我期望的结果是这篇文章后, 您可以在类模块中像在标准模块中写代码一样熟练,我也期 望不至于太乏味而使您没有耐心看完整篇文章,或者说期望 您学习的过程是轻松愉悦的,但愿我可以做到。文章构划为 8部分:1 .什么是类2. 为什么要学习类3. 类的预备知识4. 创建类属性5. 创建类方法6. 创建类事件7. 个完整的类实例&未完的结尾什
2、么是类在我们身边,相同或相似的物品无处不在,从生活用品,到工业产品,通常它们都是由同一个可以称为“模具”的 东西生产出来。理解类,一般要先从对象谈起,但由于从不同的角度,有不 同的理解,从而也有不同的关于类的定义,本文不去探讨一 个完整并且公认的类概念,在这一部分后,只要你有一个基 本的判断并且在遇到时知道是类就可以了。在上面的这个例 子中,一个“模具”就是一个“类”,而由它生产出的每一 个产品,就是一个“对象”。看下面的 VBA语句:Dim tx1 As Textbox 不用解释它的意思吧,这里我们用到一个类 Textbox 定义了 一个对象 tx1 ,再来看:Dim tx1 As Text
3、boxDim tx2 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 成为当前的焦点 (即 光标移动到它上面)。事件是指对象对外部动作的响应。如我们用鼠标点击 Textb ox 时,会产生一个 Click 事件,改变它的值,则产生一个 C hange 事件变量的作用域变量因为声明的位置和方式不同,从而有不同的作用域。作 用域是指变量在多大范围内能被代码识别。可以划分为过程 级、模块级和全局变量。过程级变量在过程中声明,这里过程指的是一个Sub 或 Function ,也包括后面提到到属性过
10、程。通常用Dim 或 Static进行声明。 Dim 声明的变量,只在该过程执行时存在,过程 结束, 变量的值也就消失了。 Static 声明的变量称为静态变 量,这个值在整个程序运行期间都存在。 模块级变量对整个模块的所有过程都有效,但对其它模块不 可用。可以在模块顶部声明。声明模块级变量用 Private 关 键字和直接使用 Dim 没有区别。但推荐使用 Private 进行声 明,因为这样可以方便地与后面的全局变量区分开来。全局变量是对整个 VBA工程的所有过程都有效的变量,使用 Public 关键字在标准模块的顶部来声明。在类模块中,对变量作用域的理解要注意下面两点:(a) 由于类是生
11、成对象的模具,每生成一个对象,相当于 产生了一个副本,这个副本就是对象的“真身”,副本间是 相互独立的,从而,模块级的变量只作用于副本自身。(b) 类模块中使用Public关键字,只有当对象变量是这个 类的实例时,才能被访问。过程和函数变量、过程(Sub)、函数(Function )是我们在标准模块中使用的最基本的构件,在类摸块中,它们仍然是最基本和 重要的角色。对于它们,你已经再熟悉不过,之所以前面还 要花这么多文字,是为了突出它的重要,也是想让你放松一 下,哦,我花了很短的时间已经看了这么多(我也写了这么 多!)。过程和函数并无实质的区别,当需要返回值时,就使用 Fun ction ,如果
12、不需要返回任何结果,随你的爱好,但这时推 荐你使用Sub,因为这样更符合微软的本意。过程(Sub)、函数( Function )也有作用域,在标准模块中通过使用 Pri vate 和 Public 关键字(可以省略 Public 关键字, 因为它是 默认的),可以划分为模块级和全局级,以决定它是在当前 的模块有效还是整个工程有效。同变量一样,在类模块中使用 Public 关键字,只有当引用 对象变量是这个类的实例时,才能被访问通用内部控件 Control ( s)VBA提供Control类作为一般内部控件类型,当使用Dim Ct As Control声明了一个变量后,就可以将任何控件赋给该变量
13、,而不管 具体的类型,因为在类的使用通常是处理大量相近的对象, 所以这种特性非常有用。在实际使用时,我们多是通过容器 控件的 Controls 属性来返回一个 Control 的集合对象。Dim Ct As ControlFor Each Ct In Me.ControlsIf TypeName(Ct) = "CommandButton" Then MsgBox Ct.CaptionNext上面这段代码可以遍历窗体的所有控件并报告找到的命令 按钮。集合 CollectionCollection 是我们在使用类时最常用到的对象。一个 Colle ction 对象代表一组相关的
14、项目,虽然它的成员并不被强制 要求是同一类型的的,但请记住,这通常并不能给我们带来 额外的方便,相反,我们通常是用来收集同一类型的数据。建立集合的方法和建立其它对象一样,如:Dim col As New Collection集合建立后,可以使用Add方法添加成员,用Remove方法删除成员,用 Item 方法从集合中返回特定成员。Private Sub CommandButton1_Click()Dim col As New CollectionDim i%Dim ct As ControlFor Each ct In Me.ControlsIf Left(ct.Name, 7) = &quo
15、t;TextBox" Then col.Add ctNext ctFor i = col.Count To 1 Step -1MsgBox " 下面删除成员 " & col.Item(i).Namecol.Remove iNext iEnd Sub上面的代码先将窗体上所有的 TextBox 加入到集合中,然后 再删除掉。Count属性返回集合的成员数量,Remove方法后 面的参数是集合成员的索引号。成员的索引号通常是按照加入的顺序自然编号,从 1开始,但可以在加入时使用 Add方 法的参数进行改变。Add方法的完整语法是:object .Add item
16、 , key , before , afteritem 必需的。任意类型的表达式,指定要添加到集合中的成员。key 可选的。 唯一字符串表达式, 指定可以使用的键字符串, 代替位置索引来访问集合中的成员。before/after 可选的。表达式,指定集合中的相对位置。 下面语句向集合增加一个对象 TextBox1 ,并定义该成员的关 键字为 tx1 。col.Add TextBox1, "tx1"然后, 下面两句都可以向集合中增加一个 TextBox2 ,并把它 放在成员 TextBox1 的前面。col.Add TextBox2, , col.Countcol.Add T
17、extBox2, , "tx1"第一句中,因为只有一个成员,所以col.Count也是索引号使用事件的WithEvents变量WithEvents不是一个单独的语句,为了使用对象的事件,需要在声明该对象时使用WithEvents关键字。例如:Dim WithEvents app As Application将上面的语句写入 ThisWorkBook的模块,可以看到在通用 框中出现了一个变量app:此主题相关图片如下:S Microsofl. Visual Basic - Book! - ThisWorkbook (代码)婦 丈件)编辑 视圈边 插入 格式辺 调试 运行
18、74; 工具 外接程存® I-題 ¥BA?raject 3onkl)j込 licraEoft Excel 对象Sh&etl (Sh&etl)SkeetS (Shtet?)Sheets CSheet) Thi WorkbookWW«)声明)Option ExplicitDim Vfi tKEveiits 电pp Am Appliation冋3模块战模块1iF、类梗块占类1屋牲-1 hi曲決Moi|TKi sf orkboa Workbook * ;按字鱼序I按分类序佟称)Thi sc-rkboolc 生AcceptLabsl eI Pals &
19、; AutoUpdateFre0 ChangeKi stcry0在通用框选择app后,左边的声明框便会显示 app的事件。此主题相关图片如下:J J羽丨勺程-VBAProject縄文件归编辑(1)视閣插入格式辺调试运行® 工具外接程序)i d VBAPrnj ect (Boakl)F3 巴? Microsoft Ixcel 对象O Sheetl Gheetl)S Sheets (Sheet?) 雹)Sheet3 (SheetS) Q Thi sWcrkboflkL=l - i檯块我模块1TH类模块类1冈u Hi hmlfl片险瞪髦MR|ThisVorkboo arkbook按字母序|
20、按分类序丨名称)A.cceptL.belI FalseAutoUpdateFr e 0ChangeHi story 0<* c d cn 41 iri二2 » z丿址憩兰"曽®行id “列1需要注意的是,使用WithEvents只是声明了对象变量,而并不实际生成对象,为了生成真实的对象,你仍然需要在声 明后向生成其它对象一样,使用Set语句进行指定。此外,WithEvents变量不能是通用类变量如Object,而必须指定类名,也不能把 WithEvents变量声明为 As New。不能在标 准模块中使用 WithEvents初识类模块现在,请打开你的 VBE
21、主菜单-插入-类模块。插入了一个类模块,也就建立了一个类。类模块的名字就是类的名字。你现在看到的,她的名字叫“类1”,这是VBA按她姐妹排行给她取的的,是的,VBA一贯如此,你早就熟悉了这种规则,现在,在标准模块或其它模块中输入 Dim As的时候,提示框中她已经出现了。但我知道,有件事你正 耿耿于怀,“类1”,太没个性了,想改成自己要的名字吧。 很容易,和你改标准模块的名字一样,打开属性窗口,看到 了吧,第一行就是她的名字,随你的意愿修改吧。此主题相关图片如下:Micros Ft Visual 阴引 t - Bookl -类 1 (代玛)绳文件漏辑(T 视團插入格式Q)调试助运行®
22、 工具外接程序 1越Sheet】&he泌打 彎 Sheets (SheetS) 團 1 Sh&et3 (SheetS)Q ThisWorkbook T H檯块悬模块1 白由牌块丿叱鬆宜岁 o行3,列堆Option Esplicitdim xx負呂七 ImlMaps越幺XmlHameEpace4 XmlNam&spaces XmlSchema XmlSchemasL XgT) <(名称)Instinc 1 ng 1 - Private碣豳名I类i类t类檯块轅字母序I植佔兰卓你或许已经注意到,在名字下面,只有一个属性:Instancing,其值也只有两个选项:Priv
23、ate 和PublicNotCreatable 。事实上,你完全可以忽略这个Instancing ,就象你完全忽略 条件编译指令一样,因为在VBA中我们几乎用不到它们,而只需维持她的默认值即可。至少我是这样认为的,但我给不 了您充足的理由,而只是个人的一种狭隘经历。既然提到了,就简单说明一下:Instancing 属性决定该“类”在其它工程中是否可以被使用。 我们知道,标准模块中的 Public过程,可以保存在宏工作 簿甚至直接被另一工作簿的工程调用,但类中的代码是不可 分割的整体,所以必须整体决定是否允许外用。当Instancing属性设为Private (默认)时,不允许其它工程访问。当设
24、置为 PublicNotCreatable 时,只有在自己的工程创建 了该类的对象时,其它工程才允许使用这个对象,注意,仅 仅是在本工程中创建的对象,而不能用她在其它工程中创建 对象。隐者已经来到你的身边,透过薄薄的面纱,你似乎已看到她 神秘的微笑。站起身来,走过去吧!创建类属性让我们想一下作为类的使用者时,我们是如何操作对象的属 性的,对象属性的操作不外乎读和写两种。当我们要给对象 的某个属性赋值时,我们会:TextBox1.Text= ” abc ”当我们要读取对象的属性时,S= TextBox1.Text现在,看看作为类的提供者需要怎样做。我们将“类 1”改名为“ MyClass ”并为
25、它创建一个名称为 x 的字符型属性。1使用 Public 变量创建类属性在类模块中写下行代码:Public x$ 是的,就这么简单,通常情况下,只需要这么简单使用 Property 过程创建类属性Private s$Public Property Get x() As Stringx = sEnd PropertyPublic Property Let x(ByVal c As String)s = cEnd Property 我们可以省去上面默认的 Public 。但看上去还是有点麻烦 哦,不仅需要两个公共过程,而且还要一个辅助的私有变量 s 和一个参数 c 。在类模块中, Property
26、 过程把对属性的读 写分开了,说一下 Property 过程的工作机制,当标准模块 中的代码读取对象的属性时,便会触发存在的 Property Ge t 过程, 或者说 Property Get 过程提供了属性的读功能, 同 样, Property Let 过程提供了写属性。这样,上面的两个过 程(当然在模块中没有先后的要求),可以只有一个,或者 虽然两个都有, 但却不全是 Public ,从而提供出去的属性是 只读或只写(呵呵,没见过只写哈)。仅仅是为了提供只读 或只写的属性,代码就从一行变成了七行?!这样的理由, 你不会信服, VBA 中的类通常是提供给我们自己使用的! 如 果它确实是只读
27、的,我们自觉地去只读就是了!我们使用 roperty 过程还有其它理由,最基本的一条,我们可以利用 这个“过程”来做我们想做的事。看一看: Public Property Let x(ByVal c As String)s = Format(c, "0000")End Property 这里我们只是简单的利用了一下,更多的在后面你会看到。此外,谁会保证有一天你不使用VB给别人提供类呢,这个技术可是通用的。提供一段标准模块的测试代码,来看看我 们上面构建的类属性,你自己试试吧。Sub aTest()Dim mc As New MyClassmc.x = "123&q
28、uot;Debug.Print mc.xEnd Sub 就象我们给普通变量和对象变量赋值的方式不同一样,对象 变量是使用Set赋值的。对“对象”属性,VBA提供了 Property Set 来代替构建“普通”属性使用的 Property Let 。 来看一段代码:Private tx As ObjectProperty Get x() As ObjectSet x = txEnd PropertyProperty Set x(ByVal o As Object)Set tx = oEnd Property 和前面的比较一下,除了多一个Set ,实在没有什么不同。告诉你一个小秘诀, 你可以按照
29、Function 去记住 Property Get的用法,按照 Sub去记住Property Let /Set 。属性的初始值我们常常希望,当一个对象建立的时候,它的某些属性会被 自动赋予一个初始值,这样,对具有最常见的属性值的对象 可以减少重复性的赋值工作。这需要借助于类的构建函数来 完成。在类模块代码窗口的“通用”框中点击向下的小三角箭头, 选择“ Class ”,右面声明框中可以看到两个选项,“ Initi alize ”和“ Terminate ”,我们对它们应该不陌生,很多对 象都有这两个事件, Initialize 事件当对象建立时发生, T erminate 事件在对象对释放时发
30、生。由于类是静态存在的, 它并不是真正的对象,所以在类模块中,它们通常被称为构 建函数和析构函数,或构建过程和析构过程。对它们的理解 和你在对象中的用法并没有什么不同。当一个对象被建立 时,构建函数将被首先执行,同样,当对象释放后,将执行 析构函数。下面建立MyClass,属性x初始值为” 0001 ”的全部测试代 码: 类模块 MyClass 的代码 Option ExplicitPrivate s$Public Property Get x() As Stringx = sEnd PropertyPublic Property Let x(ByVal c As String)s = cEn
31、d PropertyPrivate Sub Class_Initialize()s = "0001"End Sub 标准模块 1 的代码 Option ExplicitSub aTest()Dim mc As New MyClassDebug.Print mc.xEnd Sub 隐者为你揭开了第一层面纱,你隐约已看到她美丽的面厐, 虽然还不是很清晰,但你知道,早晚会的创建类方法放松一下,请拿出你家的紫砂壶,泡上一壶好茶,听我给你 将类的方法的故事,你的茶品完了,我的故事也差不多就讲 完了。1构建类的方法其实就是在类模块中写公共的Sub 和 Function现在我们给前面提到
32、的 MyClass 创建一个方法 PutIntoActi veCell ,功能是将 x 属性值写入活动单元格。Public x$Sub PutIntoActiveCell()ActiveCell = xEnd Sub 在标准模块中用下面的代码测试一下:Sub aTest()Dim mc As New MyClassmc.x = "abc"mc.PutIntoActiveCellEnd Sub 这是本回要告诉你的全部吗?你还没有开始品茶吧?就这 样了结束?这是最重要和基本的,但却不是全部。 你是否有一种感觉,但你不能清楚地说出来? 端起你可爱 的茶杯,品一口茶,我们继续。类的
33、方法环境借用广为众知的一个名词“数据环境”,虽然不准确,但我 实在想不出更好的称谓来代替,姑且这么叫吧。稍后你就会 知道它的含义。类可以象VBA提供给我们的很多标准类一样风光无限,所有的程序设计者都在工程中使用它,但更多时候,我们所构建 的类只在特定的环境下被使用,类的方法环境是指包括类所 在工程的其它成员在内的, 可以调用的资源的集合。 工作簿、 工作表、窗体或其它,在类模块中,你可以象在标准模块中 一样操作它们,千万不要因为换成了类模块而产生任何疑 虑,作为类的创建者,你要让类模块中的代码象你在标准模 块中一样亲近它们,只要你认为必要。脱离了方法环境的、 谨小慎微的、封闭的类实在没有什么意
34、义。如果你预期方法 环境在运行时可能会有变化,你要事先预知它们并象在标准 模块中一样使用恰当的措施,比如你不能确定运行时活动工 作表的名称(但你确定届时会是一个工作表),你可以使用 ActiveSheet 。我反复说“和标准模块一样”,就是想告诉你在类模块中创 建方法时,对工程中其它成员的操作,和你已经熟悉的标准 模块中的方式的实在没有什么不同,这一原则适用于类模块 中所有代码(也许叫代码环境更准确些),而不仅仅是构建 方法的代码。现在,你知道了,你刚才的感觉到的是开放的方法环境。是 的,以后你会更深地体会到,作为好的提供者,开放的思维 有多重方法的兄弟成员事件 类方法的执行需要在代码中以显性
35、的方式指定,象上面的 m c.PutIntoActiveCell ,有时候,当最终操作者触发类对象 成员(属性)的某个事件,需要在事件发生时产生一系列的 操作,这时,我们要运用成员事件。成员事件和方法都是类 提供的一系列代码的操作,倆兄弟的区别在于,成员事件无 法也不必再由代码显性调用。我们来看一个具有普遍意义的事例。 重要例 窗体 UserForm1 上有 5 个 CommandButton 控件(名称分别为 默认 CommandButton 1- CommandButton 5)和 1 个 TextBox 控件(名称为 TextBox1 )。要求当各个 CommandButton 控件 被
36、点击时,它的按钮文字( Caption )会写入 TextBox1 。如果不用类,我们需要为5个CommandButton控件分别写5个相同的 Click 事件代码。如 :Private Sub CommandButton 1_Click()TextBox1 = CommandButton 1.CaptionEnd Sub下面是用类的成员事件方法的代码:类模块Cmds的代码Option ExplicitPublic WithEvents cmd As CommandButtonPrivate Sub cmd_Click()UserForm1.TextBox1 = cmd.CaptionEnd
37、Sub窗体 UserForm1 的代码Option ExplicitDim co As New CollectionPrivate Sub UserForm_Initialize()Dim i%Dim myc As CmdsFor i = 1 To 5Set myc = New CmdsSet myc.cmd = Me.Controls("CommandButton" & i)co.Add mycNext iSet myc = NothingVBEnd Sub 仔细玩味上例的每一行代码,直至品完你壶中的茶。呵呵, 因为它实在很有用。最后提一下 Friend 关键字,
38、虽然在 A 中几乎没有什么用, 但如果有一天你要制作 ActiveX 部件, 可能会用到它。之所以要有 Friend 关键字,是因为类的私 有部分在类模块外是不可见的,但有时却需要从外面访问这 些私有部分,这时,可以使用 Friend 关键字使属性和方法 成为“友元成员”。友元成员在本工程中相当于 Public ,但 在工程外,它仍是 Private 。 隐者为你揭去了第二层面纱,你几乎已看清她美丽的面庞, 她带着甜蜜的微笑,似乎在问:什么才是最美的期待?创建类事件在VBA中,因为我们既是提供者,也是使用者,所以通过良 好地构建类的属性和方法,已可以满足我们需要全部的要 求。我不再去解释这个观
39、点,在本回后你自然会明白。从这 个意义上讲,创建类事件实在没有必要。唯一的遗憾是,我 们没有体会到作为创建者的全部乐趣,标准类给我们提供了 各种事件,当然希望自己也可以做到,想象中这应当是一件 激动人心的事,所以,追求快乐是创建类事件的重要理由, 另一个理由,前面已经提到。回到前面我们的 MyClass 类,我们将 x 属性改名为 Value 属 性,虽然对属性、方法以及事件的命名,VBA没有特别的限制,但建议您不要象我前面那样,随便取一个x,可能的话,要尽量和标准类的成员 (属性、 方法以及事件) 名称相一致。现在我们为“使用”者提供一个“Change”事件,不错,我们给它取名为“ Chan
40、ge”,而不再是随意的“ y”或其它(虽 然也可以) ,这样, 我也不用解释这个事件的用意了, 呵呵。 为了做到这一点,看看我们应该做什么。1第一步:使用 Event 语句声明事件 看一下类模块中现在的代码:Option ExplicitPublic Event Change(ByRef Cancel As Boolean)Private s$Public Property Get Value() As StringValue = sEnd PropertyPublic Property Let Value(ByVal c As String)s = cEnd PropertyPrivate
41、Sub Class_Initialize()s = "abc" 初始值End Sub和前面的代码比较,多出了一句:Public Event Change(ByRef Cancel As Boolean)这就是 Event 语句,只此一句, 我们已经为我们的类声明 (我 想使用“注册” 一词是不是更妥切)了一个事件Changeo在看 Event 语句产生的效果前,先来看它的特性:(1)为了声明事件,Event总是Public的,这好理解吧。( 2)事件可以不带参数,如 Public Event Change() ,也可以带参数,如我们上面给出的,但参数不能是命名参数,可选参数
42、或数组参数。这里我只解释一下命名参数的含义。我们知道,事件可以因特定的用户事件而触发,也可以在代码 中象方法一样指定执行,如下面的 CommandButton1_Click :Private Sub CommandButton2_Click()CommandButton1_ClickEnd Sub但在调用对象的方法时我们通常喜欢这样的方式:Selection.Sort Key1:=Range("A2"), Order1:=xlAscending这里 Key1、Order1 就是命名参数,命名参数的好处是我们 不必记住它们的次序,调用时直接以名称和冒号后加等于号 指定它的值,
43、但对事件的调用却不允许这样。( 3)事件没有返回值。现在我们看一下, Event 为我们做了什么。建立一窗体 UserForml,添加一个 TextBox控件(名称为 Te xtBoxI ),两个 CommandButton控件(名称为 CommandButt on1 和 CommandButton2), CommandButton1 的 Caption 设置 为“赋值”,CommandButton2的Caption设置为“读值”, 窗体的代码如下:Option ExplicitDim WithEvents mc As MyClassPrivate Sub CommandButton1_Cli
44、ck()mc.Value = TextBox1 ' 赋值End SubPrivate Sub CommandButton2_Click()MsgBox "mc 当前的值为 " & mc.Value ' 读值End SubPrivate Sub UserForm_Initialize()Set mc = New MyClassEnd Sub上面这段代码实现的是,当点击CommandButtonl时便会将TextBoxl 的值赋给 me的 Value,当点击 CommandButton2时 便会显示me当前的Value值。来运行一下这个窗体,先点击Com
45、mandButton2,此时显示“ a be”,是me的初始值,然后在 TextBox1输入“ 123”,点击 CommandButtonl,再点击 CommandButton2 显示 “ 123” ,说明赋值成功了。呵呵,忘了,我们要做什么了!现在,请从 UserForml代码 窗口的“通用”框中选择me,哇!我们声明的事件在右边 “声 明”框中已经出现了!此主题相关图片如下:UserFormlMicrosoft Visual Basic = BookLmIs -垮 文件 編辑® 观图世)插入 格式 调试 运行® 工具 外按程序国毎oa齟丨刁6丨工三p M国乂程會爭处丨金
46、丨行皿列-:題 VBAJfrojtct (Bookl.xls)-Microsoft Excel 对隊題 Sheetl (Sheetl)蜀 ShetS (Shet3) 窗 ThisWcrkbookS-已窗体圉 UserFormlEl - &类模块丈1 NlyClasDjjn. WithEvents me As N)v)21assFr iv<te Sub CommazidBu.11on 1 Cl i ck 0 me. ¥alu& 二 TextBoxl ' RS值End Sub =_ ” Private Sub ConumaiiiBKitton2_Cli ck
47、 0"me当前的值为"& me. Value,读值 End EubFr £va tg Suber Formal ai ti ali zeSet me - New NlyClassEnd SubPrivate Sub mc_Chang(SyRe£ Cancel Boolean)End SubHUinidhlE我们定义这个事件是希望当me的值改变时响应的,现在就迫不及待地给它写一句代码吧:Private Sub mc_Change(ByRef Cancel As Boolean)If MsgBox(" 要改变 mc的值吗?", v
48、bYesNo) = vbNo ThenCancel = TrueEnd Sub上面这句代码你不会陌生吧,希望当用户选择了在改变时给 用户一个确认的机会。但是,现在点击 CommandButtonl,却不会给你选择的机会, 我们还有一步没有做。使用 RaiseEvent 语句引发事件第二步:使用 RaiseEvent 语句引发事件 声明了事件后,我们要做的,便是找到所有与事件发生关联 的地方,使用 RaiseEvent 语句引发事件,这里引发的含义 相当于 Call ,就是调用用户在事件中写的代码。在本例中, 只有一个地方,就是 Property Let Value 过程中:Dim chyn A
49、s BooleanRaiseEvent Change(chyn)If chyn Then Exit Property通过传递回的chyn,决定是否执行后面的赋值语句。下面就是添加了 RaiseEvents 语句后的类模块的代码:Option ExplicitPublic Event Change(ByRef Cancel As Boolean)Private s$Public Property Get Value() As StringValue = sEnd PropertyPublic Property Let Value(ByVal c As String)Dim chyn As BooleanRaiseEvent Change(chyn)If chyn Then Exit Propertys = cEnd PropertyPrivate Sub Class_Initialize()s = "abc"End Sub 现在你可以去运行你的窗体了,我们要的效
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 高考数学实践2024年试题及答案
- 网络服务的级别试题及答案分析
- 企业竞争策略与风险分析试题及答案
- 2025年软考设计师备考情绪管理试题及答案
- 2025农民土地流转合同范本
- 2025企业租赁合同标准范文
- 棉业公司范本章程
- 法学概论研究的国际视野与试题与答案
- 班级获奖经验的总结与反思计划
- 组织文件档案的秘书工作计划
- 河北名校2025届高考生物全真模拟密押卷含解析
- 血站考试试题及答案
- (三模)南通市2025届高三第三次调研测试英语试卷(含答案解析)
- 2025年高考化学三轮冲刺:实验综合大题 刷题练习题(含答案解析)
- 宁夏银川市2023−2024学年高一下学期期中考试 数学试卷(含解析)
- 浙江浙达环境科技有限公司年收集、贮存及转运危险废物5000吨的搬迁项目环评报告
- 抗凝剂皮下注射技术临床实践指南(2024版)解读
- 2024年全球及中国一次性喉镜片和手柄行业头部企业市场占有率及排名调研报告
- 湖南张家界事业单位招聘考试高频题库带答案2025年
- 2025-2030中国智慧港口行业市场深度调研及竞争格局与发展趋势研究报告
- 2025四川眉山市国有资本投资运营集团有限公司招聘50人笔试参考题库附带答案详解
评论
0/150
提交评论