我的印象是VBA
具有所有对象的默认属性。因此,如果我说Cells(counter, x)
,附加的默认属性将为.value
。另外,我一直使用Cells(counter, x)
和Cells(counter, x).value
互换。但是,当通过for循环向集合添加项目时,我注意到如果我没有包含.value
而不是存储该值,它会将值存储为工作表中的位置。这样,如果删除了该位置,则该集合中的引用将丢失。这让我有两个发现:1)集合可以存储非静态引用,2)Cells()
和其他对象没有默认属性,如.value
。
如果有人能澄清,确认和启发,那就太棒了。
答案 0 :(得分:7)
不,并非所有类型都有默认会员。
任何类模块都可以有一个默认成员,通过指定一个特殊的成员属性(您必须手动导出和编辑代码文件才能执行此操作,VBE不会' t暴露任何功能):
Attribute {member name}.VB_UserMemId = 0
只允许一个成员成为类型的默认成员。
您发现了默认会员的肮脏以及为什么要避免这些行为。
VBA做了很多事情,让我们的生活变得更轻松#34; (例如隐式类型转换),默认成员就是其中之一。
集合可以存储非静态引用
我不知道"静态参考"是,但是当您在Collection
中存储对象引用时,您不会存储该对象的副本,而是存储引用。< / p>
Cells()
和其他对象没有默认属性,例如.value
。
Global.Cells
是一个参数化属性getter,它返回一个Range
对象引用; Range.Cells
也是一个返回Range
对象的getter; Excel对象模型中没有Cell
类。 Range
的默认成员是隐藏的[_Default]
成员,似乎已解析为Value
。但是当你这样做时:
Dim c As Collection
Set c = New Collection
c.Add ActiveSheet.Cells(1, 1)
然后,您要添加Range
返回的.Cells(1, 1)
引用,然后执行此操作:
Debug.Print c.Item(1)
将输出Range
对象的值。但是这个:
Debug.Print TypeName(c.Item(1))
将输出Range
。
混淆?是。这就是为什么你应该总是指定Option Explicit
,尽可能使用显式类型声明的变量,避免隐式类型转换,...并避免使用默认成员。
通过编写完全按照其应有的方式读取的代码,可以避免大量的VBA陷阱,当您最终想要学习一些VB.NET或C#时,您根本不会丢失类型安全性和显式性