返回默认属性

我填写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 )属性的默认属性来设置每个variables。 但是,我得到了最后一行代码的运行时错误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 

这里发生了什么 ??

区别在于如何通过实现RangeSheets对象来处理对其默认属性的input。

RangeSheets对象的默认属性采用Varianttypes的参数。 你可以传递任何东西,所以不需要强制types。 在你的第一个例子中,你将一个Range对象传递给两者。

默认属性如何处理input取决于它们自己。 显然Range的属性试图检索传递参数的默认值,在你的例子中一个地址为String。 Sheets对象似乎没有那么宽容,并且引发错误,因为你既没有传递一个数字也没有传递一个String。

不一致是VBA的强项之一…

顺便说一下,传递CStr(Cells(2, 1))也是可行的,因为在传递参数之前,你明确地将其转换为String。

也许Leviathan的评论“不一致是VBA的强项之一…”可能是正确的,但是他的回答忽略了一些上下文细节(在技术上在一些细微的点上是不正确的)。 他是正确的,对于给定的代码,所有的参数都是变体,但是“不需要强制types强制”的说法在许多情况下可能是误导性的,也许只是错误的。 即使许多对象和方法被编程来处理多种types和deafult值,但这个问题揭示了避免故意确保(或胁迫)正确的数据types是错误的。 完全避免默认属性(通过总是input完整的引用)可以避免许多麻烦。

这个特定问题的代码行之间的显着差异是: Range是一个需要参数的属性 ,而Sheets也是一个属性,但没有参数。 范围表格在这个上下文中不是对象 ,即使它们是分别返回Range和Sheets对象的属性。 它们是为特定模块或Excel工作簿实例定义的(自动全局)对象的属性 。 这些细节对于理解代码实际上在做什么来说并不是微不足道的。

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

 Property Range(Cell1, [Cell2]) As Range Property Sheets As Sheets 

对于Range(Cells(1, 1)) Cells(1,1) Range(Cells(1, 1)) ,将参数Cells(1,1)传递给参数Cell1 。 此外,事实certificate, Cells(rowindex, colindex)也是一个参数化的属性,返回一个Range对象。 因此, Set r = Range(Cells(1, 1))冗余的,因为Set r = Cells(1, 1)是等价的。 与Leviathan的回答相反, Cells(1, 1)对象的默认属性可能永远不会被调用(并且是毫无意义的),因为参数已经是预期的返回types。 顺便说一下,R​​ange对象的默认属性是Range.Value

Sheets类的默认属性是参数化的Item(Index)方法。 因此, Sheets(Cells(2, 1))相当于Sheets.Item(Cells(2, 1)) 。 更重要的是,这意味着Sheets.Item(Cells(2, 1))传递一个Range对象作为索引值,但文档说它期望一个整数或string值。 我们已经提到过index参数是变体…当传递一个对象到一个变体时,它总是传递实际的对象而不是它的默认属性。 所以我们知道Sheets.Item在该调用中获得一个Range对象。 这里Levithan是正确的,Sheets.Item可以决定如何处理它。 很可能它已经足够聪明,可以获得单个string的值,并且可以继续而不会出错。 MS Office对象中的其他集合对象(具有默认的Item(index)属性)似乎并没有performance出相同的“挑剔”,所以看起来Sheets.Item在validation其参数方面似乎相当严格。 但这只是这个方法的一个特殊的devise问题而已……不一定是VBA的一个总体问题。


难以确定的是属性的源对象究竟是什么。 在“ThisWorkbook”模块中,“ Me.Sheets显示Sheets是模块特定工作簿的属性。 但是, Me.Range在工作簿模块中是无效的,但是右键单击Range属性(没有Me限定符)并select“定义”结果的消息“无法跳到范围,因为它是隐藏的”。 在这方面,从表单模块(即Me.Range是有效的,而不是Me.Sheets)调用它们时,Range和Sheets属性是相反的。

为什么不一致和隐藏的属性? 为了使Excel的当前实例及其所有组件以“自然”方式可访问,Excel(和所有Office应用程序)实现了这些各种隐藏属性,以避免必须重复发现并输出完整的“复杂性”引用。 例如,自动的全局应用程序对象也有Range和Sheets属性。 例如, Application.Sheets的实际文档中提到“使用不带对象限定符的属性等同于使用ActiveWorkbook.Sheets”。 即使这个文档没有说的是,ActiveWorkbook反过来是全球Excel应用程序对象的属性。