1、对象模型
上一讲说了Range对象,这一次我们从总体方面来说一下Excel VBA的对象模型。
你真正想了解Excel VBA里的对象的话,看官方文档是最好的,没有比官方文档更准确的了。然后就是自己去测试、使用,不会的就录制,多用就会逐渐的理解。
我们前面说过,Excel VBA的对象都是微软已经做好了,让我们来使用的,所以这些对象和我们平时普通操作Excel都是有联系的,每个对象你都可以想象是在手动操作Excel,手动操作说到底就是做好了一个图形界面让我们去操作,而使用VBA是在后台操作。
如果你看了官方文档,你应该已经发现Excel VBA里有好多对象,这些对象其实都是有层级关系的,就像一棵树一样,树顶上最高级的是Application,然后不停的分叉,衍生里众多的对象。
下图是网上下载的一个帮助文档:
地址:
http://club.excelhome.net/forum.php?mod=viewthread&tid=849024&extra=page=1&page=1&
2、Application对象
你打开一个Excel(注意不要有其他的Excel文件打开了),然后进入到代码编辑器,在菜单视图里点击立即窗口,在立即窗口输入:
代码语言:javascript复制ThisWorkBook.Close False
立即窗口是一个可以打印输出的窗口,方便调试用,也可以直接运行一些简单的代码,比如你想看一下单元格A1的值,直接在立即窗口输入:
代码语言:javascript复制?Range("A1").Value
记住有输出的要在前面加个问号,不需要输出的和平时写的语句一样。
这样你关闭了那个唯一打开的Excel文件,但是这时候,Excel这个程序并没有退出,你还可以看到1个界面,这个就是我们安装目录里,那个叫做EXCEL.EXE(我们双击打开这个,会自动创建1个新的工作簿)打开后的东西,也就是Excel VBA对象模型里的最高级的Application。
这个时候你再试试?Range("A1").Value看看,出错了吧,为什么呢?
这个时候最好自己先好好想一下,然后看看那个错误的提示框上什么意思,多想想。
对象定义错误:为什么会有这个错误?Range("A1"),因为这个Range对象根本不存在,我们通过ThisWorkBook.Close False这句代码,已经关闭了工作簿,当前根本没有了单元格了,操作根本不存在的东西,当然出错。
我们这么来理解看看,中国古代封建社会,比如周朝的时候,那时候的天下是1个天子、多个诸侯国、每个诸侯国里有多个家:
代码语言:javascript复制Application 天下 EXCEL程序
Workbook 国 工作簿
Workbooks 国的集合 所有打开的工作簿
Worksheet 家 工作簿里的工作表
Worksheets 家的集合 1个工作簿里所有的工作表
Range 人 单元格
Cells 家的所有的人 1个工作表里所有的单元格
在天下初建的时候,还没有分封国(Workbook),这时候的状态就和我们用ThisWorkBook.Close False关闭了唯一的工作簿一样,只有Application,也就是只有天下,还没有国。在立即窗口输入:
代码语言:javascript复制?Application.Workbooks.Count
可以看到,这种情况下,输出返回的是0,天下还没有国,Application还没有Workbook。
天子觉得这样管理太累,自然就要分封了,他分封一个国,在VBA里我们可以这样新建1个Workbook,在立即窗口输入:
代码语言:javascript复制Application.Workbooks.Add
这时候你能看到,出现了一个空白的工作簿Workbook了,再运行?Application.Workbooks.Count,就会输出1了。
我们要看看这个工作簿的名称:
代码语言:javascript复制?Application.Workbooks(1).Name
因为这个国Workbook是天子分封的第1个,所以在国集合Workbooks里,他的序号就是1。你可以继续Application.Workbooks.Add试试看。
国Workbook在建立的时候,天子规定了他必须至少要分封一个家,所以新建的Workbook里会有Worksheet,而我们所看到Worksheet的那些单元格,就是最基础的家的人了。
对象模型就是这样一层一层的下来的,你要找某个家Worksheet的国Workbook,在立即窗口输入:
代码语言:javascript复制?Activesheet.Parent.Name
这样我们找到的就是当前活动Worksheet的Workbook,输出了他的名称,其他都类似,基本都可以用Parent找到他上一层的对象。
在存在工作簿的时候,我们在立即窗口里输入的?Range("A1").Value,标准的输入应该是:
代码语言:javascript复制?Application.Workbooks(1).Worksheets(1).Range("A1").Value
前面那些之所以能够省略,是因为Excel VBA在管理Workbooks和Worksheets的时候,都会有一个ActiveWorkbook, ActiveSheet,他会记录下当前活动的对象,省略的时候它操作的对象就是当前活动的。
3、打开1个工作簿的时候,Excel到底做了些什么
我们电脑上的Excel文件,其本质只是硬盘上的一些数据,也就是010101那种东西。和其他所有文件都一样,和我们安装的office也一样,和前面说的EXCEL.EXE还是一样,只不过是包含的010101的数量不同、排列组合不同。
你双击一个Excel文件,他能够打开,不是你双击有什么魔力,这一切都是windows操作系统在后面帮忙做了很多很多工作。
我以自己非专业的认识讲一下,可能有不对的地方:
- 你双击一个Excel文件
- windows操作系统根据后缀找到注册表里对应文件后缀的可执行文件,也就是EXCEL.EXE
- EXCEL.EXE首先运行起来
- 然后EXCEL.EXE读取那个文件在硬盘上的数据,并解析数据放到了内存中
- 解析过程也就是去创建1个树形的对象模型
- 解析过程会根据文件的情况创建Workbook、Worksheet对象,其实所谓的创建也只是在内存中按一些规则来组织数据,可以让我们方便找到这些数据的内存地址
所以,我们用这种语句:
代码语言:javascript复制?Application.Workbooks(1).Worksheets(1).Range("A1").Value
它能输出内容,是因为EXCEL.EXE把数据在内存中解析好了,这个语句只是定位到了内容的内存地址,然后读取出来。
我们用那些Add等语句新添加对象,Excel VBA都会开辟新的内存空间来存放。
所以假如你一直添加新的Workbook、Worksheet对象,内存终将耗尽而无法继续添加。
而修改一些单元格值的时候,有的可能是直接在原来的内存地址修改数据即可,有些仍然要新开辟内存空间存放,然后把原来的空间释放掉。
所以很多读取属性的语句是要比赋值语句快很多。
4、小结
Excel VBA对象模型,和自己平时操作联系到一起,你能操作什么,就能找到对应的VBA对象。
然后就是多去用才能熟悉。