标签:VBA,对象模型
要编写Excel VBA程序,必须知道对象。可以认为,VBA基于面向对象编程,这意味着VBA程序主要是在处理(或操控)对象。因此,我们要掌握ExcelVBA编程,必须理解:
1.什么是对象
2.如何操控VBA对象
3.Excel VBA对象模型
刚开始接触对象和对象模型的朋友,可能会被一些概念搞糊涂,这是正常的,随着不断地学习和使用,你的理解会越来越深入,这些概念也会逐渐清晰起来。
基本说来,Excel VBA对象模型是编程时可以使用的对象的层次结构,它使得引用要操控的对象更容易。
对象层次结构如下:
层级1:在最顶端,只有一个对象。
层级2:层次结构顶部的对象包含的一些对象。
层级3:层级2中的对象可能包含的一些对象。
层级4:层级3中的对象可能包含的一些对象。
…
对象可能包含其他对象。该过程会重复,直到到达不包含任何其他对象的对象。
通常,层次结构顶部的对象是Application对象,即层级1的对象是应用程序本身。对于Excel来说,Application对象就是Excel本身。
Application对象包含其他VBA对象。Excel的Application对象包含的一些主要对象为:
- AddIns,包含所有的加载项对象。
- Windows,包含应用程序所有Window对象。
- Workbooks,包含所有Workbook对象。
这些VBA对象中的每一个又包含其他对象。例如,Workbook对象中包含的一些VBA对象如下:
- Charts,包含Chart对象。
- Names,包含Name对象
- VBProjects,代表打开的项目。
- Windows,包含指定Excel工作簿中的Window对象。
- Worksheets,包含Worksheet对象。
同样,这些VBA对象包含其他对象。例如Worksheet对象包含下列VBA对象:
- ChartObjects,包含ChartObject对象。
- Comment,代表单元格批注。
- Hyperlink,代表超链接。
- Name,代表为特定单元格区域定义的名称。
- PageSetup,用于存储打印信息。
- PivotTables,包含PivotTable对象。
- Range,代表单元格、行、列、所选择的单元格,或三维单元格区域。
如果以图形描述,上述Excel VBA对象层次结构大致如下所示:
注:上图仅仅是Excel VBA对象模型层次结构的很小一部分。但不要着急,在编程时,我们通常只使用其中一些常用的对象,即便需要使用一些不常见对象,也能很快在Excel对象模型参考中找到,或者通过宏录制器录制宏来找到想要用的对象。
下面,我们来看看Excel VBA对象模型层次结构背后的逻辑。
对象集合
集合有两个显著特征:它们本身就是对象;它们的主要目的是对同一类的VBA对象进行组合和管理。
因此,集合是用于组合和管理其他对象的对象。
在某些情况下,集合非常有用。例如,假设想对一组特定的对象执行某些操作,如果所有这些对象都是同一集合的一部分,则可以构造VBA代码以遍历集合的每个成员并执行所需的操作。可以想得到,这种结构比单独列出每个集合成员更简单。
所以,集合允许同时处理一组完整的VBA对象,而不是处理每个单个的对象。
以下是常见集合的示例:
- Workbooks,当前打开的所有Excel工作簿的集合。
- Worksheets,特定工作簿中所有Excel工作表的集合。
- Charts,特定工作簿内所有图表工作表。
- Sheets,特定工作簿中所有工作表的集合,此时与工作表类型无关,包含常规工作表和图表工作表。
引用对象
在编写VBA代码时,了解如何引用对象是至关重要的。很明显,想要开始处理特定的VBA对象时,必须先识别它,也就是说,告诉VBA要处理哪个对象。
如果遍历Excel VBA对象模型的整个层次结构来引用对象,则称为完全限定引用。
我们已经知道,Excel对象模型层次结构的顶部是Application对象,因此引用这个对象很简单,只需输入:
Application
从这里开始,需要使用点(.)运算符开始沿着层次结构移动,即使用点(.)将每个VBA对象连接到上一个对象(对象的父对象)。这些点(.)用于自上而下连接并引用ExcelVBA对象模型的成员。
例如,假设要引用Range对象,参考上图所示的对象模型层次结构,Range对象处于第4层:
现在,自顶而下使用(.)连接这些不同的对象,从而引用Range对象:
Application.Workbooks.Worksheets.Range
注意,这只是基本的引用框架,并没有实际识别单个的VBA对象,即如果有几个工作簿或工作表,如何知道引用哪个?如何知道要处理的具体单元格区域。
这就需要处理如何引用集合内的特定对象。可以使用两种方法。
方法1:使用对象名称,其语法为:集合名(“对象名”)。例如,如果要处理工作表Sheet1,则可以使用:
Worksheets(“Sheet1”)
或者:
Sheets(“Sheet1”)
方法2:使用索引号,其语法为:集合名(索引号)。这样,上面的代码可修改为:
Worksheets(1)
或者:
Sheets(1)
好了,解释清楚这些后,我们回过去看如何引用具体的Range对象。假设要处理工作簿Book1的工作表Sheet1中的单元格A1,则其完全限定引用为:
Application.Workbooks(“Book1.xlsm”).Worksheets(“Sheet1”).Range(“A1”)
正如你所看到的,完全限定引用需要编写很长的代码,繁琐且难以阅读。实际上,可以简化对象引用,使代码更简短。
之所以能够简化完全限定引用,是因为Excel VBA对象模型有一些默认的对象,当没有明确输入时,Excel会假设你引用的是这些对象。
下面来看看一些简化引用的情形。
情形1:Application对象
Excel总是假设你在处理Application对象,因此,可以从引用中忽略该对象。这样,上面的完全限定引用代码可简化为:
Workbooks(“Book1.xlsm”).Worksheets(“Sheet1”).Range(“A1”)
情形2:当前工作簿和当前工作表
Excel总是假设你在处理当前工作簿(标准模块中代码所在的工作簿),如果你的目的是处理当前工作簿,则上面的代码可进一步简化为:
Worksheets(“Sheet1”).Range(“A1”)
如果你要处理的工作表是当前活动工作表,代码又可简化为:
Range(“A1”)
小结
如果想要精通Excel VBA,那么必须掌握ExcelVBA对象模型的原理。随着不断的学习和实践,你会更清楚其中的细节,ExcelVBA对象模型的结构和使用也会越来越熟练。