下载
加入VIP
  • 专属下载特权
  • 现金文档折扣购买
  • VIP免费专区
  • 千万文档免费下载

上传资料

关闭

关闭

关闭

封号提示

内容

首页 vb入门

vb入门.pdf

vb入门

笑笑鸿鹄
2011-06-02 0人阅读 举报 0 0 0 暂无简介

简介:本文档为《vb入门pdf》,可适用于IT/计算机领域

序言speedfirstspeedfirstsinacom原版载于http:speedfirstmysmthnet目录目录序言基本编程元素对象开始编写完整的程序操作文件事件用户窗体根据VBA制作展示PPT提取Word中未样式化的标题操作数据库操作WindowsAPI序言序言某圣贤说过人和动物的最大之不同在于人知道怎么利用工具。VBA就是一种工具一种可以创造工具的工具。VBA提供了给你充分的自由做几乎任何其他编程语言或者环境能做的事情避免重复的手动劳动。当然有太多人对编程充满了敬畏认为编程是类似周小川做金融决策或者爱因斯坦在思考问题那样很玄幻、难以理解的事情更不用说运用了。但其实这更多的是误解(我觉得这些误解源自于国内的编程教科书上那些高深莫测的概念和诘屈聱牙的讲解)。事实上多年来编程正朝着越来越人性化越来越容易学的方向发展。VBA确切的说是VB(我在下面会解释这个微妙的差别)是众多语言中最容易学的正如其名字一样又”Visual”又”Basic”。所以大可不必担心诸如“我没有编程基础”之类的心理障碍。VBA的全称是VisualBasicforApplications的简称。其意思是开发环境被整合到了某个应用程序的VisualBasic语言。在本教程中特指整合在MSOffice中的VBA。(其余的还有比如VBAforAutoCAD,VBAforCorelDraw)我简单的将一门编程语言分为两个大的部分第一部分是其语法。语法规定了编程指令执行的顺序和内存的使用方式。尽管如此语法本身不能解决任何实际的问题这就好比你知道了英语语法但是不懂单词和短语就不能正确沟通一样另一个部分我称之为“库”就是其他人写好了的可以完成一定功能的东西。你可以调用库的某一个部分来完成自己想做的事情。语法和库在一起合作最终可以完成复杂的任务。对于VBA来讲使用的是VB的语法(确切的说是VB的语法与目前的VBNet完全不同如果你不知道我在说什么那么就忽略这句话好了)采用的是COM组件这种库库的功能是让你能操作Office的各种功能(VB也包含一个基本的库以完成一些常见的操作比如访问文件字符串操作数学运算等。这个库的形式是Func和Sub而不是COM)。比如代码:Fori=ToActiveWindowCaptain=iNext完成的工作是让当前Office组件的窗口标题在一瞬间从变成,,…,。FOR…NEXT是VB规定的语法用于循环。这些词语被称为“关键字”你不能将关键字用于其他用途。而ActiveWindow是指当前活动的Windows窗口Captain指窗口标题这些就是提供Office功能的COM组件。关于COM组件到底是怎么工作的我会在第章进行更详细的介绍。你可以类似的写出如下的代码:sum=Fori=Tosum=sumiNext序言就变成了求…的和。而:Fori=ToMsgBoxiNext可以显示次对话框依次显示,,…,。可见语法并不关心你到底用了哪些库在做什么而仅仅是完成其任务而已(在这里是循环)。在今后的教程中我会将重点放在介绍Office库提供的各种功能上而不会花很多时间介绍语法。仅仅是在第一次用某种语法举例子时我会说明一下。很快你就会发现这是很简单的一件事情。在正式介绍编程之间我简单说一下VBA的开发环境也就是你写代码的地方。如果你用的是Office在“工具”菜单找“宏”在其子菜单中找”VisualBasic”就可以打开一个新的窗口。如果是在Office中若你没看到“开发工具”选项卡的话先到选项中打开它。然后在“开发工具”选项卡的“代码”区域里按”VisualBasic”按键就可以打开同样的界面。(我用Excel举例)序言和的界面完全一样。因为Office添加了若干新的功能所以只有库比起来多了些东西表面上看不出来。在“工程”视图中右键单击”ThisWorkbook”然后在菜单中选“插入”>“模块”就会在主界面出现一片空白。键入我在图中写的代码:Subtest()MsgBox"Hello,VBA"EndSub然后点击上面的绿色箭头就可以运行它了。看看出了什么?:)这就是你的第一个VBA程序了。记住这个写代码的过程以后我们会反复用到它。并且我不会再重复。如果你有兴趣在桌面上新建一个文本文件将MsgBox"Hello,VBA"这句放到里面(不要第一句和第三句)然后保存为testvbs。(注意不是testvbstxt一定要把默认的扩展名去掉)然后双击这个文件你又看到了什么?(如果有杀毒软件或者防火墙问你是否执行脚本请确认允许。这段代码不会带来任何伤害)。以下是对一些常见问题的回答:宏和VBA是什么关系?广义上来讲宏就是VBA。我说“一段宏代码”和“一段VBA代码”是等价的。Office的自动录制功能可以帮你录制一个宏实际上就是把你的动作用VBA代码的形式记录下来。狭义上宏是指一个无参数的非Private的Sub(我会在后边解释什么是Sub)如果手写代码的话只有这种Sub才会出现在“宏”那个对话框的列表里。序言既然可以录制宏为何还要手写代码?首先宏录制的局限性很大很多动作(比如鼠标行为)是录不下来的。另外宏只能录制顺序的多个指令如上面的比较复杂一点的循环就不可能录制。而且宏录制不能覆盖VBA的强大功能。例如VBA可以直接读写文件系统中的任何文件。这些动作是录不下来的。最后录制宏得到的代码非常死板不灵活而且很冗余。如果你知道了怎么写就会立刻抛掉这个宏录制功能。事实上PowerPoint已经取消了宏录制。VBA能干什么?如果你想避免重复劳动或者需要多个文档协作VBA是最好的选择。虽然默认下VBA只可以操作VB自带的库和Office的库但可以通过添加引用的方式来为其扩充功能。理论上VBA可以操作任何WindowsAPI(代表你的Windows能做的任意事情)和任意用COM封装的组件。比如像AcrobatEndNote等都是这么做的。它们可以使自身的功能和办公紧密结合。如果你高兴大可以写一个Word用的聊天插件:)VBA不能干什么?什么时候不适合使用VBA?VBA的功能取决于其库。如果没有库提供一个功能(比如让Excel一个单元格显示一副图片)那么VBA也不能帮你。此外你还可以用VBA编写插件来完成普通Office不能完成的功能。此外如果你开发的项目过于庞大则应该换一门更专业的编程平台(比如Net)以便更好的组织代码和查错。VBA比较适合短小的与工作任务很直接的问题。VBA能访问某个文本文件么?当然可以。VBA直接提供OPEN关键字来访问文件。VBA能模拟键盘输入么?当然可以。VBA直接提供SendKeys函数来做到这一点。VBA会被保存在哪里?VBA是保存在Office文档中的具体可以是某一个文档或者某一个文档的模板中。具体的位置需要在工程视图中选择(如上图)。如果你希望一批文档都能用到同一个功能最好先写个模板然后将VBA写到模板里。然后利用此模板来生成多个文档。当然VBA代码也可以单独导出保存。在工程视图中右键单击某一个模块然后点“导出文件”即可。不同Office组件可以互操作么?当然可以。VBA的功能是由COM库来添加的。默认情况下某一个Office组件只引用了当前这个组件的库。但是你也可以手动添加其他库的引用。在VBA开发环境的“工具”菜单里点击“引用”就可以添加Windows上安装的任意COM组件。这样不光不同Office组件可以互操作你可以操作比如MediaPlayerIE等程序。VBA可以写图形界面么?当然可以。不然就说不上”Visual”了。VB一向支持一种被称为UserForm的模块。你可以在上面添加各种控件。VBA还提供哪些其他的功能?VBA可以捕捉Office的事件于是可以编写如“当打开一个文档要做某事”“当Excel计算发生了错误则做某事”这样的程序。VBA还有定时器让你可以做周期性的工作。除了VBA还有哪些开发平台可以操作Office?实际上任何可以使用COM组件的语言都可以访问Office的功能。在微软平台上的各种语言基本上都满足这个条件。不过有几个平台是专门针对Office的。如Net上的VSTO(VisualStudioToolsforOfficeDevelopers)。这是一个利用VisualStudio进行Office开发的集合环境适合大型项目。不过为序言了使用它你必须得安装VisualStudio或者。这对于办公族来说负担过重了。只有开发复杂的插件或者开发企业办公管理系统的人才应该使用它。此外Apache基金会有一个POI项目可以让Java程序访问Office文档。这样用Java开发同时又想自动生成Office文档的人(比如用Java写实验但想用Excel文档统计实验结果)可以利用POI来达到他们的目标。不过POI目前不支持Office的文件格式。基本编程元素基本编程元素这一期就是要介绍在VBA环境下你能使用什么东西。一般来讲新手往往对到底写什么会引起什么结果感到比较混乱。比如写MsgBox可以出现对话框但写MessageBox为什么就不可以。在VBA中直接写代码而不是在Sub里写就会报错?为何是Sub而不是Suc不是Sud?等等。我会将最常见的做概要性的讲解。但是我不会深入去介绍每个细节的语法。精简够用就好。如果有必要你可以查任何的关于VB的参考手册。Sub与Function最基本的问题是:如果你写了很多模块每个模块有很多代码那么你的程序代码是从哪一句开始执行?答案是VB将代码组成一段一段的每段从头到尾执行(当然这是粗略的说因为代码还可能有跳转和循环)。每一段叫做一个Sub或着一个Function。Sub是子过程“Subroutine”的简称。比如像如下的代码就定义了一个Sub。SubTest()MsgBox"Hello"'ShowHellowithamessageboxEndSub其中”Sub”这个关键字标志着Sub的开始EndSub则表示其结束。其中的Sub和EndSub是关键字。所谓关键字就是VB定义好的有特殊意义的词汇。在写代码时不可以写错一个字母否则就不被程序解释器接受(但是你可以不区分大小写VBA开发环境会自动帮你调整)。如果你在开发环境中写了这段代码就会发现关键字都被表为蓝色。其他的如ForNextIfThenWhile等都是关键字。以上代码中的Test是一个名称即这个Sub的名称。你可以随意定义这个名称只要其不包含一些特别的符号并且不和关键字重名(注意:绝对不能包含空白字符如空格或制表符)。写完这段代码后在Office的“宏”对话框列表里就能看到一项“Test”了。代码中的括号是用于定义参数的。如果想在SubFunction上加输入参数都是在括号中写一个列表即参数名As类型参数名As类型参数和类型在下面的“变量与类型”一节更详细的介绍。即使没有参数也要写个空括号来占位置。这是VB的要求。之后当你将键盘光标放在这个Sub里并点击上面的绿色箭头或者到“宏”对话框执行Test这个Sub就被执行了。另外值得注意的是单引号后边的文字称为注释。VB中所有写在单引号后边的文字都会被解释器忽略掉它们仅仅是给人看的。所以你可以在写代码时加上注释方便其他人看懂你的程序。基本编程元素Function和Sub是很类似的东西。比如:FunctionAdd(aAsInteger,aAsInteger)AsIntegersum=aaAdd=sumEndFunction这个例子实现了一个Function含义是将两个整数加起来。这次我添加了两个参数a和a用于输入其类型均为Integer。参数的语法Sub和Function是一样的。形式上Function和Sub仅仅有关键字的差别。Function与Sub最大的不同就在于Function需要返回一个值而Sub不需要。第一行最后那个“AsInteger”是指返回值的类型。返回的语法是:Function名称=想要返回的值那么什么叫“返回”呢?这是因为程序段之间是可以互相调用的。Sub和Function可以调用其他的Sub和Function。整个程序的执行顺序大致如下图所示:图中的矩形相当于一个Sub或者Function箭头代表程序的执行顺序(注意矩形的长短不代表代码的长短而仅仅是排版需要并且调用层数不一定是层)。每个SubFunction都可以调用其他的SubFunction这种形式造成了一种层数无限定的树状结构。在调用时上层可以以参数的形式给予下层输入而下层将控制权返回给上层的时候也可以给上层一个返回值(只有Function可以)。基本编程元素比如上面的Sub“Test”调用了VB已经定义好的MsgBox这个Function来完成工作(是不是觉得MsgBox应该是一个Sub?实际上MsgBox会返回一个整数值表示用户是按哪个键关闭对话框的比如“确定”“取消”“重试”等。只不过在最简单的情况下我们不关心这个返回值罢了)。另外我们也可以写一个程序让Test调用Add。SubTest()sum=Add(,)MsgBoxsumEndSub这样就能用对话框显示与的和了。在实践当中Sub一般用于执行某个动作而Function则在Excel自定义函数中特别有用。VB为开发者提供了一个很大的库即你可以直接使用许许多多的Sub和Function来完成常见的任务(这和Office库无关)比如字符串操作的SubstrTrimLen文件操作的DirWrite数学运算的LogSqr等。完整的清单可以在任何一本VB的参考手册上找到。变量与类型我们在算数的时候需要草稿纸将计算的中间结果记录下来。计算机算数也不例外也得需要在内存中开辟一些空间来记录这些内容。定义一块空间的方法的代码是:Dimvar或者DimvarAsType或者就像上文Test中的sum那样不经定义直接使用。其中Dim和As是关键字而var就是变量名。你可以随意定义变量名称只要其不包含一些特别的符号并且不和关键字重名。既然是分配一块内存空间那么分配空间有多大呢又是怎么使用的呢?这就由类型来定义了。一个类型规定了要分配的空间的大小和内部结构比如Integer整数就分配个Byte(所以其范围是~)而Long长整型数分配ByteDouble双精浮点数(小数)就分配个ByteString字符串的长度就是其存储字符串长度一块用于存放字符串的长度的额外空间。以上这些类型由VB定义被称为基本类型(还有其它几个基本类型可以使用)。VB会尽可能在你混用这些基本类型时进行自动转换。比如:DimstrAsStringDimnAsIntegerstr='nowstris""n=""'nownisn='nownis基本编程元素可见在类型转换中可能会有数据损失。此外对于对象类型(下文将介绍)来讲将一个类型的值赋给另一个类型的变量是会报错的。因此建议大家尽量减少混用的情况。一种特别的类型是Variant。这种变量可以放置任何类型的数据。比如上文中的Dimvar就等价于DimvarAsVariant。但是要注意的是Variant并不意味着变量内容的类型可以变化。它仅仅是能放置任何类型的数据而已同一时间只有一个”实际类型”。为此其内部必须维护当前到底是什么类型还需要在被访问时进行内部的二次解释。所以它消耗的空间更大并且性能更差。另外如果用Variant变量表示一个对象在写变量名后输入一个点就不会有自动提示出现。因此建议大家少用Variant类型。最后说一下作用域的问题。每一个变量都有一个作用域。如果在一个SubFunction内定义变量那么这个变量的作用域就仅仅限于这个SubFunction称为局部变量。也就是说在其他SubFunction中是访问不到这个变量的或者说如果在其他SubFunction中定义了同名的变量二者完全是两码事互相不会有任何影响。在SubFunction中的参数也是一种局部变量其定义的方式就是比常规方法省略了Dim。其形式正如上文所写的那样。当然你也可以在参数列表里不写类型这就意味着参数类型是Varaint。同样的Function第一行的最后的AsType表明Function返回值的类型。不写这个返回值就意味返回Variant类型。如果将Dim语句写在任意SubFunction之外就定义了全局变量。此时变量对于当前模块文件的所有SubFunction都有效。这时不同的SubFunction之间就能通过全局变量交流(尽管这不是个好习惯因为这样就破坏了SubFunction的独立性使得复用难以进行)。当然还有可以在不同模块之间都有效的变量的定义方法即将全局变量定义中的“Dim”改为“Public”。不过这种变量在小型程序中非常少见。也许你会问如果某个局部变量恰好和全局变量同名会怎么样?这时局部变量会“遮蔽”全局变量使你只能访问到局部变量。下面是一个例子大家可以来复习一下本次的内容。SubShowSum()Range("A")Value=CalSum()EndSubFunctionCalSum(nAsInteger)AsIntegerDimsumAsIntegersum=Fori=TonStepIfiMod=Thensum=sumi基本编程元素EndIfNextCalSum=sumEndFunction最近代码计算了~之间所有可以被整除的数字之和并在A单元格内显示结果(所以请在Excel的VBA环境里运行此段代码)。里面展示了如何定义和使用SubFunction以及如利用变量来存储数据。当然我也用了一些没有讲过的关键字如ForIf等。但我觉得它们的意思都是非常容易懂的。比如Fori=TonStep就定义了一个循环让i从逐渐增长为n每次步长是。所以i依次变为……n。当运行到Next那句时就会返回到For那一行将i增量重新执行循环体代码。而If是判断语句判断i与取模是否是(整除)Mod是关键字表示取模。而Range(”A″)则是Excel提供的一个对象意为得到名称为A的那个单元格区域。之后的代码就是将其值设为想要的结果。关于对象将是下次的主题。最后值得注意的是那个n不要设的过大否则很容易造成sum不足以存储过大的数据而越界(记得么整数的最大值是)。总结本期我们讲了最基本的VB构造元素。讲解了Sub、Function、关键字、变量定义和类型等概念。如果你能读到这里想想看你还能记得它们是怎么回事不?当然关于这个主题有很庞大的内容我没有讲。但往往就是这的内容在代码里被用到,它们是最核心的内容。对于一些高级话题如果你有兴趣的话可以看ProgrammingMicrosoftVisualBasicbyFrancescoBalena(MicrosoftPress)。下一期讲带大家进入对象的世界:)问答我是菜鸟一般一个sub连dim都不用想起什么变量就上去用了。这是不是相当于dimasvariant?比如suba()aa=msgboxaaendsub真实感觉:速度上损失似乎不大内存似乎一个sub一次执行之后变量全清空了内存里的aa也被释放了。那么对于一般的小程序来说是不是就无所谓了呢?基本编程元素是的小程序无所谓方便就好。但是如果程序稍微大了些对象多了些类型检查是一个很好的防止错误的功能。那个时候写的对比写的少更重要。其实我觉得在目前的硬件平台上性能可以不做最优先考虑。反倒是编程的便利性(写正确的类型后VBA编辑器有自动提示)可读性和类型错误检测让我不喜欢用Variant。能返回数值的function以及带变量的sub。感觉很好用但是他们自己若返回数值就不能单独执行了比较困扰是的一般情况下Function不能像Sub直接被绑定到某个快捷键某个按钮那样执行。必须被某个Sub或者Function调用才行。但是有一种情况就是Excel的自定义函数Function的地位无可替代。写一个Function后可以像Excel自带函数那样直接在单元格里使用。VBA的变量必须先声明再使用么?当然不是VBA允许你直接使用变量而不经任何声明。但是这样做可能会引起难以调试的错误。比如你在第一行直接使用了变量abc结果到了后边由于笔误写成了acb。这一定会出逻辑错误但是解释器因为语法没问题而不会报错。你自己也很难在密密麻麻的代码中将这个错误挑出来。为了强迫变量必须先声明再使用在程序的第一行加上这句:OptionExplicit这样如果不经声明直接使用变量就会报语法错误。这对于比较大的程序十分必要。对象对象当你叫一个人做什么事情的时候一般来讲你会如何做呢?你会说比如“周正龙拍老虎去”。如果你想知道一个人的信息时你大概会这么问“姚明你有多高”。这是我们平时的直观的交流方式。对象就提供了这样一种机制使得我们的编程更加符合人的思维习惯。这样做基于对象的编程就很方便了。比如你可以用程序指令写ApplicationWorkbooksAdd的代码让Application这个对象新建一个Workbook。对象在物理上是一段内存的区域维护着一组数据这些数据管理着实际的各种看得见摸得着的实体。比如应用程序Application是一个对象窗口Window是一个对象单元格是一个对象段落是一个对象……在Office中几乎任何实体都可以找到对应的对象。如果你希望操作某个实体那么你就操作它的对象就好了。这样编程的任务被转变成了找到合适的对象并让这个对象做一些事情或者从对象上获得一些信息。在Office中使用的对象模型是COM(不同于比如CORBAJava或者Net的对象)。COM是ComponentObjectModel的简称是微软开发的组件(Component)标准。如果你不理解什么是组件可以把软件看作是一个机器而组件就是机器的一个个零件。组件之间相互协作共同完成任务。COM组件的好处是可以跨语言。也就是说你可以用不同的编程语言来开发组件并用不同的编程语言来使用组件。在Windows下你可以用CVisualBasicJ等语言开来发和使用组件。当然我们在这里并不关心一个COM组件是怎么开发的。你仅仅要记住如果要使用一个COM组件的主要步骤是什么就可以。首先要使用COM组件就必须先注册它。如果你足够细心就能留意到很多Windows程序在安装的时候都有一步叫做“注册组件”。这就是为什么如果有的程序不安装就用不了的原因它们的组件没安装因此没法用程序自然就运行不起来。Office当然也不例外它会注册几个组件这些组件分别对应不同的Office程序比如WordExcelPowerPointOutlook等。“注册”的结果可以在你的注册表里找到。打开HKEYCLASSESROOT就能看到一长串的注册的组件如下图所示。图中你能看到Excel的一些组件。对象每个组件定义了若干“对象类型”。回想上一期讲解的类型就能知道任何一个变量都有一个类型。而对象也有类型。每个类型可以生成不同的“对象实例”。这就是说如果有一个ExcelApplication的对象类型我可以生成很多个此类型的对象实例即开启多个Excel(其实类似的如果有Integer这个类型就可以定义很多个不一样的Integer变量)。在下文中我会简称“对象类型”为“类型”而“对象实例”为“对象”。为了在VBA中使用某个类型需要添加对包含这个类型定义的组件的引用(有点拗口是吧多念几遍)。在VBA编辑器的工具>引用就能打开一个对话框来更改引用如下图所示:对象默认情况下VBA已经为我们自动添加了一些必要组件的引用所以大多是时候我们可以完全忽略以上的步骤直接写代码。但如果想用一些额外的组件就需要手动添加了。每个对象会有如下几种成员:•方法:表示一种动作。这和上次讲的一般的Sub是没什么区别的只不过它代表针对当前对象的动作。比如上面提到的WorkbooksAdd中的Workbooks是一个对象(更确切的说是一个集合对象下面再详述)而Add就是这个对象的方法用于执行“新建一个Workbook”这个动作。•函数:表示一种具有返回值的功能。这和上次讲的一般的Function是没什么区别的只不过它代表针对当前对象的功能。•属性:表示对象所带有的某种信息。比如Window对象具有Captain这样的属性表示其标题栏的标题Height和Width属性表示Window对象的宽和高等等。通过改变这些值就可以改变对象所代表的实体比如改变其外观。每个属性即可能是一个对象也可能是一个基本类型的变量。每个属性都属于一个类型。值得注意的是有两种特别的属性。第一种是“只读”的属性。就是说你不能改变它而仅仅能读取它。比如单元格的Text属性就是只读的。Excel根据单元格的Value和应用于此单元格的Format来决定Text是什么。所以如果非得要改的话需要改Value或者Format。另一种是所谓“集合”的属性。表示当前对象包含一组子对象。直观上一个Application包含多个Workbook一个Workbook包含多个Worksheet一个Worksheet包含若干的Range。对象也正是这么嵌套的。比如你想获得第一个Workbook的第一个Worksheet的A单元格需要这么写:ApplicationWorkbooks()Worksheets()Range("A")对象可以看到大多数集合对象比常规对象的名称多一个s表示复数(这是一种习惯而不是语法要求的。比如Range就没有s)。另外取得集合中的某一个对象即可以用对象索引值来获得(记得索引值是从开始算的而不是)也可以用过对象的名称比如如果你的第一个工作表又叫“MySheet”那么上面的语句可以等价的写为:ApplicationWorkbooks()Worksheets("MySheet")Range("A")你可以注意到访问对象成员的语法就是在对象名成后边加””。确切的语法是:对象名成员名下图是Excel对象结构的一个概览。虽然总共有一百多个对象但是实际上经常使用的仅仅只有Application,Workbook,Worksheet,Range,Window,Chart,Shape这么几个。(图是从帮助里截下来的所以那个箭头点了不会有效果:)对象对象我们可以定义一个变量来指向某个对象。这称为“对象的引用”(注意要和组件引用的概念区分开)或者引用变量。之所以用引用的方式访问对象的原因是对象比起常规变量都大的多。如果像普通变量那样每Dim一次就分配整个对象的内存非常浪费空间。所以对象的引用只包含对象在内存地址而已。当然我们通过对象的引用还是能够直接操作对象。比如下面的代码:DimaAsRange,bAsRangeSeta=Range("A")Setb=Range("A")就定义了两个对象引用a和b它们指向同一个对象Range("A")。逻辑上如下图所示:所以如果用aValue=xxx改变了对象的值bValue也能反映出变化。这和定义两个整数变量各自独立的语义是不一样的。另外需要注意的是对对象引用进行赋值的时候需要加Set关键字表示传递的是引用。如果不加Set就等价于对对象的默认属性赋值。如果a指向Range("A")对象那么写a="abc"等价于aValue="abc"因为Value是Range对象的默认属性。但是如果你写a=Range("A")就会出错。所以不要忘记Set关键字。那么什么时候对象会释放掉内存呢?每个对象有一个内部的引用计数。每添加一个引用就能使引用计数增加。如果你确认某个引用不再使用了就写a=Nothing这会让引用计数减。当对象的引用计数为的时候就会自动销毁释放内存。对象有人会问多个对象怎么找啊。答案是帮助文档。Office自带了庞大的开发文档。不过需要进入VBA编辑器后打开的帮助才能看得到。普通的帮助文档是找不到这些对象的。帮助中记录了每一个对象的每个成员的详细信息比如是做什么的是否是只读的参数信息等。如下图所示:所以如果想找一个对象完全没必要去录制宏那样去找。你仅仅把需要的对象的名字翻译成英文(工作簿>Workbook工作表>Worksheet……)然后去查文档。如果你对常用对象不熟悉的话那么请等待下一期教程:)开始编写完整的程序开始编写完整的程序前几期介绍了一些基本概念。是该拿真东西练练手的时候了。本期的主题就是拿OfficeSoft一个真实的问题作为例子讲解如何开始编写一个程序。当然这个例子也很简单:)这个问题是:如何将一组单元格内红色的数字求和。Excel自己提供的函数Sum不能对待求和数据进行条件判断而Sumif只允许对待求和数值进行数值比较上的判断也无法处理“字体是红色”这种格式条件。这时正是VBA发挥作用的时候它可以将一些基本的功能组织到一起然后完成自定义的任务。开始编程之前应该先想清楚几个关键的问题也就是一个设计的过程。编程可不是上来就开写。对于本问题首先想明白如何表达问题中的几个关键点:•如何表示一个单元格范围并以此作为问题的输入?即到底要对哪些单元格应用这个自定义的求和?•如何遍历一个个的单元格?•如何获取一个单元格的值?•对于一个单元格如何判断一个单元格的文字是红色的?•如何求和?•如何输出?对于第一个问题。我们一开始可以用最简单的输入方法来做这个事情即选择。用户在单元格上拖动一下选中了一组单元格。我们在VBA中可以用Selection对象来取得所有选中的单元格。Selection对象的类型是Range以后我会用“对象名{类型名}”的方法来表示对象和其类型的关系如Selection{Range}。顾名思意Range就表示一个单元格的范围。值得注意的是之前可以看到有这种写法Range("A")。这里的Range是一个对象名。具体来讲它等价于ActiveSheetRange("A")(这里Excel为我们提供了很好的快捷写法)。也就是说类型名可以和对象名重名。所以需要你来区分什么时候是类型什么时候是对象。回到我们的问题上Selection{Range}可以表示选中的所有单元格并为我所用。第一个问题解决。第二个问题。关于遍历一个像Selection这样的集合VBA提供了一个很方便的语法叫做ForEach…Next。其语法为:ForEach<obj>In<Collection>'DoSomethingwith<obj>Next使用的时候将<obj>和<Collection>替换成实际的变量和对象即可。每次<obj>这个变量都会指向Collection的一个元素。对于Selection其类型是Range那么其包含的元素是什么类型呢?答案是也是Range只是这些Range只代表开始编写完整的程序一个单元格。Range类型的对象包含一组Range类型的对象这没什么好奇怪的。文件系统中文件夹不是还能包含文件夹了么?第二个问题解决。第三个问题。一个对象r{Range}会有一个属性叫做Value表示单元格的值。当r是表示多个单元格的范围时rValue实际上是一个数组包含所有单元格的值如果r是一个单元格rValue就是那个单元格的值。也就是说Value的内容随着r的改变而改变并不是总是具有相同的类型所以Value属性一定是Variant类型的。第四个问题。如何判断单元格是红色的?回想一下我们是怎么在Excel里设定单元格是红色的?是利用字体对话框(Font)来设定的。在VBA中是一样的对象r{Range}有一个Font{Font}属性表示字体的所有信息比如边框粗体斜体等当然还有文字颜色Color{Double}。那么什么是红色?如果你学过三原色的话就知道颜色是由RGB组成的红色对应的是R=G=B=。在VBA中写作RGB(,,)。也就是说如果rFontColor=RGB(,,)就表示这就是我们想要的红色文字单元格。当然VBA还提供了一些颜色常量来方便我们的书写比如红色就是vbRed。所以上面的代码等价于rFontColor=vbRed。注意在本期教程中我忽略了一种特殊情况即一个单元格内的不同字符可能具有不同颜色。这个今后用到再说。第五个问题求和。可以用最基础的方法累加:设定一个变量sum初始值为。然后遍历所有单元格如果单元格符合条件就将其值累加到sum上。需要注意求和之前应该根据要求和数据的总量估算求和结果考虑sum应该用什么类型。Integer的范围是~而Long是,,,到,,,。这里为了简单就直接用Integer了。最后一个问题输出。这里就暂且用最基本的MsgBox输出吧。好了所有问题都解决。你可以根据这些知识尝试自己编写一下然后在看以下的完整代码:SubSumIfRed()DimsumAsIntegerDimrAsRangesum=ForEachrInSelectionIfrFontColor=vbRedThensum=sumrValueEndIfNextMsgBoxsumEndSub也许你对整个运算过程的细节非常感兴趣也许你写代码后发现除了错误。这时就可以对代码进行调试。在VBA编辑器写代码区域的左边空白单击一下就可以开始编写完整的程序增加一个“断点”。你也可以显示“调试”工具栏并点击上面的小手做到这一点。增加完断点之后运行程序当程序执行到断点时就会停下来。你可以借此机会查看当前各个变量的值。使用“监视”窗口(WatchView)或者“本地”窗口(LocalView)可以帮你做到这一点。调试工具栏上点击对应的按钮就可以让它们显示出来。本地窗口自动显示当前SubFunction的所有局部变量(本地、局部、Local是等价的这是翻译问题)。如果一个变量指向对象的话可以点击其左边的展开符号查看其所有成员。你还可以利用“类型”那列的信息显示出一个Variant变量当前的实际类型是什么。监视窗口与本地窗口类似只不过你需要指定让它显示哪些属性或者变量的信息。你可以直接在代码上选中一段代码然后拖拽到监视窗口添加对那些数据的监视。开始编写完整的程序“立即”窗口(ImmediateView)可以让你输入一段VBA代码查看某些内容。比如你可以输入Printsum一类的代码显示某些变量的值。还可以执行一段完整的代码段查看或者改变其他任意对象的状态。比如你想在程序被断点中断时Activate某个单元格就可以在立即窗口书写相应代码这时没有SubFunction的概念直接写功能代码即可。此外“调用堆栈”窗口显示第期教程中介绍的SubFunction互相调用的情况。让代码停下来之后你还可以一步一步的执行你的代码。用调试工具栏上的“逐语句”(StepIn)“逐过程”(Step)和“跳出”(StepOut)可以单步执行代码。它们的区别体现在如果执行到了一个你自己写的SubFunction是否单步进入那个SubFunction代码。OK完成上边那个Sub你可能会发现希望想要一个长的更像Sumif那样的自定义函数。输入应该用参数而输出直接放到单元格里。这时Sub就不能满足需要了而应当用Function来自定义一个函数。核心代码其实没什么变化仅仅是输入输出有所区别。代码如下:FunctionSumIfRed(rangeAsRange)AsIntegerDimsumAsIntegerDimrAsRangesum=ForEachrInrangeIfrFontColor=vbRedThensum=sumrValueEndIfNextSumIfRed=sumEndSub可以看到函数接受一个range{Range}作为操作范围(因此ForEach的Collection也从Selection改为range)并将结果作为函数的返回值返回。这样就能在Excel直接使用(甚至有自动提示哦)。比如你在A:A范围内输入一些整数然后在A输入=SumIfRed(A:A)就能得到想要的结果了。开始编写完整的程序在单元格作为自定义函数使用的Function有一点需要注意就是Function在执行过程中不能改变任何单元格的状态(格式值等等)否则Excel会报错。不过如果Function是被Sub调用的就没有这个限制。到此你应该可以用VBA完成一些初步的工作了。起码应该先像本文一开始那样将问题分解为若干小问题然后勤查文档逐个解决最后组合成完整的代码。多熟悉几遍这个过程就会很容易上手。如果出了错误就仔细调试找出问题。这样一定可以慢慢成为VBA高手。本期留个作业就是编写一个自定义函数求所有斜体数据的平均值。下一期会给出另外一个更复杂的例子讲解更多Excel的对象。操作文件操作文件在使用Excel的工作中很常见的就是收集磁盘上的文件并整理成Excel文件。被收集的文件可能是Excel文件XML文件数据库文件等特种文件也可能是普通的文本文件或者自己定义的文件。VBA提供了相当丰富的文件操作工具。当然本教程是不会流水般的列举所有操作的如有这个需要请看VBA的文档或者OfficeSoft的精华区。本期教程还是集中精力解决一个实际问题用以说明各种文件的操作方法。在以下的代码中需要注意的地方是对于文件的基本操作如打开、关闭、进入目录、查找、列举等操作是VBA直接支持的它们是VBA库提供的SubFunction甚至是关键字。针对Excel格式文件的操作自然由Office库来提供比如Workbook对象。我们的问题是:每个月公司都会收集大量的日志数据它们是以文本的方式记录的格式如下:交易时间商品名称成交价格:牙膏:牙刷……当然文本文件中并不存在那行列头仅包含数据。记录中间是以个空格分开的(上面为了排版的需要夸大了空格的长度)。已知我们的系统有个服务器每个服务器每天都会记录一份日志。每天所有服务器的日志都被保存在一个以日期为名称的目录

用户评价(0)

关闭

新课改视野下建构高中语文教学实验成果报告(32KB)

抱歉,积分不足下载失败,请稍后再试!

提示

试读已结束,如需要继续阅读或者下载,敬请购买!

评分:

/13

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利