VBA - CallByName 不接受变体参数



解决方案:只需在 CallByName 语句中的 Value 两边加上括号即可强制对其进行计算。

前任。CallByName MobClass, TargetData, vbLet, (Value)

归功于另一篇文章中的罗里,我可能会删除它,因为它不再相关并且可能是重复的。

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

(我什至不明白它是如何或为什么这样做的,因为VarType(Variant/Integer) = VarType(Integer)

)所以我要么需要一种方法来让它接受变体输入,要么在没有巨大选择的情况下将变量从Variant/Integer转换为Integer(或创建一个新变量)。

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

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 

初始化为VariantValue问题。我唯一能让它不抛出类型不匹配异常的时候是当我Value初始化为属性想要的完全相同的类型时,但我不能这样做,因为类中的数据类型各不相同。

编辑2:我要问另一个关于整个问题的问题,因为似乎没有人对CallByName了解很多

编辑3:以下是我们目前所拥有的摘要:

  • CallByName的第四个参数(Args)在尝试调用类的Let属性时抛出类型不匹配。

  • 仅当尝试分配的值存储在Variant数据类型中时,才会发生这种情况。如果变量初始化为Let属性期望的相同类型,或者如果值被硬编码到参数中,则它可以完美运行。

  • Let酒店本身运作良好。它接受Variant数据类型就好了。

  • 我的问题是:有没有办法阻止这种异常?我正在创建另一篇关于我整体问题的其他可能解决方案的文章。

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

您可以通过在Property Letter中使用ByVal而不是ByRef(如果未设置,则隐式使用什么)来避免这种情况。您是否知道通过引用变量,属性中所做的更改也会更改调用方值?

例:

课堂通行证示例

'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 

带测试子的模块:

'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

感谢Rory和Chris Neilsen提供的解决方案!

最新更新