Vba 返回默认属性

Vba 返回默认属性,vba,excel,Vba,Excel,我将A1和A2填充如下: 然后我运行: Sub WhatIsGoingOn() Dim r As Range, sh As Worksheet Set r = Range(Cells(1, 1)) Set sh = Sheets(Cells(2, 1)) End Sub 我希望在这两种情况下,VBA都会使用默认的Cells属性(Value)属性来设置每个变量。然而,我在最后一行代码中得到了一个运行时错误13 为了避免错误,我必须使用: Sub WhatIsGoing

我将A1A2填充如下:


然后我运行:

Sub WhatIsGoingOn()
    Dim r As Range, sh As Worksheet

    Set r = Range(Cells(1, 1))
    Set sh = Sheets(Cells(2, 1))
End Sub
我希望在这两种情况下,VBA都会使用默认的Cells属性(Value)属性来设置每个变量。然而,我在最后一行代码中得到了一个运行时错误13

为了避免错误,我必须使用:

Sub WhatIsGoingOn2()
    Dim r As Range, sh As Worksheet

    Set r = Range(Cells(1, 1))
    Set sh = Sheets(Cells(2, 1).Value)
End Sub

这里发生了什么?

区别在于
范围
图纸
对象的实现如何处理对其默认属性的输入

范围
工作表
对象的默认属性都采用类型为
变量
的参数。您可以向它传递任何内容,因此不需要类型强制。在第一个示例中,将范围对象传递给两个对象

默认属性如何处理输入取决于它们自己。显然,
范围
的属性试图检索传递参数的默认值,在您的示例中,地址是字符串。
Sheets
对象似乎不太宽容,因为您既没有传递数字,也没有传递字符串,因此引发了一个错误

不一致性是VBA的优势之一


顺便说一句,传递
CStr(单元格(2,1))
也会起作用,因为在作为参数传递之前,您会显式地强制转换为字符串。

也许Leviathan的评论“不一致性是VBA的优势之一…”听起来可能是真的,但他的回答忽略了一些上下文细节(从技术上讲,在某些细微之处是不正确的)。他正确地指出,对于给定的代码,所有参数都是变体,但“不需要类型强制”的说法是正确的可能会产生误导,在许多情况下可能是错误的。即使许多对象和方法被编程为处理多种类型和默认值,这个问题也表明,故意避免确保(或强制)正确的数据类型是错误的。完全避免默认属性(始终键入完整引用)可以避免很多头痛

此特定问题的代码行之间的一个显著区别是:范围是一个接受参数的属性,而图纸也是一个属性,但没有参数。范围和图纸在此上下文中不是对象,即使它们分别是返回范围和图纸对象的属性。T以下是为特定模块或Excel工作簿实例定义的(自动全局)对象的属性。对于理解代码实际执行的操作,此详细信息并非微不足道

VBA窗口中的Obect浏览器显示两个属性的以下元数据:

Property Range(Cell1, [Cell2]) As Range
Property Sheets As Sheets
对于
范围(单元格(1,1))
,参数
单元格(1,1)
被传递到参数
Cell1
单元格
本身是
Excel.Global
隐藏对象的一个属性,它返回一个范围对象,以便
单元格(rowindex,colindex)
正在调用与
单元格等效的Range类的隐藏默认属性。\u default(rowindex,colindex)
。属性的返回类型
\u default()
未声明,因此从技术上讲,它可以返回变量中的任何类型,但检查表明它返回一个范围对象。显然,将范围对象传递到其默认属性将尝试获取默认值,如果它是一个有效的范围值,如带范围表达式的字符串,则它将无误执行

Sheets类的默认属性是参数化的hidden
\u default(Index)
方法。因此,
工作表(单元格(2,1))
等同于
工作表。\u default(单元格(2,1))
。更重要的是,它意味着
工作表。\u default(单元格(2,1))
将范围对象作为索引值传递,但文档说明它需要整数或字符串值。我们已经提到,
index
参数是variant…并且当将对象传递给variant时,它总是传递实际对象,而从不传递其默认属性。因此我们知道
Sheets.Item
obtains在该调用中是一个范围对象。下面是Levithan在该表中的正确性。Item可以决定如何处理它。它可能已经足够聪明,可以获取单个字符串值并无错误地继续。MS Office对象中的其他集合对象(具有默认Item(index)属性)似乎没有表现出相同的特性“挑剔”,因此似乎
工作表。_Default()
(可能还有
Sheets.Item()
)在验证其参数时非常严格。但这只是此方法的一个特殊设计问题……不一定是VBA的整体问题


困难的是确定属性的源对象是什么。在ThisWorkbook模块中,
Me.Sheets
显示工作表是该模块特定工作簿的属性。但是
Me.Range
在工作簿模块中无效,但右键单击
Range
属性(没有Me限定符)并选择“定义”将导致消息“无法跳转到范围,因为它是隐藏的”。但是,一旦进入对象浏览器,在浏览器中单击鼠标右键可以选择“显示隐藏的成员”,这将允许导航到隐藏的全局对象和其他隐藏的成员

为什么会出现不一致和隐藏属性?为了使Excel的当前实例及其所有组件能够以“自然”的方式访问,Excel(以及所有Office应用程序)实现了这些隐藏属性,以避免“复杂性”例如,自动全局应用程序对象还具有Range和Sheets属性。例如,Actual表示“在没有对象限定符的情况下使用此属性等同于使用Activ