单元格()的默认属性 [英] The default property for cells()
问题描述
我的印象是 VBA
具有所有对象的默认属性。所以如果我说 Cells(counter,x)
附加的默认属性将是 .value
。此外,我一直使用 Cells(counter,x)
和 Cells(counter,x).value
可互换。但是,当通过for循环将项目添加到集合中时,我注意到,如果我没有包含 .value
而不是存储该值,则将其存储在该位置所表示的值在工作表中。这样,如果位置被删除,则集合中的引用将丢失。这带给我两个发现:1)集合可以存储非静态引用,并且2) Cells()
和其他对象没有默认属性,例如 .value的
。
如果有人可以澄清,确认和启发,这将是非常好的。
不,所有类型都不具有默认成员。
任何类模块都可以有一个默认成员,通过指定一个特殊的成员属性(您必须手动导出和编辑代码文件才能执行此操作,VBE不会公开任何功能):
属性{member name} .VB_UserMemId = 0
只允许一个成员一个类型的默认成员。
你发现了默认成员的肮脏,为什么要避免这种情况。 >
VBA做了很多事情来让我们的生活更轻松(例如隐式类型转换),默认成员就是其中之一。
集合可以存储非静态引用
我不知道什么静态参考erence是,但是当您在集合
中存储对象引用时,您不存储对象的副本,而是存储参考。
Cells()
和其他对象没有默认属性,如.value
。
Global.Cells
是一个参数化属性getter,返回一个 Range
对象引用; Range.Cells
也是一个getter,返回一个 Range
对象;在Excel对象模型中没有单元格
类。 Range
的默认成员是其值
。但是当你这样做:
Dim c As Collection
Set c = New Collection
c。添加ActiveSheet.Cells(1,1)
然后你要添加范围
引用 .Cells(1,1)
返回,然后是:
Debug.Print c.Item(1)
将输出 Range
对象的值。但是这样:
Debug.Print TypeName(c.Item(1))
将输出范围
。
混乱?是。这就是为什么你应该始终指定 Option Explicit
,尽可能使用显式类型声明的变量,避免隐式类型转换,避免使用默认成员。
通过编写正确读取的代码,您可以避免一些VBA陷阱,当您最终想要学习一些VB.NET或C#时,不要迷失类型的安全性和明确性。
使用最新的Rubberduck build (一个我所管理的开源VBE加载项目),您可以指定一个类'默认成员一个特殊的注释(注释):
'@ DefaultMember
公共属性Get Foo
结束属性
注释触发代码检查结果,警告关于缺少的相应属性;运行该检查结果快速修复同步注释/属性,Rubberduck导出模块,添加 VB_Attribute Foo.VB_UserMemId = 0
属性,并为您重新导入模块。
相反,如果一个成员有一个 VB_UserMemId = 0
属性,但没有相应的 @DefaultMember
注释,Rubberduck会生成关于缺少注释的检查结果警告,并提出一个快速修复程序,为您自动添加ot。
有更多的注释存在,但超出了这个答案的范围。浏览所有信息的 RD新闻博客文章。
I was under the impression VBA
had default properties for all its objects. So that if I say Cells(counter, x)
the default property attached will be .value
. Additionally, I've always used Cells(counter, x)
and Cells(counter, x).value
interchangeably. However, when adding items to a collection via a for loop, I noticed if I did not include .value
instead of storing the value, it stored the value as represented by the location in the worksheet. Such that if the location were deleted the reference in the collection would be lost. This brings me to two discoveries: 1) Collections can store non-static references, and 2) Cells()
and other objects do not have default properties such as .value
.
If anyone can clarify, confirm, and enlighten, that would be excellent.
No, not all types have a default member.
Any class module can have a default member, by specifying a special member attribute (you'd have to export and edit the code file manually to do this, the VBE doesn't expose any functionality for this):
Attribute {member name}.VB_UserMemId = 0
Only one member is allowed to be a type's default member.
You're discovering the nastiness of default members and why they should be avoided.
VBA does a lot of things to "make our lives easier" (e.g. implicit type conversions), and default members is one of these things.
Collections can store non-static references
I don't know what a "static reference" is, but when you store an object reference in a Collection
, you're not storing a copy of the object but a reference to it.
Cells()
and other objects do not have default properties such as.value
.
Global.Cells
is a parameterized property getter that returns a Range
object reference; Range.Cells
is also a getter that returns a Range
object; there is no Cell
class in the Excel object model. The default member of a Range
is its Value
. But then when you do this:
Dim c As Collection
Set c = New Collection
c.Add ActiveSheet.Cells(1, 1)
Then you're adding the Range
reference that .Cells(1, 1)
returns, and then this:
Debug.Print c.Item(1)
Will output that Range
object's value. Yet this:
Debug.Print TypeName(c.Item(1))
Will output Range
.
Confusing? Yes. That's why you should always have Option Explicit
specified, work with variables declared with an explicit type as much as possible, avoid implicit type conversions, ...and avoid using default members.
By writing code that reads exactly as it should behave, you avoid a number of VBA traps, and when you eventually want to learn some VB.NET or C# you won't be lost at all about type safety and explicitness.
With the latest Rubberduck build (an open-source VBE add-in project I manage), you can specify a class' default member with a special comment ("annotation"):
'@DefaultMember
Public Property Get Foo()
End Property
The annotation triggers a code inspection result that warns about the missing corresponding attribute; running that inspection result's quick-fix "synchronize annotations/attributes", Rubberduck exports the module, adds the VB_Attribute Foo.VB_UserMemId = 0
attribute, and re-imports the module for you.
Conversely, if a member has a VB_UserMemId = 0
attribute, but no corresponding @DefaultMember
annotation, Rubberduck produces an inspection result warning about the missing annotation, and proposes a quick-fix to automatically add ot for you.
More annotations exist, but would be beyond the scope of this answer. Browse the RD News blog posts for all the info.
这篇关于单元格()的默认属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!