返回默认属性
我填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将使用单元格的默认属性(值)属性设置每个变量。但是,在最后一行代码中出现运行时错误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
这到底是怎么回事?
不同之处在于如何通过执行Range
和Sheets
对象来处理对其默认属性的输入。
Range
和Sheets
对象的默认属性采用类型为Variant
的参数。你可以传递任何东西给它,所以不需要类型强制。在你的第一个例子中,你将一个Range对象传递给两者。
默认属性如何处理输入取决于它们自己。显然,Range
的属性尝试检索传递参数的默认值,在您的示例中为String的地址。 Sheets
对象似乎没有如此宽容,并且引发错误,因为您既没有传递数字也没有传递字符串。
不一致VBA的优势之一...
顺便说一句,路过CStr(Cells(2, 1))
也将工作,因为你明确地转换为字符串作为参数传递之前。
非常感谢! –
也许Leviathan的评论“不一致是VBA的强项之一......”可能是事实,但是他的回答忽略了一些背景细节(并且在一些细微的点上在技术上是不正确的)。他是正确的,对于给定的代码,所有参数都是变体,但是“不需要强制类型强制”的说法在许多情况下可能是误导性的,也许只是错误的。即使许多对象和方法被编程来处理多种类型和deafult值,但这个问题揭示了避免故意确保(或强制)正确的数据类型是错误的。完全避免默认属性(通过始终输入完整引用)可以避免许多令人头痛的问题。
的代码对于该特定问题的线之间的显著区别是:范围是属性即采用参数,而表也是属性但具有没有参数。 范围和表在这方面不是对象,尽管它们是属性做分别返回Range和Sheets对象。它们是为特定模块或Excel工作簿实例定义的(自动全局)对象的属性。这些细节对于理解代码实际在做什么来说并不是微不足道的。
的Obect浏览器在窗口VBA揭示了两个属性的以下元数据:
Property Range(Cell1, [Cell2]) As Range
Property Sheets As Sheets
对于Range(Cells(1, 1))
,参数Cells(1,1)
被传递给参数Cell1
。而且,事实证明Cells(rowindex, colindex)
也是一个返回Range对象的参数化Property。所以这使得Set r = Range(Cells(1, 1))
冗余,因为Set r = Cells(1, 1)
是等价的。与Leviathan的回答相反,Cells(1, 1)
对象的默认属性可能永远不会被调用(并且毫无意义),因为该参数已经是预期的返回类型。顺便说一下,Range对象的默认属性是Range.Value
。
Sheets类的默认属性是参数化的Item(Index)
方法。因此,Sheets(Cells(2, 1))
相当于Sheets.Item(Cells(2, 1))
。更重要的是,这意味着Sheets.Item(Cells(2, 1))
传递一个Range对象作为索引值,但文档说它期望一个整数或字符串值。我们已经提到index
参数是variant ...并且当将一个对象传递给一个变体时,它总是传递实际的对象而不是它的默认属性。所以我们知道Sheets.Item
在该调用中获得一个Range对象。 Levithan是正确的,Sheets.Item可以决定如何处理它。它很可能已经足够聪明,可以获得单个字符串的值并继续而不会出错。 MS Office对象中的其他集合对象(具有默认的Item(index)属性)似乎并没有表现出同样的“挑剔”,所以看起来Sheets.Item
在验证其参数方面相当严格。但这只是这种方法的一个特殊设计问题......不一定是VBA的总体问题。
难以确定哪些属性的源对象是()。在ThisWorkbook模块中,Me.Sheets
显示Sheets是模块特定工作簿的属性。但Me.Range
在工作簿模块中无效,但右键单击Range
属性(不带Me限定符),并选择“定义”结果显示消息“因为隐藏而无法跳转到范围”。在这方面,从表单模块调用它们时(即Me.Range有效,但不是Me.Sheets),Range和Sheets属性相反。
为什么不一致和隐藏属性?为了使Excel的当前实例及其所有组件以“自然”方式可访问,Excel(和所有Office应用程序)实现了这些各种隐藏属性,以避免必须重复发现并输出完整的“复杂性”引用。例如,自动全局应用程序对象也具有Range和Sheets属性。例如,实际的documentation for Application.Sheets表示“使用不带对象限定符的此属性等效于使用ActiveWorkbook.Sheets”。即使该文档没有说的是,ActiveWorkbook反过来是全球Excel应用程序对象的属性'。
感谢您的意见。 –
有趣的问题,你也可以把它包装在CStr()中,它将工作没有价值。 '表格(CStr(Cells(1,2)))'。所以它必须与Sheets()本身有关。 –
看来Sheets()并没有将值作为字符串引入,而是试图将值作为Long来引入。如果你在A2中放入'1',它将抓取索引中的第一张,而不带'.Value'。因此,为了引入名称,它要求它被告知它是一个字符串,使用CStr,.Value,或者你可以使用'“&Cells(2,1)'我认为这是因为Sheets()的默认查找,索引是一个Long而不是一个字符串。 –
@ScottCraner我认为你已经找到了一些...............我会再试验一些。 –