返回默认属性

时间:2016-05-15 14:51:42

标签: excel vba excel-vba

我按如下方式填写 A1 A2

enter image description here 我然后跑:

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

这里发生了什么?

2 个答案:

答案 0 :(得分:2)

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

RangeSheets对象的默认属性采用类型Variant的参数。你可以传递任何东西,所以不需要强制类型。在第一个示例中,您将Range对象传递给它们。

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

不一致是VBA的优势之一...

顺便说一下,传递CStr(Cells(2, 1))也可以,因为你在作为参数传递之前显式地转换为String。

答案 1 :(得分:1)

也许Leviathan评论说"不一致是VBA的优势之一......"可能是真的,但有一些背景细节,他的答案忽略(并在技术上在一些微妙的点上不正确)。他是正确的,对于给定的代码,所有参数都是变体,但声明“#34;没有类型强制是必要的"在许多情况下可能会产生误导,也许是错误的。即使许多对象和方法被编程为处理多种类型和聋人价值,这个问题也表明,避免故意确保(或强制)正确的数据类型是错误的。完全避免默认属性(通过输入完整的引用)可以避免许多麻烦。

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

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

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参数是变量的......当将对象传递给变体时,它总是传递实际对象而不是它的默认属性。所以我们知道Sheets.Item在该调用中获得了一个Range对象。这是Levithan在Sheets.Item可以决定如何处理它是正确的。它可能足够聪明,可以获得单个字符串值并继续而不会出错。 MS Office对象中的其他集合对象(具有默认的Item(索引)属性)似乎没有表现出相同的" pickiness",因此Sheets.Item似乎对验证其参数非常严格。但这只是这种方法的一个特殊设计问题......不一定是VBA的整体问题。

确切地确定属性的源对象是什么是很困难的。在ThisWorkbook模块中,Me.Sheets显示Sheets是模块的特定工作簿的属性。但是Me.Range在工作簿模块中无效,但右键单击Range属性(没有Me限定符)并选择"定义"导致消息"无法跳转到Range,因为它是隐藏的"。在这方面,从工作表模块调用它们时,Range和Sheets属性是相反的(即Me.Range有效,但不是Me.Sheets)。

为什么不一致和隐藏属性?试图使当前的Excel实例及其所有组件在" natural"方式,Excel(和所有Office应用程序)实现这些各种隐藏属性,以避免"复杂性"必须反复发现并输入完整的参考文献。例如,自动全局Application对象还具有Range和Sheets属性。例如,实际documentation for Application.Sheets表示"在没有对象限定符的情况下使用此属性等同于使用ActiveWorkbook.Sheets"。即使该文档未能说明ActiveWorkbook又是全局Excel应用程序对象的属性,而且