语法选项在VBA宏for Excel中创建错误

时间:2012-07-30 15:15:31

标签: excel vba syntax excel-vba

在为Excel编写VBA宏时,我遇到了语法选项方面的问题。在VBA中,您可以通过两种不同的方式在对象上调用方法:

foo.bar(arg1, arg2)

foo.bar arg1, arg2

我绝对讨厌第二种语法因为我发现它没有任何清晰度,所以我通常坚持第一种选择。但是,我遇到过使用第一个选项会产生错误,而第二个选项执行正常的情况。 (这可能是我的代码中其他问题的一个指标。)这是罪魁祸首代码:

Function GetFundList() As Collection
    Dim newFund As FundValues
    Range("A5").Select
    Set GetFundList = New Collection

    While Len(Selection.Value)
        Set newFund = New FundValues

        ' I set the fields of newFund and move Selection

问题在于下一行:

        GetFundList.Add newFund
    Wend
End Function

FundValues是我创建的一个基本上只是一个结构的类;它有三个在循环中设置的属性。

基本上,当我拨打GetFundList.Add(newFund)时,我收到以下错误:

运行时错误'438': Object不支持此属性或方法

但是调用GetFundList.Add newFund完全没问题。

有没有人能够理解VBA的复杂性,足以解释为什么会发生这种情况?

编辑:非常感谢您的解释!

3 个答案:

答案 0 :(得分:0)

向集合添加项目不是定义为返回值的函数,而是作为子例程:

Public Sub Add( _
   ByVal Item As Object, _
   Optional ByVal Key As String, _
   Optional ByVal { Before | After } As Object = Nothing _
)

当按名称调用另一个子例程并发送参数(不添加“Call”语句)时,不需要添加括号。
调用函数时,需要添加括号,该函数将值返回给变量

示例:

Sub Test_1()
Dim iCnt As Integer
Dim iCnt_B As Integer
Dim iResult As Integer


iCnt = 2
iCnt_B = 3

fTest_1 iCnt, iResult, iCnt_B

End Sub

Public Function fTest_1(iCnt, iResult, iCnt_B)

iResult = iCnt * 2 + iCnt_B * 2

End Function

Sub Test_2()

Dim iCnt As Integer
Dim iCnt_B As Integer
Dim iResult As Integer


iCnt = 2
iCnt_B = 3

iResult = fTest_2(iCnt, iCnt_B)

End Sub

Public Function fTest_2(iCnt, iCnt_B)

fTest_2 = iCnt * 2 + iCnt_B * 2

End Function

如果不清楚,请告诉我。

答案 1 :(得分:0)

Daily Dose of Excel conversation会有所帮助。

当您使用括号时,您强制VBA评估其中的内容并将结果添加到集合中。由于NewFund没有默认属性 - 我假设 - 评估没有产生任何结果,因此无法添加。如果没有括号,它会计算出类的实例,这就是你想要的。

另一个例子。这样:

Dim coll As Collection
Set coll = New Collection
coll.Add Range("A1")
Debug.Print coll(1); TypeName(coll(1))

这......

coll.Add (Range("A1"))
Debug.Print coll(1); TypeName(coll(1))

...两者都会产生debug.window中的A1,因为Value是Range的默认属性。但是,第一个将产生一种“范围”,而第二个示例中的类型是A1中的数据类型。换句话说,第一个为集合添加一个范围,第二个是范围的内容。

另一方面,这有效:

Dim coll As Collection
Set coll = New Collection
coll.Add ActiveSheet
Debug.Print coll(1).Name

......而这不是:

coll.Add (ActiveSheet)
Debug.Print coll(1).Name

因为ActiveSheet没有默认属性。您将收到运行时错误438,就像您的问题一样。

答案 2 :(得分:0)

这是看待同样事物的另一种方式。

假设单元格A1包含字符串Hi!

Function SomeFunc(item1, item2)
    SomeFunc = 4
End Function

Sub Mac()
    ' here in both of the following two lines of code,
    '  item1 will be Variant/Object/Range, while item2 will be Variant/String:
    SomeFunc Range("A1"), (Range("A1"))
    Let i = SomeFunc(Range("A1"), (Range("A1")))

    'this following is a compile syntax error
    SomeFunc(Range("A1"), (Range("A1"))) 

    ' while here in both the following two lines of code, 
    '  item1 will be Variant/String while item2 will be Variant/Object/Range:
    SomeFunc ((Range("A1")), Range("A1")
    Let j = SomeFunc((Range("A1")), Range("A1"))

    'this following is a compile syntax error
    SomeFunc((Range("A1")), Range("A1"))

    Set r = Range("A1")       ' sets r to Variant/Object/Range
    Set r = (Range("A1"))     ' runtime error 13, type mismatch; cannot SET r (as reference) to string "Hi!" -- Strings are not objects in VBA
    Set r = Range("A1").Value ' runtime error (same)


    Let r = Range("A1")       ' set r to "Hi!" e.g. contents of A1 aka Range("A1").Value; conversion to value during let = assignment
    Let r = (Range("A1"))     ' set r to "Hi!" e.g. contents of A1 aka Range("A1").Value; conversion to value by extra ()'s
    Let r = Range("A1").Value ' set r to "Hi!" by explicit use of .Value 
End Sub

我只是添加这个来帮助说明这里有两件事情可能会混淆。

第一个是表达式中的(),它将项目转换为其Value属性,如上面其他答案中所述。

第二个是,意图捕获或使用返回值而调用的函数需要围绕整个参数列表的extra(),而调用函数(或子函数)而无意捕获或使用返回值(例如作为语句)必须在参数列表周围没有那些相同的()被调用。这些surround()不使用.Value转换参数列表。当参数列表只有一个参数时,这种区别可能特别令人困惑。