在 VBA 中传递 Variant 参数 ByRef 时出现编译错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9376002/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 15:17:17  来源:igfitidea点击:

Compilation-error while passing Variant argument ByRef in VBA

excelvba

提问by adrien.pain

I've got a "compilation" error in Excel VBA, which I don't understand...

我在 Excel VBA 中有一个“编译”错误,我不明白...

I've got a method like that :

我有一个这样的方法:

    Public Sub SomeMethod(ByRef argument As SomeClass)
        ... <- 'argument' must be called ByRef because I have to modify it
    End Sub

If I define a variable like :

如果我定义一个变量,如:

    Dim var As SomeClass

No problem, I can call :

没问题,我可以打电话:

    SomeMethod var

and it's working.

它正在工作。

BUT, if I define a Variant variable like :

但是,如果我定义一个 Variant 变量,如:

    Dim var as Variant
    Set var = New SomeClass

It doesn't work.

它不起作用。

If I call :

如果我打电话:

    SomeMethod var

VB pops-up a message : 'ByRef argument type mismatch'

VB 弹出一条消息:'ByRef 参数类型不匹配'

If I call :

如果我打电话:

    SomeMethod (var)

it "compiles", but var is then passed ByVar and it gave me a runtime-error message : 'Object doesn't support this property or method'

它“编译”,但随后通过 ByVar 传递了 var 并给了我一条运行时错误消息:“对象不支持此属性或方法”

So I basically just want to tell VBA that my Variant variable 'var' is in fact a 'SomeClass' object (in debugger, VBA says so), but I don't know how to do that...

所以我基本上只是想告诉 VBA,我的 Variant 变量“var”实际上是一个“SomeClass”对象(在调试器中,VBA 是这样说的),但我不知道该怎么做……

Could someone please help me ?

有人可以帮我吗?

回答by Alex K.

Decorate the argument with ByVal

ByVal

Public Sub SomeMethod(ByVal argument As someclass)

then you can pass a variant;

然后你可以传递一个变体;

SomeMethod var

This works because the ByVal argumentis received as a local copyof a reference to a Variant[someclass]which means VB can freely perform a type-conversion (to convert the Variant[someclass]->someclass).

这是有效的,因为ByVal argument是作为对 a 的引用的本地副本接收的,Variant[someclass]这意味着 VB 可以自由执行类型转换(以转换Variant[someclass]->someclass)。

It wont work when passed as ByRefbecause any changes to argumentwould also affect the calling object reference variable outside the current procedure.

传递时它不会工作,ByRef因为任何更改argument也会影响当前过程之外的调用对象引用变量。

If you pass As Objectyou don't need the ByVal.

如果通过As Object,则不需要ByVal.

If your doing this a lot with custom classes VBA supports interfaces; function foo(obj as IOneOfMyWidgets)

如果您经常使用自定义类 VBA 支持接口; function foo(obj as IOneOfMyWidgets)

回答by Jean-Fran?ois Corbett

Two things:

两件事情:

Proper way to call a Sub

调用 Sub 的正确方法

In VBA, to call a Sub, you can either write this

在 VBA 中,要调用 Sub,你可以这样写

SomeSub var

without parentheses or this

没有括号或这个

Call SomeSub(var)

This: SomeSub (var)doesn't do what you think it does.

这:SomeSub (var)不会做你认为它会做的事情。

Casting Variant to class or data type

将 Variant 转换为类或数据类型

As I was writing this, Alex K's answer came in, so I will just supplement by showing that the type mismatch isn't restricted to objects, but also affects primitive data types contained in a Variant:

在我写这篇文章的时候,Alex K 的回答出现了,所以我将补充说明类型不匹配不仅限于对象,还会影响包含在 Variant 中的原始数据类型:

Sub tester()
    Dim v As Variant
    v = 1.234567 ' v is now type Variant/Double
    dothis v ' No problem.
    dothat v ' Compile error: ByRef argument type mismatch.
End Sub

Sub dothis(ByVal d As Double)
    'stuff
End Sub

Sub dothat(ByRef d As Double)
    'stuff    
End Sub

回答by mvanle

You could also explicitly cast to a type:

您还可以显式转换为类型:

'/* Factory */
Select Case TypeName(var)
    Case "SomeClass":
        Dim cast As SomeClass
        Set cast = var
        SomeMethod cast
End Select