我明白:
Range.Item
返回一个 Range 对象,该对象表示与指定范围偏移的范围。
Range.Cells
返回一个 Range 对象,该对象表示指定范围内的单元格。
然而,当我读到"Item is a default property of the Range
object"时,混乱就开始了。
这让我想问:
是Range("A1:D5").Cells(1,1)
真正的简化版本Range("A1:D5").Cells.Item(1,1)
?
为什么不只是Range("A1:D5").Item(1,1)
在任何情况下使用?
为什么 VBA 程序员似乎使用Cells
属性来引用范围而不是Item
属性?仅省略Item
默认属性以支持是“最佳实践”Cells
吗?
Range
是一个类。类是蓝图的对象-一个对象是一个实例类的。
现在,VBA 中的类可以有一个默认属性。如果你导出一个类模块,你可以给他们成员属性。VB_UserMemId
值为的属性0
将成员标识为该类的默认成员- 您不能直接在 VBE 中编辑成员属性,但您可以导出模块、添加属性并将模块重新导入到项目中.
一个默认的属性可能是这个样子:
Option Explicit
Private mFoo As Bar
Public Property Get Foo() As Bar
Attribute Foo.VB_UserMemId = 0
Set Foo = mFoo
End Property
VB_UserMemId
您可以使用许多可能的值,但只有一个类的成员可以具有任何给定值 -0
使其成为该类的默认成员。
默认成员允许您编写隐式代码——这是否是一件好事是一个判断调用。
例如,当您想访问i
a索引处的项目时Collection
,您可以这样做:
foo = myCollection.Item(i)
但由于Item
是在默认属性中的Collection
类,你也可以这样做:
foo = myCollection(i)
结果是完全一样的。
该Range
班是......一个特殊的动物。如果您在Object Browser 中查看它的定义,您会发现它的默认属性是一个名为 的隐藏属性_Default
,它通常被推断为返回Range.Value
- 因为这个隐式默认成员调用:
foo = Sheet1.Range("A1")
相当于这个显式代码:
foo = Sheet1.Range("A1").Value
类的Item
属性不是默认成员。但是,如果您查看该隐藏属性的定义,您会发现它接受两个可选参数:Range
_Default
所以这也是合法的:
foo = Sheet1.Range("A1:A10")(1)
相当于:
foo = Sheet1.Range("A1:A10").Item(1).Value
基本上,Range
类的默认属性是这样实现的,如果没有指定参数,它会做一件事(给你Value
.. 它本身返回单元格的值,或者如果范围包含多个单元格,则返回一个二维变量数组),如果指定了参数,则另一件事(Item
在该范围内的指定行/列处为您提供)。
所以这就是为什么Range("A1:A10").Cells
(没有参数)是多余的:它产生完全相同的细胞Range("A1:A10")
。
该Cells
属性未参数化:
因此,Range.Cells
使用参数调用的 VBA 程序员实际上是Range._Default
使用这些参数调用,针对Cells
...返回的范围,这意味着Range("A1:A10").Cells(1)
有效Range("A1:A10").Cells.Item(1)
... 这涉及对Cells
.
因此,参数化Cells[._Default][.Item](1)
语法只是为了方便;它主要是一个可读性的事情......然后是IntelliSense:Item
返回 a Variant
,这意味着当您.
在它之后键入点/取消引用运算符时,您不会得到可用成员的漂亮小下拉列表(调用是“后期绑定”,即所涉及的类型在运行时解析) - 但您在调用时会这样做Cells
,因为Cells
返回一个早期绑定的Range
对象(即在编译时解析)。
最佳实践是编写代码来执行它所说的,并说明它所做的- 因此您通常希望避免隐式默认成员调用。然而,在这种情况下,Range
这与另一个最佳实践相冲突,即尽可能编写编译时验证的早期绑定代码- 使用Cells
而不是Item
给你。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句