基本编程元素 可见,在类型转换中,可能会有数据损失。此外对于对象类型(下文将介绍)来 讲,将一个类型的值赋给另一个类型的变量是会报错的。因此建议大家尽量减少 混用的情况。 种特别的类型是 Variant。这种变量可以放置任何类型的数据。比如上文中的 Dim var就等价于 Dim var as variant。但是要注意的是 Variant并不意味着变 量内容的类型可以变化。它仅仅是能放置任何类型的数据而已,同一时间只有 个”实际类型”。为此,其内部必须维护当前到底是什么类型,还需要在被访问 时进行内部的二次解释。所以它消耗的空间更大,并且性能更差。另外如果用 Variant变量表示一个对象,在写变量名后输入一个点,就不会有自动提示出现。 因此,建议大家少用 Variant类型 最后说一下作用域的问题。每一个变量都有一个作用域。如果在一个 Sub/ Function内定义变量,那么这个变量的作用域就仅仅限于这个 Sub/ Function,称为局部变量。也就是说,在其他Sub/ Function中是访问不到 这个变量的;或者说,如果在其他Sub/ Function中定义了同名的变量,二者完 全是两码事,互相不会有任何影响。 在Sub/ Function中的参数也是一种局部变量,其定义的方式就是比常规方法省 略了Dim。其形式正如上文所写的那样。当然,你也可以在参数列表里不写类型, 这就意味着参数类型是 Varmint。同样的, Function第一行的最后的 As Type 表明 Function返回值的类型。不写这个返回值就意味返回 Variant类型。 如果将Dim语句写在任意Sub/ Function之外,就定义了全局变量。此时变量对 于当前模块文件的所有Sub/ Function都有效。这时,不同的Sub/ Function之间 就能通过全局变量交流(尽管这不是个好习惯,因为这样就破坏了Sub/ Function 的独立性,使得复用难以进行)。当然,还有可以在不同模块之间都有效的变量 的定义方法,即将全局变量定义中的“Dim”改为“ Public”。不过这种变量在 小型程序中非常少见。 也许你会问,如果某个局部变量恰好和全局变量同名会怎么样?这时局部变量会 “遮蔽”全局变量,使你只能访问到局部变量。 下面是一个例子,大家可以来复习一下本次的内容 Sub ShowSumo Range(A1").Value CalSum(200) End Sub Function CalSum(n As Integer) As Integer Dim sum As Integer sum=0 For i=1 To n Step 1 If i Mod 7=o The sum sum+ I
基本编程元素 9 可见,在类型转换中,可能会有数据损失。此外对于对象类型(下文将介绍)来 讲,将一个类型的值赋给另一个类型的变量是会报错的。因此建议大家尽量减少 混用的情况。 一种特别的类型是 Variant。这种变量可以放置任何类型的数据。比如上文中的 Dim var 就等价于 Dim var As Variant。但是要注意的是 Variant 并不意味着变 量内容的类型可以变化。它仅仅是能放置任何类型的数据而已,同一时间只有一 个”实际类型”。为此,其内部必须维护当前到底是什么类型,还需要在被访问 时进行内部的二次解释。所以它消耗的空间更大,并且性能更差。另外如果用 Variant 变量表示一个对象,在写变量名后输入一个点,就不会有自动提示出现。 因此,建议大家少用 Variant 类型。 最后说一下作用域的问题。每一个变量都有一个作用域。如果在一个 Sub/Function 内定义变量,那么这个变量的作用域就仅仅限于这个 Sub/Function,称为局部变量。也就是说,在其他 Sub/Function 中是访问不到 这个变量的;或者说,如果在其他 Sub/Function 中定义了同名的变量,二者完 全是两码事,互相不会有任何影响。 在 Sub/Function 中的参数也是一种局部变量,其定义的方式就是比常规方法省 略了 Dim。其形式正如上文所写的那样。当然,你也可以在参数列表里不写类型, 这就意味着参数类型是 Varaint。同样的,Function 第一行的最后的 As Type 表明 Function 返回值的类型。不写这个返回值就意味返回 Variant 类型。 如果将 Dim 语句写在任意 Sub/Function 之外,就定义了全局变量。此时变量对 于当前模块文件的所有 Sub/Function 都有效。这时,不同的 Sub/Function 之间 就能通过全局变量交流(尽管这不是个好习惯,因为这样就破坏了 Sub/Function 的独立性,使得复用难以进行)。当然,还有可以在不同模块之间都有效的变量 的定义方法,即将全局变量定义中的“Dim”改为“Public”。不过这种变量在 小型程序中非常少见。 也许你会问,如果某个局部变量恰好和全局变量同名会怎么样?这时局部变量会 “遮蔽”全局变量,使你只能访问到局部变量。 下面是一个例子,大家可以来复习一下本次的内容。 Sub ShowSum() Range("A1").Value = CalSum(200) End Sub Function CalSum(n As Integer) As Integer Dim sum As Integer sum = 0 For i = 1 To n Step 1 If i Mod 7 = 0 Then sum = sum + i
基本编程元素 End if Next Calsum= sum End Function 最近代码计算了1200之间所有可以被7整除的数字之和,并在A1单元格内显 示结果(所以,请在 Excel的WBA环境里运行此段代码)。里面展示了如何定义 和使用Sub, Function以及如利用变量来存储数据。当然,我也用了一些没有讲 过的关键字,如For,If等。但我觉得它们的意思都是非常容易懂的。比如For i=1 To n Step1就定义了一个循环,让i从1逐渐增长为n,每次步长是1。 所以i依次变为1,2,3, n。当运行到Next那句时就会返回到For那 行,将ⅰ增量,重新执行循环体代码。而If是判断语句,判断i与7取模是否 是0(整除),Mod是关键字表示取模。而 Range(”A1")则是 Excel提供的 个对象,意为得到名称为A1的那个单元格区域。之后的代码就是将其值设为想 要的结果。关于对象将是下次的主题。最后值得注意的是那个n不要设的过大, 否则很容易造成sum不足以存储过大的数据而越界(记得么,整数的最大值是 32767) ●总结 本期我们讲了最基本的ⅦB构造元素。讲解了Sub、 Function、关键字、变量定 义和类型等概念。如果你能读到这里,想想看你还能记得它们是怎么回事不? 然关于这个主题,有很庞大的内容我没有讲。但往往就是这20%的内容在100% 代码里被用到,它们是最核心的内容。对于一些高级话题,如果你有兴趣的话 可以看 Programming Microsoft Visual Basic6.0 by Francesco Balena ( Microsoft press)。下一期讲带大家进入对象的世界:) ●问答 1.我是菜鸟,一般一个sub连dim都不用,想起什么变量就上去用了。这是不 是相当于 dim as variant? 比如 sub ao msgbox aa end sub 真实感觉:速度上,损失似乎不大;内存,似乎一个sub一次执行之后,变量全 清空了,内存里的a也被释放了。那么对于一般的小程序来说,是不是就无所 谓了呢?
基本编程元素 10 End If Next CalSum = sum End Function 最近代码计算了 1~200 之间所有可以被 7 整除的数字之和,并在 A1 单元格内显 示结果(所以,请在 Excel 的 VBA 环境里运行此段代码)。里面展示了如何定义 和使用 Sub,Function 以及如利用变量来存储数据。当然,我也用了一些没有讲 过的关键字,如 For,If 等。但我觉得它们的意思都是非常容易懂的。比如 For i=1 To n Step 1 就定义了一个循环,让 i 从 1 逐渐增长为 n,每次步长是 1。 所以 i 依次变为 1,2,3,……,n。当运行到 Next 那句时就会返回到 For 那一 行,将 i 增量,重新执行循环体代码。而 If 是判断语句,判断 i 与 7 取模是否 是 0(整除),Mod 是关键字表示取模。而 Range(”A1″)则是 Excel 提供的一 个对象,意为得到名称为 A1 的那个单元格区域。之后的代码就是将其值设为想 要的结果。关于对象将是下次的主题。最后值得注意的是那个 n 不要设的过大, 否则很容易造成 sum 不足以存储过大的数据而越界(记得么,整数的最大值是 32767)。 总结 本期我们讲了最基本的 VB 构造元素。讲解了 Sub、Function、关键字、变量定 义和类型等概念。如果你能读到这里,想想看你还能记得它们是怎么回事不?当 然关于这个主题,有很庞大的内容我没有讲。但往往就是这 20%的内容在 100% 代码里被用到,它们是最核心的内容。对于一些高级话题,如果你有兴趣的话, 可以看 Programming Microsoft Visual Basic 6.0 by Francesco Balena (Microsoft Press)。下一期讲带大家进入对象的世界:) 问答 1.我是菜鸟,一般一个 sub 连 dim 都不用,想起什么变量就上去用了。 这是不 是相当于 dim as variant ? 比如 sub a() aa=1 msgbox aa end sub 真实感觉:速度上,损失似乎不大;内存,似乎一个 sub 一次执行之后,变量全 清空了,内存里的 aa 也被释放了。那么对于一般的小程序来说,是不是就无所 谓了呢? —————————————————
基本编程元素 是的,小程序无所谓,方便就好。但是如果程序稍微大了些,对象多了些,类型 检查是一个很好的防止错误的功能。那个时候,写的对比写的少更重要。其实我 觉得在目前的硬件平台上,性能可以不做最优先考虑。反倒是编程的便利性(写 正确的类型后VBA编辑器有自动提示),可读性和类型错误检测让我不喜欢用 Variant。 能返回数值的 function,以及带变量的sub。感觉很好用,但是他们自己若 返回数值就不能单独执行了??比较困扰 是的,一般情况下, Function不能像Sub直接被绑定到某个快捷键,某个按钮 那样执行。必须被某个Sub或者 Function调用才行。但是有一种情况,就是 Excel 的自定义函数, Function的地位无可替代。写一个 Function后,可以像 Excel 自带函数那样直接在单元格里使用。 3.VBA的变量必须先声明再使用么? 当然不是,VBA允许你直接使用变量而不经任何声明。但是这样做可能会引起难 以调试的错误。比如你在第一行直接使用了变量abc,结果到了后边由于笔误写 成了acb。这一定会出逻辑错误,但是解释器因为语法没问题而不会报错。你自 己也很难在密密麻麻的代码中将这个错误挑出来。为了强迫变量必须先声明,再 使用,在程序的第一行加上这句 Option Explicit 这样,如果不经声明直接使用变量就会报语法错误。这对于比较大的程序十分必
基本编程元素 11 是的,小程序无所谓,方便就好。但是如果程序稍微大了些,对象多了些,类型 检查是一个很好的防止错误的功能。那个时候,写的对比写的少更重要。其实我 觉得在目前的硬件平台上,性能可以不做最优先考虑。反倒是编程的便利性(写 正确的类型后 VBA 编辑器有自动提示),可读性和类型错误检测让我不喜欢用 Variant。 2.能返回数值的 function,以及带变量的 sub。 感觉很好用,但是他们自己若 返回数值就不能单独执行了 ?? 比较困扰 ————————————————— 是的,一般情况下,Function 不能像 Sub 直接被绑定到某个快捷键,某个按钮 那样执行。必须被某个 Sub 或者 Function 调用才行。但是有一种情况,就是 Excel 的自定义函数,Function 的地位无可替代。写一个 Function 后,可以像 Excel 自带函数那样直接在单元格里使用。 3.VBA 的变量必须先声明再使用么? ————————————————— 当然不是,VBA 允许你直接使用变量而不经任何声明。但是这样做可能会引起难 以调试的错误。比如你在第一行直接使用了变量 abc,结果到了后边由于笔误写 成了 acb。这一定会出逻辑错误,但是解释器因为语法没问题而不会报错。你自 己也很难在密密麻麻的代码中将这个错误挑出来。为了强迫变量必须先声明,再 使用,在程序的第一行加上这句: Option Explicit 这样,如果不经声明直接使用变量就会报语法错误。这对于比较大的程序十分必 要
2.对象 当你叫一个人做什么事情的时候,一般来讲你会如何做呢?你会说,比如,“周 正龙,拍老虎去”。如果你想知道一个人的信息时,你大概会这么问,“姚明, 你有多高”。这是我们平时的直观的交流方式。对象就提供了这样一种机制,使 得我们的编程更加符合人的思维习惯。这样,做基于对象的编程就很方便了。比 如你可以用程序指令写 Application. Workbooks.Ad的代码让 Application这个 对象新建一个 Workbook 对象在物理上是一段内存的区域,维护着一组数据,这些数据管理着实际的各种 看得见,摸得着的实体。比如应用程序 Application是一个对象,窗口 Window 是一个对象,单元格是一个对象,段落是一个对象……在0 office中,几乎任何 实体都可以找到对应的对象。如果你希望操作某个实体,那么你就操作它的对象 就好了。这样,编程的任务被转变成了找到合适的对象,并让这个对象做一些事 情,或者从对象上获得一些信息。 在0 ffice中使用的对象模型是COM不同于比如 CORBA,Java或者.Net的对象)。 COM是 Component Object Model的简称,是微软开发的组件( Component)标准。 如果你不理解什么是组件,可以把软件看作是一个机器,而组件就是机器的一个 个零件。组件之间相互协作,共同完成任务。COM组件的好处是可以跨语言。也 就是说,你可以用不同的编程语言来开发组件,并用不同的编程语言来使用组件。 在 Windows下,你可以用C艹+, Visual basic,J++等语言开来发和使用组件。 当然,我们在这里并不关心一个COM组件是怎么开发的。你仅仅要记住如果要使 用一个COM组件的主要步骤是什么就可以。首先要使用COM组件,就必须先注册 它。如果你足够细心就能留意到很多 Windows程序在安装的时候都有一步叫做 “注册组件”。这就是为什么如果有的程序不安装就用不了的原因—一它们的组 件没安装,因此没法用,程序自然就运行不起来。 Office当然也不例外,它会 注册几个组件,这些组件分别对应不同的 Office程序,比如Word, Excel, Powerpoint, Outlook等。“注册”的结果可以在你的注册表里找到。打开 HKEY CLASSES R0OT,就能看到一长串的注册的组件,如下图所示。图中你能看 到 Excel的一些组件
对象 12 2. 对象 当你叫一个人做什么事情的时候,一般来讲你会如何做呢?你会说,比如,“周 正龙,拍老虎去”。如果你想知道一个人的信息时,你大概会这么问,“姚明, 你有多高”。这是我们平时的直观的交流方式。对象就提供了这样一种机制,使 得我们的编程更加符合人的思维习惯。这样,做基于对象的编程就很方便了。比 如你可以用程序指令写Application.Workbooks.Add的代码让Application这个 对象新建一个 Workbook。 对象在物理上是一段内存的区域,维护着一组数据,这些数据管理着实际的各种 看得见,摸得着的实体。比如应用程序 Application 是一个对象,窗口 Window 是一个对象,单元格是一个对象,段落是一个对象……在 Office 中,几乎任何 实体都可以找到对应的对象。如果你希望操作某个实体,那么你就操作它的对象 就好了。这样,编程的任务被转变成了找到合适的对象,并让这个对象做一些事 情,或者从对象上获得一些信息。 在 Office 中使用的对象模型是 COM(不同于比如 CORBA,Java 或者.Net 的对象)。 COM 是 Component Object Model 的简称,是微软开发的组件(Component)标准。 如果你不理解什么是组件,可以把软件看作是一个机器,而组件就是机器的一个 个零件。组件之间相互协作,共同完成任务。COM 组件的好处是可以跨语言。也 就是说,你可以用不同的编程语言来开发组件,并用不同的编程语言来使用组件。 在 Windows 下,你可以用 C++,Visual Basic,J++等语言开来发和使用组件。 当然,我们在这里并不关心一个 COM 组件是怎么开发的。你仅仅要记住如果要使 用一个 COM 组件的主要步骤是什么就可以。首先要使用 COM 组件,就必须先注册 它。如果你足够细心就能留意到很多 Windows 程序在安装的时候都有一步叫做 “注册组件”。这就是为什么如果有的程序不安装就用不了的原因——它们的组 件没安装,因此没法用,程序自然就运行不起来。Office 当然也不例外,它会 注册几个组件,这些组件分别对应不同的 Office 程序,比如 Word,Excel, PowerPoint,Outlook 等。“注册”的结果可以在你的注册表里找到。打开 HKEY_CLASSES_ROOT,就能看到一长串的注册的组件,如下图所示。图中你能看 到 Excel 的一些组件
弯注册表编餐器 文件编辑但查看收藏夹色A帮助 O Eventsystem.EventClass.1 O EventSystem.EventPublisher O Eventsystem. EventPublisher1 D-O Eventsystem. EventSubscription O EventSystem. EventSubscription1 O Eventsystem. Eventsystem a Eventsystem. Eventsystem1 口Exce,Addn b-0 Excel. AddInMacroEnabled a Excel Application a Excel Application, 1? a Excel. Backup O ExcelChart D口 Excel, Chart.5 口 Excel Chart.8 a Excel.CSV D□ Excel. Macroshee eXcelSheet a ExcelSheet.12 口 Excel, Sheet5 口Exce. Sheet.8 b-0 Excel. SheetBinaryMacroEnabled b-O Excel. SheetBinaryMacroEnabl O Excel. SheetMacroEnabled a Excel.SheetMacroEnabled 12 口Exce.SK O Excel Template 口 Excel, Template8 e Template mabled 我的电脑 HKEY CURRENT USER 每个组件定义了若干“对象类型”。回想上一期讲解的类型就能知道任何一个变 量都有一个类型。而对象也有类型。每个类型可以生成不同的“对象实例”。这 就是说,如果有一个 Excel. Application的对象类型,我可以生成很多个此类型 的对象实例,即开启多个 Excel(其实类似的,如果有 Integer这个类型,就可 以定义很多个不一样的 Integer变量)。在下文中我会简称“对象类型”为“类 型”,而“对象实例”为“对象”。 为了在VBA中使用某个类型,需要添加对包含这个类型定义的组件的引用(有点 拗口是吧,多念几遍)。在VBA编辑器的工具->引用就能打开一个对话框来更改 引用,如下图所示
对象 13 每个组件定义了若干“对象类型”。回想上一期讲解的类型就能知道任何一个变 量都有一个类型。而对象也有类型。每个类型可以生成不同的“对象实例”。这 就是说,如果有一个 Excel.Application 的对象类型,我可以生成很多个此类型 的对象实例,即开启多个 Excel(其实类似的,如果有 Integer 这个类型,就可 以定义很多个不一样的 Integer 变量)。在下文中我会简称“对象类型”为“类 型”,而“对象实例”为“对象”。 为了在 VBA 中使用某个类型,需要添加对包含这个类型定义的组件的引用(有点 拗口是吧,多念几遍)。在 VBA 编辑器的工具->引用就能打开一个对话框来更改 引用,如下图所示: