看看Excel VBA中对象的层级和继承关系
《周易·序卦传》中认为:“有天地然后有万物,有万物然后有男女,有男女然后有夫妇,有夫妇然后有父子,有父子然后有君臣,有君臣然后有上下,有上下然后礼仪有所错(意为措置)。”在儒家思想里,“君君臣臣父父子子”勾勒出了清晰的人伦层级与从属关系,每个人在这种体系里都有着明确的定位。
有趣的是,这种“层级从属”的逻辑,在Excel VBA的世界里也是存在的,并并且贯穿着整个对象模型的始终。那些我们天天打交道的工作簿、工作表、单元格、图形、图表等等,所有元素都对应着一个“对象”,每个对象便如同一个人,这是一个不缺对象的世界!而,这些对象之间,也有着如同“君臣父子”一般清晰的继承关系。掌握对象的层级和继承关系,是解锁VBA高效编程的关键密码。
今天,我们通过一个实际的VBA需求,来看看Excel VBA中的“继承关系”,以及如何利用这种关系精准获取我们想要的对象信息。
一、需求描述
通过Application.InputBox(Type:=8)弹出交互式对话窗口,可以让用户点选单元格区域。但是,我们并不知道这个单元格(区域)来自哪个工作表、工作簿。
如何知道选择的单元格(区域)来自哪里呢?
二、问题分析
你或许以为可以这样:
Option ExplicitSub test()Dim rng As RangeDim str1$, str2$ Set rng = Application.InputBox("选择一个单元格或单元格区域。", _ "对象在哪里?", Type:=8) str1 = ActiveSheet.Name str1 = ActiveWorkbook.NameEnd Sub
代码中,试图通过激活的工作表(或工作簿)ActiveSheet来解决这个问题。但这种方法有个明显的漏洞——用户虽然可以在点选过程中手动切换工作表(或工作簿),导致ActiveSheet发生变化,但是当对话框关闭后,操作界面又会返回到原来的工作表,此时的ActiveSheet已非那时的ActiveSheet了!这样的结果与实际选择的并不一致,导致最终获取的信息出错。
如何才能准确获取这个单元格区域所属的工作表呢?
三、解决办法
其实,通过VBA的对象继承(从属)关系(关键属性:Parent),就可以轻松解决这个问题。
执行Application.InputBox(Type:=8)语句后,找到自己中意的“对象”后,点“确定”返回,这样就可以返回一个单元格(或区域)的对象。再通过“Set rng”语句将对象与变量rng绑定,然后通过rng的Parent属性,一步一步地溯源,就可以知道他(rng单元格对象)的爹(工作表对象)是谁,以及他爹的爹(工作簿)是谁了。
就这么简单,请看代码:
Option ExplicitSub test()Dim rng As RangeDim str1$, str2$ Set rng = Application.InputBox("选择一个单元格或单元格区域。", _ "对象在哪里?", Type:=8) str1 = "单元格的爹是谁?答:" & rng.Parent.Name str2 = "单元格的爷是谁?答:" & rng.Parent.Parent.Name MsgBox "你对象的地址是:" & rng.Address _ & vbCrLf & str1 & vbCrLf & str2, _ vbInformation, "恭喜,找对象成功!"End Sub
四、结果验证
在打开第4张工作表的情况下,运行代码,然后从第2张表中选择单元格,然后看看返回的结果是否符合要求。
结果正确,问题解决!