Excel VBA案例实战

978-7-115-57289-9
作者: 韩立刚徐侃张立明蒋超
译者:
编辑: 武晓燕

图书目录:

详情

本书以案例讲解的形式,由浅入深地介绍了VBA在Excel中的应用。本书的内容可分为两个部分,前半部分介绍了VBA的基础应用,主要讲解如何简化复杂的工作,以及减少Excel中不必要的重复性操作;后半部分介绍了如何使用VBA编写各种工具、函数和小型系统,解决日常工作中遇到的包括但不局限于Excel的各种问题。

图书摘要

版权信息

书名:Excel VBA案例实战

ISBN:978-7-115-57289-9

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。


著    韩立刚 徐 侃 张立明 蒋 超

责任编辑 武晓燕

人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

读者服务热线:(010)81055410

反盗版热线:(010)81055315


本书以案例讲解的形式,由浅入深地介绍了VBA在Excel中的应用。本书的内容可分为两个部分,前半部分介绍了VBA的基础应用,主要讲解如何简化复杂的工作,以及减少Excel中不必要的重复性操作;后半部分介绍了如何使用VBA编写各种工具、函数和小型系统,解决日常工作中遇到的包括但不局限于Excel的各种问题。

本书图文并茂,理论与案例相结合,力求将本书涉及的VBA相关知识点通过实际案例进行讲解。本书案例几乎都源于实践,并配有全套资料文件和解决代码,颇具参考价值。

本书面向VBA零基础人员,日常工作中需要接触大量数据和Excel表格的人员,帮助他人解决Excel难题的运维人员,以及希望通过VBA进行自主开发的IT从业人员。本书亦可作为计算机培训教材。


微软公司的Office Excel功能强大、应用范围广,因此使用人数较多。而VBA作为Excel的扩展应用程序,使用人数却少了很多,甚至很多职场“老手”已经熟练掌握了Excel的各种使用技巧,却不知道如何在Excel中打开Visual Basic编辑器。

作为一款基于Visual Basic、但依附于Office应用程序的编程语言,VBA即使拥有入门门槛低、使用自由度高等诸多优点,似乎也很难获得一些专业程序员的青睐。

VBA的处境似乎有点尴尬。

但是,不能忽视的是,VBA是Office办公软件取得巨大成功的重要因素之一。

首先,VBA可以简化复杂的工作流程,减少不必要的重复性操作,大大提高工作效率。其次,VBA可以为Excel或者其他Office应用程序添加很多各具特色的小工具或小程序,极大地丰富了Office的功能。最后,基于Visual Basic 的可视化编程方法、强大的功能和较低的学习门槛,VBA为业余编程爱好者敞开了系统开发的大门。

鉴于VBA具有以上优点,我们认为有必要让更多的人认识和学习VBA,并享受VBA为工作和学习带来的便利。基于此目的,我们编写了本书。本书既可作为初学者系统学习VBA的教材,也可作为有一定基础的VBA使用者编程时的参考。

第 1 章,通过一个简单的案例,带领读者进入VBA的世界,介绍了VBA过程代码的结构,以及For循环的基本用法。

第2章,不仅介绍了Excel的录制宏功能,以及如何使用For循环对录制的宏代码进行修改,还介绍了相对引用、变量、为工作表插入按钮和宏安全性设置等。通过本章的学习,读者能够利用For循环和录制宏解决工作与学习中遇到的需要执行大量重复操作的问题。

第3章,介绍了VBA的第二个逻辑控制语句:If函数,并且围绕If函数介绍了Range(单元格)对象的简单用法、在工作表中删除整行数据时的注意事项,以及使用Exit For语句退出For循环等内容。在学完本书的前3章后,读者可以利用For循环和If函数解决大部分的单元格取值问题。

第4章,正式引入VBA中对象的概念。本章介绍了Worksheets(工作表)对象和Sheets(表)对象的主要方法与属性,以及Application(主程序)对象的DisplayAlerts(报警显示)属性。本章内容能够使读者对VBA中的对象、方法和属性有一个初步认识。

第5章,介绍了Workbooks(工作簿)对象的主要方法和属性,以及For Each循环的使用方法。在学完本章后,读者能够掌握跨表、跨文件操作数据的基本方法。

第6章,介绍了Range(单元格)对象的主要方法和属性,以及用于获取工作表最后一行数据行号的固定表达式。

第7章,在继续介绍Range对象的同时,还介绍了如何优化和改良编写的VBA代码,如何使用Range对象的筛选方法代替For循环以提高代码的执行效率,以及如何使用MsgBox函数和InputBox函数提高代码的互动性等。

第8章,介绍了VBA中的事件和事件的调用,以及工作表和工作簿中常用的事件,还介绍了With语句的用法。从本章开始,读者会逐渐意识到,编写VBA代码时,Sub和End Sub并非只限定了VBA代码的书写范围,它们还有更深层次的含义。

第9章,主要介绍了VBA中的两类函数:工作表函数和VBA函数。工作表函数是指在Excel中原本就存在的函数,这类函数的功能和使用方法与Excel中的基本一致;而VBA函数是仅存在于VBA中的函数,Excel无法直接调用。本章还介绍了中止编辑器报错的方法。

第10章,介绍了VBA的自定义函数和带参数的过程,以及如何把编写的VBA过程添加到Excel的加载宏中。通过前10章的学习,读者会对VBA代码的结构有比较清晰的认识,并且具备利用VBA解决大多数Excel数据问题的能力。

第11章,介绍了Dir函数的使用方法,以及如何使用关键字Set将对象赋值给变量、Range对象的Find方法等。

第12章,介绍了VBA中数组的使用方法,以及如何利用Timer函数计算代码的执行时间、如何使用GoTo语句退出循环等。

第13章,介绍了ActiveX控件的属性和事件。

第14章,介绍了VBA中窗体的相关知识。通过第13章和第14章的学习,读者将具备使用VBA创建系统前台界面并编写相关代码的能力。

第15章,介绍了VBA中的各种用户信息交互函数,以便让用户在使用VBA编写的各种宏和工具时,拥有更好的使用体验。

第16章,介绍了VBA中的ADO对象。

第17章,介绍了VBA的几种常用自学方法。

第18章,简单介绍了类模块的部分知识,让读者对类模块有个大致了解,并对VBA的整个知识体系加深认识。本章还介绍了VBA中Do-While循环的使用方法。

第19章,介绍了如何利用字典去除数据中的重复值,以及如何利用窗体和控件合理创建用户界面。

第20章,完成商品收银系统用户界面的创建工作,并将完成的用户界面与后台的Access数据库进行关联,最终得到一个完整的C/S架构的小型系统。

VBA零基础人员。

日常工作中需要频繁接触Excel并且需要操作大量数据的人员,如财务人员、销售人员和采购人员等。通过对本书的系统学习,他们可以利用VBA大幅提高工作效率。

就职于公司信息部、需要为公司其他人员解决Excel难题的运维人员。利用VBA为他人解决问题的最大优势在于无须教会他人解题的思路和步骤,只需要将编写好的宏或绑定了宏的其他控件交给他人使用。

希望尝试自主开发但又未能系统学习其他编程语言的IT从业人员。相比其他编程语言,VBA的学习门槛更低、使用自由度更大、对新手更加友好。


河北师范大学软件学院采用“校企合作”的办学模式。在课程体系设计方面,与市场接轨;在教师配备方面,大量聘用来自企业一线的工程师;在教材和实验手册建设方面,结合国内优秀教材的知识体系,大胆创新,开发了一系列理论与实践相结合的教材(本书即是其中一本)。在学院新颖模式的培养下,百余名学生进入知名企业实习,有的已签订就业合同,得到了用人企业的广泛认可。这些改革成果的取得,不仅要感谢河北师范大学校长蒋春澜教授的大力支持和鼓励,还要感谢河北师范大学校党委对这一办学模式的肯定与关心。

借此机会对河北师范大学数信学院院长邓明立教授,软件学院副院长赵书良教授和李文斌副教授表示感谢,他们为本书的写作提供了良好的环境,为本书内容的教学实践“保驾护航”,同时还为本书提供了大量案例和建议。感谢河北师范大学软件学院教学团队的每一位成员,以及河北师范大学软件学院每一位学生热情的帮助和支持。

最后,感谢作者的家人在本书创作过程中给予的支持与理解。


本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。

本书提供如下资源:

要获得以上配套资源,请在异步社区本书页面中点击,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。

如果您是教师,希望获得教学配套资源,请在社区本书页面中直接联系本书的责任编辑。

作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。

当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,点击“提交勘误”,输入勘误信息,点击“提交”按钮即可。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。

我们的联系邮箱是contact@epubit.com.cn。

如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。

如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线提交投稿(直接访问www.epubit.com/selfpublish/submission即可)。

如果您是学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。

如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。

“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT技术图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT技术图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。

“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近30年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端、网络技术等。

异步社区

微信服务号


VBA(Visual Basic for Application)是一种基于Visual Basic的宏编程语言。

微软公司开发VBA的初衷是扩展Windows应用程序,尤其是Microsoft Office系列办公软件的功能。因此,VBA的存在,为Office增添了无限的可能。VBA不但可以简化办公软件中的复杂工作,减少不必要的重复操作,大幅提高工作效率,而且能为Excel或者其他Office应用程序添加很多特色各异的小程序,极大地丰富Office的功能。

此外,虽然必须依附其他应用程序,但是VBA的开发功能依旧很强大。搭配Excel或者Access数据库,VBA能够开发出一套完整的、C/S架构的系统,而且学习门槛极低。因此,可以说VBA为业余编程爱好者敞开了系统开发的大门。

为了让广大Office Excel用户能够享受VBA带来的种种便利,也为了让更多的编程爱好者通过VBA进入系统开发的世界,本书将以实践驱动理论的形式,通过92个案例,抽丝剥茧、层层递进地介绍VBA的各个方面。

本章将介绍以下内容:

由于VBA基于VB(Visual Basic)发展而来,因此,从语言结构上而言,VBA可被视为VB的子集,二者语法结构一样,开发环境高度相似。不同之处在于,VB拥有独立的开发环境和编译系统,无须依附于其他应用程序;而VBA无法独立运行,必须依附于某一个主应用程序,如Word、Excel、Access等。

这种依附关系使得VBA与主应用程序之间的通信变得简单而高效。例如,编写VBA代码访问和操作Excel中的数据,大部分情况下直接指定对象即可实现访问和操作,无须设定文件路径、环境变量和其他参数。

各个Office应用程序都提供了录制宏功能,这意味着在编写某个具体操作的VBA代码时,若遇到阻碍,除可以翻阅相关资料以外,还可以通过录制宏获取所需的代码。这大大降低了VBA的学习难度,也为后续深入学习提供了便利。

由于VBA可在各个Office应用程序中通用,因此掌握了如何在Excel中运用VBA,就同时具备了在Word、Access和PowerPoint中使用VBA的能力。

作为Visual Basic的子集,VBA同样继承了可视化(visual)编程形式。换言之,在利用VBA进行程序开发时,可以随时、随意地调整用户界面的图像、大小和颜色等。这与某些编程语言需要编写代码来处理用户界面截然不同。VBA提供了窗体和插件等可视化设计工具,程序员只需要根据需求“画出”用户界面的布局和各种图形,并设置相关属性。这种设计至少减少开发过程中50%的工作量,程序员不必再为设计用户界面编写大量代码,也不必一定要等到程序执行时才能看到界面效果,对界面不满意时,不必返回代码中进行修改。这是VBA作为一种编程语言,学习门槛极低、使用自由度极高的重要原因。

VBA必须依附于某个主应用程序,无法直接在Windows系统中打开。那么,如何在Excel中打开VBA呢?

以Office Excel 2016为例,如果第一次使用VBA,那么需要单击Excel功能区中“文件”标签下的“选项”按钮,打开“Excel选项”对话框,然后选中“自定义功能区”,在右侧“主选项卡”中的“开发工具”前打“√”,如图1-1所示。

图1-1 “Excel选项”对话框

在设置完成后,单击“确定”按钮,此时Excel功能区中会增加一个“开发工具”标签。单击“开发工具”标签,可以看到一组如图1-2所示的按钮。

图1-2 “开发工具”标签下的按钮

这组按钮最左侧为“Visual Basic”,单击该按钮,即可弹出图1-3所示的VBA编辑器。

图1-3 VBA编辑器

小贴士:在VBA编辑器的“视图”菜单中,可以选择打开或关闭各种窗口、浏览器和管理器,其中常用的是“工程资源管理器”和“属性窗口”。我们可将“工程资源管理器”和“属性窗口”分上下置于编辑器的左侧,以便随时查看和使用。

在其他版本的Excel和其他Office应用程序中,打开VBA的方法与上述方法类似。

下节将通过案例01介绍如何在VBA中执行一段代码,并了解VBA过程代码的结构,以及逻辑控制语句——For循环。

以Excel 2016为例,如果要在工作簿中新增一张工作表,那么,首先使用鼠标右键单击工作簿左下角的“Sheet1”标签,然后单击“插入”,即可弹出图1-4所示的窗口。先选择窗口中的“工作表”,再单击“确定”按钮,即可添加一张工作表。

当然,也可通过单击“Sheet1”标签旁的加号快速新增一张工作表。但是,如果要新增100张工作表,上述两种方式似乎都无法快速完成。那么,本书的案例01就来介绍如何使用VBA快速新增100张工作表。

图1-4 在工作簿中新增一张工作表

在编写VBA代码之前,首先要在编辑器中创建一个模块,步骤如下:右键单击“工程资源管理器”,先选择“插入”,再选择“模块”,如图1-5所示,即可在编辑器中插入一个模块。

图1-5 在编辑器中插入一个模块

插入模块后,编辑器会打开一个代码窗口,如图1-6所示。编辑器中可同时存在多个模块,在模块的代码窗口中,可以编写和执行VBA代码。

在代码窗口中,输入新增100张工作表的代码(详见1.3.2节),然后单击图1-7中的“执行”图标按钮。

图1-6 模块1的代码编辑窗口

图1-7 代码执行按钮

如果代码存在错误,那么单击“执行”图标按钮时会弹出错误提示;如果代码能够正确执行,则不会弹出提示。

单击“执行”图标按钮后,切换回Excel,可以看到VBA已经为工作簿新增了100张工作表,如图1-8所示。案例01完成。

图1-8 使用VBA代码增加了100张工作表

图1-7中的代码详见代码清单1-1。

代码清单1-1

Sub test()
     For i = 1 To 100
          Sheets.Add
     Next
End Sub

代码清单1-1以关键字Sub开始,以关键字End Sub结束,这也是所有VBA过程代码的统一结构。过程是指一段完整的、可以执行的VBA代码。关键字Sub后面紧跟过程名,如代码清单1-1的过程名为“test”。

小贴士:在计算机编程语言中,关键字是指事先定义的、有固定用法的标识符,也称为保留字。VBA的关键字在编辑器中会被自动标为蓝色,以示区分。

代码清单1-1的主体部分是一个For循环。在VBA中,For循环用于重复执行一行或多行代码,并且利用循环控制变量(也称为计数器或计数变量)控制循环的次数。For循环的语法为:

For 计数变量 = 起始值 to 结束值 [ step 步长值 ]
     动作1 
     动作2
     ……
     动作N
Next

For循环的代码结构以关键字For开始,以Next结束。计数变量在起始值至结束值之间、按步长值(如有)的幅度依次取值。For循环的循环次数计算公式为:

循环次数 = (计数变量的结束值 - 计数变量的起始值 + 1) / 步长值

在代码清单1-1中,For循环的计数变量i取值范围为1至100,且没有设置步长值,那么步长值取默认值1,计算可得代码清单1-1中For循环的循环次数为100次。循环体中的代码“Sheets.Add”表示新增一张工作表,因此整个For循环表示新增了100张工作表。

案例01的重点是展示如何在VBA中编写和执行代码,以及VBA过程代码的结构。案例01的代码比较简单,无须详细解释,读者也能了解大致含义。

For循环无论是在VBA中还是在其他编程语言中,都有相当重要的地位,因为For循环可用于快速执行大量重复操作,还可进行迭代取值。在本书后续章节中,For循环的出镜率相当高,如果在案例01中还未对For循环有深刻的了解,那么在后续的案例中还有很多学习和练习的机会。

作者认为,学习VBA(也包括其他编程语言),案例实操比背诵概念更为重要,因此希望读者能够在阅读案例解析之后,先动手编写代码,再与书中的代码进行比较。这种学习方式可以让学习过程不会太枯燥,还能有效提升代码编写能力,并加深对相关概念的理解。


本章涉及的概念性内容较多,包括关键字、变量、宏按钮、宏安全性等。同时,本章还包括以下主要内容:

学完以上内容后,读者即可利用录制宏与For循环解决工作和学习中需要大量重复操作的问题。从本章开始,请读者务必跟随本书动手编写每一段代码,以求快速和牢固地掌握与理解每个知识点。

本书附带的“案例资料”中含有学习案例时需要用到的Excel文件,案例02对应的Excel文件为“案例02:对不同工作表执行相同操作.xls”。打开该文件,可以得到图2-1所示的多张工作表。

图2-1 案例02对应的Excel文件

本案例要求对工作簿中的所有工作表依次进行如下操作:

因为案例02需要对多张工作表进行重复操作,所以可以考虑先操作一张工作表,并把操作的过程录制成宏,再在其他工作表上执行宏。

在Excel中,一个(Macro)其实就是一个VBA过程,只不过VBA过程是一段完整的VBA代码,而宏被具体成一个单独的命令。宏的作用与过程一样,可以按照一系列预定义规则完成一个指定的任务。

Excel的录制宏功能可将一组操作或者完成某项任务的步骤录制下来,转换为VBA过程代码,并形成宏命令,以便再次执行。

单击Excel功能区的“开发工具”标签中的“录制宏”按钮,会弹出图2-2所示的“录制宏”对话框。

图2-2 “录制宏”对话框

图2-2中的“宏名”可以根据实际需要填写,也可以使用默认名字,如“宏1”。其他选项可不用设置,直接单击下方的“确定”按钮。此时,“开发工具”标签中的“录制宏”按钮会变成“停止录制”按钮,如图2-3所示。从此刻起,所有在Excel中的动作都会被录制下来,直至单击“停止录制”按钮,录制结束。

图2-3 “录制宏”按钮变成了“停止录制”按钮

根据案例02的要求,在录制宏的状态下,在“1月”工作表中进行如下操作:

完成以上所有操作后,单击“停止录制”按钮。

打开“2月”工作表,在“开发工具”标签中单击“宏”按钮,会弹出图2-4所示的对话框,在“宏名”选项框中选中“宏1”(或自定义的其他宏名),单击“执行”按钮。

图2-4 “宏”对话框

在“2月”工作表中执行“宏1”后,效果如图2-5所示,符合本案例要求。在其他工作表中,执行“宏1”也会有同样的效果。案例02完成。

图2-5 在“2月”工作表上执行宏1的结果

注意,只有当工作表格式与“1 月”工作表完全一致时,“宏 1”的执行结果才能确保正确,这也是录制的宏在执行时必须满足的先决条件。例如,在“4月”工作表的最左侧插入一个空白列,使之与“1月”工作表的格式出现差异,如图2-6所示。

图2-6 在“4月”工作表的最左侧插入一个空白列

然后,在“4月”工作表上,执行“宏1”,就会出现错误的结果。

小贴士:使用宏执行的操作无法被撤回,因此,在工作表中使用宏执行操作时,一定要提前做好备份,以便在出现错误结果后能够使用备份文件还原数据。

本案例的代码暂时不需要详细解读,读者只需要知道如何在Excel中找到录制的宏代码。在Excel的“开发工具”标签中,单击“Visual Basic”,打开编辑器,然后双击“工程资源管理器”中的“模块1”,“宏1”的代码会显示在“模块1”的代码窗口中,如图2-7所示。

图2-7 “宏1”的VBA代码

如果“工程资源管理器”中有多个模块,那么最后录制的宏代码一般被保存在最后一个模块中;如果模块中有多个过程(多段VBA代码),那么过程名与宏名相同的代码就是录制的宏代码。

图2-7中的代码就是案例02所需的代码,详见代码清单2-1。

代码清单2-1

Sub 宏1()
    Columns("C:E").Select
    Selection.Delete Shift:=xlToLeft
    Columns("G:G").Select
    Selection.Cut
    Columns("B:B").Select
    Selection.Insert Shift:=xlToRight
    Columns("G:G").Select
    Selection.AutoFilter
    ActiveSheet.Range("$G$1:$G$114").AutoFilter Field:=1, Criteria1:=">200",
         Operator:=xlAnd
End Sub

本案例引入了宏的概念,还介绍了如何在Excel中录制宏、如何执行宏,以及如何在Visual Basic编辑器中找到录制的宏代码等。

通过本案例,读者还应了解,虽然通过录制宏可以对不同的工作表进行相同的操作,但是必须保证不同工作表的格式一致。因此,在VBA的学习和使用过程中,录制宏往往并非解决问题的最终方法,而是获取解决问题所需代码的手段。

案例03要求先在工作表的一列中输入“2020年1月1日”至“2020年12月31日”,如图2-8所示,再用深色填充色将所有是周日的日期标记出来。

图2-8 2020年全年的日期

如果使用键盘和鼠标,那么,首先需要找到2020年的第一个周日,也就是2020年1月5日,并将该日期的单元格的填充色改成深色,然后每隔6个单元格改一次填充色,重复操作,直至2020年所有的周日被标记。

既然本案例需要执行大量重复操作,那么可以考虑使用录制宏。在录制宏之前,先介绍绝对引用和相对引用的概念。

宏执行的操作一定会在录制时选中的单元格或区域中进行,这被称为绝对引用。例如,在绝对引用下,开始录制宏,然后选中A1单元格,改变其填充色,停止录制。在其他任意工作表上执行该宏,A1单元格都会被选中并改变填充色。

但是,绝对引用仅针对选中操作。如果录制过程中没有选中操作,那么绝对引用将不起作用。还是以改变单元格填充色为例,在录制开始前,首先选中某个单元格;然后,开始录制宏;接着,改变单元格填充色;最后,停止录制。在执行宏时,我们会发现,选中任意工作表的任意单元格都能改变其填充色。对于以上操作,建议读者亲自测试并验证,以加深理解。

录制宏的另一种引用方式为相对引用。相对引用是指宏记录的并非操作单元格或区域的具体位置,而是单元格或区域的位置变化。在Excel的“开发工具”标签中,“录制宏/停止录制”按钮的下方就是“使用相对引用”按钮,如图2-9所示。

针对案例03,我们可以分别使用绝对引用和相对引用录制宏,看看得到的宏有何区别。

先使用绝对引用。首先,选中2020年的第一个周日,也就是“2020年1月5日”所在的A5单元格,然后开始录制宏,改变A5单元格的填充色,接着选中下一个周日,也就是“2020年1月12日”所在的A12单元格,停止录制。

图2-9 “使用相对引用”按钮

执行得到的宏,其效果为改变当前选中单元格的填充色,然后选中A12单元格。很明显,使用绝对引用录制的宏无法满足案例03的要求。

再使用相对引用。在功能区的“开发工具”标签中选中“使用相对引用”按钮(选中后文字变为深色),然后选中A5单元格,开始录制宏,改变A5单元格的填充色,选中A12单元格,停止录制。重新选中A5单元格并执行宏,A5单元格的填充色被改变且A12单元格被选中;再次执行宏,A12单元格的填充色被改变且A19单元格被选中;第三次执行宏,A19单元格的填充色被改变且A26单元格被选中……如图2-10所示。

图2-10 使用相对引用录制的宏可改变当前单元格的填充色并下移7个单元格

由此可知,本案例中使用相对引用录制的宏可以改变当前选中单元格的填充色,并将光标下移7个单元格。因此,只要选中A5单元格(2020年的第一个周日),并将该宏执行足够多次数,就能将2020年所有的周日标记出来。

但是,将所有周日都标记出来,需要将宏执行50次以上,工作量依然很大。为了提高工作效率,可将录制的宏代码嵌入For循环,以此来代替手动执行宏。打开Visual Basic编辑器,在模块中找到使用相对引用录制的宏代码,如图2-11所示。

图2-11 使用相对引用录制的宏代码

为了便于区分和修改,建议重新创建一个过程,可将其命名为“标记”或其他符合VBA规则的过程名,并将图2-11中“宏1”过程的主体部分复制到该过程中,如图2-12所示。

图2-12 创建一个新的过程,并将录制得到的代码复制至其中

现在“标记”过程的执行效果为:修改当前选中单元格的填充色,然后使鼠标光标下移7个单元格。该执行效果与录制得到的“宏1”相同。

因为2020年一共有52个周日,所以需要将“标记”过程的主体部分嵌入For循环执行52次,那么计数变量的取值范围应设为1~52。For循环的代码详见代码清单2-2。

代码清单2-2

For i = 1 To 52
……
Next

小贴士:编写VBA代码时,可不区分大小写,编辑器会根据需要自动转换,如将代码中的for自动转换为For,将next自动转换为Next。

虽然默认情况下Visual Basic编辑器不要求在代码中事先定义变量,但是为了增加代码的可读性,也为了避免错误,编写代码时应养成定义变量的好习惯。定义变量是指在使用变量前先声明其数据类型,而未被定义的变量,其数据类型是不确定的,因此,在使用时编辑器无法为其提供足够多的信息支持。

根据使用环境可知,For循环中的计数变量i的类型为整数型,因此,可在过程中增加一行代码,将变量i的数据类型定义为整数型:

Dim i As Integer

将代码清单2-1和代码清单2-2整合到一起,即可得到“标记”过程的完整代码,如代码清单2-3所示。

代码清单2-3

Sub 标记()
     Dim i As Integer
     For i = 1 To 52
         With Selection.Interior
              .Pattern = xlSolid
              .PatternColorIndex = xlAutomatic
              .Color = 65535
              .TintAndShade = 0
              .PatternTintAndShade = 0
         End With
         ActiveCell.Offset(7, 0).Range("A1").Select
     Next
End Sub

代码清单2-3的“标记”过程在Visual Basic编辑器中的显示详见图2-13。

图2-13 “标记”过程代码

切换至Excel程序,选中工作表的A5单元格(即2020年1月5日),然后在“宏”对话框中选中“标记”宏,并单击“执行”按钮,如图2-14所示。

图2-14 执行“标记”宏

执行“标记”宏后,工作表中2020年所有周日对应的日期均会被标记,如图2-15所示。

图2-15 所有周日对应的日期均被标记

注意,在执行“标记”宏之前,必须先选中A5单元格,再执行宏。

本案例“复习”了录制宏和For循环,重点介绍了绝对引用和相对引用,以及如何对录制的宏代码进行修改。

本案例的“标记”宏还遗留了一个小问题,如果在执行宏之前没有正确选择起始单元格(A5单元格),执行结果就会出现错误。这个问题的解决方法将在后续章节中介绍。

案例04的资料文件“案例04:工资表改工资条.xls”为某公司某月的工资表,如图2-16所示。

图2-16 工资表

财务人员每个月都会通过财务软件导出工资表,然后制作成工资条,裁剪并分发给每个员工。本案例要求编写VBA代码,实现将图2-16所示的工资表转换为图2-17所示的工资条。

图2-17 工资条

想要将图2-16所示的工资表转换为图2-17所示的工资条,就需要在工资表中为每一行数据创建一个表头。表头可以通过复制工资表第一行获得,步骤如下:选中工资表第一行,右键单击并选择“复制”,如图2-18所示。

图2-18 复制表头

然后选中工资表第3行,右键单击并选择“插入复制的单元格”,如图2-19所示。

图2-19 在工资表第3行插入表头

完成以上操作后,工资表原来的数据会从第3行开始全部下移一行,而现在的第三行是一个新的表头,且为被选中状态,如图2-20所示。

图2-20 第3行插入表头后的工作表

接下来,直接复制第3行的表头,插入第5行;复制第5行的表头,插入第7行;复制第7行的表头,插入第9行……直至得到图2-17所示的工资条。

因此,可先选中工资表的第1行,然后使用相对引用,将“复制第1行表头并插入第3行”的操作录制成宏,所得宏代码的主体部分如代码清单2-4所示。

代码清单2-4

Selection.Copy
ActiveCell.Offset(2, 0).Rows("1:1").EntireRow.Select
Selection.Insert Shift:=xlDown

代码清单2-4中的3行代码的含义分别为:复制当前选中的行、下移两行、插入复制的行并选中。现在只需要将代码清单2-4嵌入For循环,然后执行足够多次数,就能实现为工资表的每一行添加一个表头的目的。

案例04的工资表一共需要插入10个表头,因此For循环计数变量的取值范围应为1到10,无须设置步长。案例所需For循环代码如代码清单2-5所示。

代码清单2-5

For i = 1 To 10
……
Next

注意,在录制所得的宏代码中,必须先选中工资表的第1行,这样才能正确插入表头。因此,可考虑将“选中第1行”这个操作写入过程中,相关代码可通过录制宏获取,见代码清单2-6。

代码清单2-6

Rows("1:1").Select

注意,录制代码清单2-6所示的宏时,应使用绝对引用。

将上述代码进行合并,即可得到本案例所需的“工资条”过程,完整的代码见2.3.2节。

在Excel中,执行“工资条”宏,工资表即可转变成图2-21所示的工资条。

宏(VBA过程)的使用者往往并非开发者本身,如本案例的“工资条”宏,使用更多的应该是公司的财务人员。而公司的财务人员可能并不了解VBA,也不知道如何在Excel功能区的“开发工具”中执行宏。因此,可考虑在工作表上创建一个按钮并绑定宏,以便执行。

图2-21 执行宏后得到的工资条

在“开发工具”标签中,单击“插入”按钮,可看到两组控件:“表单控件”和“ActiveX控件”,如图2-22所示。其中“ActiveX控件”功能强大,可以创建丰富的事件,但是需要编写VBA代码才能使用,本书后面的章节会有详细介绍;而“表单控件”(在较早版本的Excel中称为“窗体控件”)使用起来相当便捷,虽然功能比较单一,但已能满足本案例的需求。

图2-22 “表单控件”和“ActiveX控件”

单击“表单控件”中的第一个控件(按钮),将鼠标光标移动到工作表区域后,鼠标光标会变成一个小十字。按住左键拖动十字光标,画出按钮的形状,然后松开,Excel会弹出“指定宏”对话框。在该对话框中,可将创建的按钮与当前已有的宏进行绑定,如图 2-23所示。

在图2-23中,选中“工资条”宏,然后单击对话框中的“确定”按钮,工资表上就会出现图2-24所示的“按钮1”。“按钮1”的位置、形状和大小由之前拖动鼠标的操作决定。

图2-23 “指定宏”对话框

右键单击“按钮1”即可进入编辑状态,此时可单击或拖动鼠标改变按钮的大小和位置,也可在单击“编辑文字”菜单项后修改按钮上的文字,如将“按钮1”改成“工资条”。如果在之前的“指定宏”对话框中错误选择了需要绑定的宏,那么可通过选择“指定宏”菜单项再次打开“指定宏”对话框,重新绑定宏,如图2-25所示。

图2-24 在工作表中添加“按钮1”

单击工作表的任意区域,将按钮从编辑状态中释放,此时,单击按钮,即可执行按钮绑定的宏。

按钮被单击后,其形状、大小和位置可能会随着宏的执行产生变化,这是因为还需要对按钮的属性进行设置。右键单击按钮,选择“设置控件格式”,在弹出的对话框中,打开“属性”标签,将“对象位置”单选菜单中的选项由默认的“大小、位置随单元格而变”更改为“大小、位置均固定”,然后单击“确定”按钮,如图2-26所示。如此设置,即可保证按钮不会随着宏的执行而产生变化。

图2-25 按钮的大小、位置、文字,以及绑定的宏都可以修改

图2-26 设置按钮的属性

如果财务人员在打开含有宏的Excel文件时弹出错误提示,提示无法执行宏,则需要进行宏的安全性设置。在Excel的功能区,打开“开发工具”标签,单击“宏安全性”按钮,在弹出的“信任中心”对话框中选择“宏设置”菜单,然后在右侧的“宏设置”单选菜单中选    择“启用所有宏(不推荐:可能会运行有潜在危险的代码)”,单击“确定”按钮,如图2-27所示,之后就能正常打开含有宏的工作簿了。

图2-27 修改宏安全性

案例04的“工资条”过程代码详见代码清单2-7。

代码清单2-7

Sub 工资条()
    Dim i As Integer      '定义计数变量i
    Rows("1:1").Select    '选中工资表第1行
    For i = 1 To 10       '定义For循环的执行次数
         Selection.Copy
         ActiveCell.Offset(2, 0).Rows("1:1").EntireRow.Select
         Selection.Insert Shift:=xlDown
    Next
End Sub

小贴士:代码清单2-7使用了英文单引号“'”为代码进行注释。注释有利于代码阅读,以及后期对代码进行排错和修改,因此,开发人员应养成为代码注释的好习惯。

经过之前两个案例的学习,录制宏和编写For循环代码已不再是本案例的难点。确定录制宏时的步骤成为了本案例的关键。

本案例录制了选中表头并复制、下移两行和插入表头3个步骤的宏代码。因为使用了相对引用,所以录制的宏代码在执行完第三个步骤后,又可在For循环中无缝衔接第一个步骤,继续执行下一个循环。

本案例还介绍了如何设置宏按钮和宏安全性。

本案例的资料文件“案例05:恢复工资表.xls”中有一张工资条样式的工作表,如图2-28所示。现要求编写VBA代码,将图2-28中的工资条恢复成图2-16所示的工资表样式,结合案例04中的代码,在工作表中添加两个按钮:“生成工资条”和“恢复工资表”,并分别绑定对应的宏。

图2-28 工资条

在将工资条恢复成工资表时,需要将多余的表头逐一删除。

首先整理逐一删除多余表头的操作,每选中一行表头并删除,Excel会自动将下方数据上移一行,因此当前选中行的下一行是另一个表头,如图2-29所示。因此,我们得到录制宏的两个重复步骤:删除选中的行,然后选中下一行。

图2-29 删除一行表头后,将光标下移一行,即可选中下一行表头

使用相对引用录制上述两个步骤(注意,在开始录制前,应先选中表头),代码如代码清单2-8所示。

代码清单2-8

Selection.Delete Shift:=xlUp
ActiveCell.Offset(1, 0).Rows("1:1").EntireRow.Select

将代码清单2-8嵌入For循环,重复执行足够多次数,即可完成本案例。注意,在执行For循环之前,应先选中工作表第3行(第一个多余表头),相关代码可通过录制宏获取(录制时使用绝对引用),也可参照2.3.1节中的代码清单2-6进行修改,结果如代码清单2-9所示。

代码清单2-9

Rows("3:3").Select

“恢复工资表”的代码见代码清单2-10。

代码清单2-10

Sub 恢复工资表()
    Dim i As Integer          '定义For循环的计数变量
    Rows("3:3").Select        '选中工资表第3行的表头
    For i = 1 To 10           '重复10次“删除整行并下移一行”的操作
         Selection.Delete Shift:=xlUp
         ActiveCell.Offset(1, 0).Rows("1:1").EntireRow.Select
    Next
End Sub

在实际工作中,很难遇见将工资条恢复成工资表样式的需求,本案例的意义在于再次尝试整理出解决问题时需要重复操作的步骤。

提醒一下,在执行宏之前,务必备份工作表,因为宏的操作无法撤回

本案例还需要在工作表上创建两个按钮:“生成工资条”和“恢复工资表”,并分别绑定案例03和案例04中的宏,结果如图2-30所示。

图2-30 工作表上的按钮


相关图书

ChatGPT写作超简单
ChatGPT写作超简单
Word/Excel/PPT  AI办公从新手到高手
Word/Excel/PPT AI办公从新手到高手
精通Excel数据统计与分析
精通Excel数据统计与分析
和秋叶一起学Excel(第3版)
和秋叶一起学Excel(第3版)
和秋叶一起学PPT(第5版)
和秋叶一起学PPT(第5版)
Excel高效办公——表格、图表、透视表、函数、数据分析5项修炼
Excel高效办公——表格、图表、透视表、函数、数据分析5项修炼

相关文章

相关课程