VBA - CallByName不会接受变体参数 [英] VBA - CallByName won't accept variant arguments

查看:165
本文介绍了VBA - CallByName不会接受变体参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

解决方案:只需在CallByName语句中将括号括在Value中即可对其进行评估。



CallByName MobClass,TargetData,vbLet,(Value)



可能是删除,因为它不再相关和可能的重复。



我花了很长时间试图找出我使用CallByName的方式有什么问题。我终于意识到,如果输入不是与它的调用或其硬编码的输入参数完全相同的类型,那么它的第四个参数(Args)将引发类型不匹配。



(我甚至不知道如何,或者为什么,它自从 VarType(Variant / Integer)= VarType(Integer)



所以我需要一种方法让它接受变量输入或将变量从 Variant / Integer 转换为整数(或创建一个新的变量)没有一个巨大的选择案例。



编辑:所以我的问题不清楚,所以我会解释它更详细。我有一堆我想循环访问的类,并调用 Let 属性。我的简化设置是:

pre $ Dim AllClasses as Collection
Sub SetAll(TargetProperty as String,Value as Variant)

对于AllClasses中的每个ClassX

CallByName ClassX,TargetProperty,vbLet,Value

Next ClassX

End Sub

当它被初始化为<$时,问题是 Value C $ C>变体。唯一一次,我可以让它不抛出类型不匹配异常是当我初始化作为属性想要的完全相同的类型,但我不能这样做,因为编辑2:我会问关于整个问题的另一个问题,因为没有人似乎知道很多关于 CallByName



编辑3:以下是我们到目前为止的摘要:


  • CallByName 的第四个参数(Args)在尝试调用时抛出类型不匹配> Let 类的属性。只有当试图分配的值存储在 Variant 数据类型中时,才会发生这种情况。 如果变量初始化为相同类型的让属性期望或者如果该值被硬编码到参数中,那么它可以很好地工作。


  • 让属性可以自行工作。它接受 Variant 数据类型就好。

  • 我的问题是:有没有办法停止此异常?我创建另一篇文章了解我的整体问题的其他可能的解决方案。

    解决方案

    问题在于你通过引用传递属性参数而不是但不能将引用传递给其他数据类型(variant - > long),因为类型不匹配,并且无法转换,因为这也会更改调用方中的数据类型。通过使用括号,您强制参数被值传递,它可以被转换为类型 Long



    您可以通过在属性字母中使用 ByVal 来避免此情况而不是 ByRef (如果未设置,隐式使用什么)。你知道通过引用一个变量,属性中所做的更改也会更改调用者的值?



    示例:

    类PassExample



    'Save as class module PassExample
    Public Property让PropByVal(ByVal NewVal As Long)
    NewVal = 1
    End Property
    Public Property让PropByRef(ByRef NewVal As Long)
    NewVal = 1
    End Property

    使用test子模块:

     'save作为标准模块
    Sub test()
    Dim v As Variant
    v = 0

    Dim ExampleInstance As New PassExample

    CallByName ExampleInstance, PropByVal,VbLet,v'这个工程
    CallByName ExampleInstance,PropByRef,VbLet,v'类型不匹配
    CallByName ExampleInstance,PropByRef,VbLet,(v)'This as the ByRef is changed to byval
    Debug.Print v'显示0,而不是1,因为它应该是引用

    CallByName ExampleInstance,PropByRef,VbLet,CVar(v)它传递了一个无法被引用的函数结果

    End Sub

    感谢Rory和chris neilsen提供解决方案!


    Solution: Just put brackets around Value in the CallByName statement to force evaluation of it.

    Ex. CallByName MobClass, TargetData, vbLet, (Value)

    Credit goes to Rory from the other post, which I will probably be deleting since it is no longer relevant and a possible duplicate.

    I've spent a long time trying to figure out what was wrong with how I was using CallByName. I finally realized that its fourth argument (Args) will throw a type mismatch if the input is not either EXACTLY the same type as the input argument of what its calling or its hard-coded in.

    (I don't even understand how, or why, it does this since VarType(Variant/Integer) = VarType(Integer))

    So I either need a way to make it accept variant inputs or convert variables from Variant/Integer to Integer (or create a new variable) without a giant select case.

    Edit: So my question wasn't clear so I'll explain it in more detail. I have a bunch of classes that I want to cycle through and call the Let property on. My simplified setup is:

    Dim AllClasses as Collection 
    Sub SetAll(TargetProperty as String, Value as Variant)
    
        For each ClassX in AllClasses
    
            CallByName ClassX, TargetProperty, vbLet, Value
    
        Next ClassX
    
    End Sub 
    

    The problem is Value when it is initialized as Variant. The only time I can get it to not throw a type mismatch exception is when I initialize Value as the exact same type that the property wants, but I can't do that since the data types in the class vary.

    Edit 2: I'm going to ask another question about the whole problem since no one seems to know much about CallByName

    Edit 3: Here's a summary of what we have so far:

    • CallByName's fourth argument (Args) throws a type mismatch when trying to call the Let property on a class.

    • This only happens when the value trying to be assigned is stored in a Variant data type. It works perfectly if the variable is initialized to the same type the Let property is expecting OR if the value is hard-coded into the argument.

    • The Let property works fine on its own. It accepts Variant data types just fine.

    • My question is: Is there a way to stop this exception? I'm creating another post about other possible solutions to my overall problem.

    解决方案

    The Problem is that you pass the properties-arguments by reference not by value, but you can't pass a reference to a different datatype (variant -> long) as the types don't match and it can't be converted as this would change the data type in the caller too. By using brackets, you force the argument to be passed by value and it can be casted as typeLong.

    You can avoid this by using ByValin theProperty Letterinstead ofByRef(what is implicit used if not set). You are aware that by referencing a variable, changes made in the property change the callers value too?

    Example:

    Class PassExample

    'Save as class module PassExample
    Public Property Let PropByVal(ByVal NewVal As Long)
    NewVal = 1
    End Property
    Public Property Let PropByRef(ByRef NewVal As Long)
    NewVal = 1
    End Property 
    

    Module with test sub:

    'save as standard module
    Sub test()
    Dim v As Variant
    v = 0
    
    Dim ExampleInstance As New PassExample
    
    CallByName ExampleInstance, "PropByVal", VbLet, v 'this works
    CallByName ExampleInstance, "PropByRef", VbLet, v 'type mismatch
    CallByName ExampleInstance, "PropByRef", VbLet, (v) 'this works as ByRef is changed to byval
    Debug.Print v ' shows 0, not 1 as it should be if referenced
    
    CallByName ExampleInstance, "PropByRef", VbLet, CVar(v) ' works too as it passes a function-result that can't be referenced
    
    End Sub
    

    Thanks to Rory and chris neilsen for providing the solution!

    这篇关于VBA - CallByName不会接受变体参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆