解决方案:只需在CallByName语句中将值括在Value旁边即可强制对其进行评估。
实施例。 CallByName MobClass, TargetData, vbLet, (Value)
Rory从另一篇文章转到Rory,我可能会删除它,因为它不再相关且可能重复。
我花了很长时间试图弄清楚我如何使用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
问题是Value
初始化为Variant
时。我唯一一次不能抛出类型不匹配异常就是当我将Value
初始化为属性所需的完全相同的类型时,但由于类中的数据类型不同,我不能这样做。 / p>
编辑2:我将问另一个关于整个问题的问题,因为似乎没人知道CallByName
编辑3:这是我们到目前为止的总结:
CallByName
的第四个参数(Args)在尝试调用类的Let
属性时抛出类型不匹配。
仅当尝试分配的值存储在Variant
数据类型中时才会发生这种情况。如果将变量初始化为Let
属性期望的相同类型,则它可以正常工作,如果该值被硬编码到参数中,则可以正常工作。
Let
属性可以自行运行。它接受Variant
数据类型就好了。
我的问题是:有没有办法停止此异常?我正在创建another post关于我整体问题的其他可能解决方案。
答案 0 :(得分:2)
问题是你通过引用而不是通过值传递属性参数,但是你不能将引用传递给不同的数据类型(variant - > long),因为类型不匹配,它不能转换,因为这将改变调用者中的数据类型。通过使用括号,您force the argument to be passed by value可以将其转换为Long
类型。
您可以使用ByVal
中的Property Letter
代替ByRef
来避免这种情况(如果未设置则隐式使用)。您知道通过引用变量,属性中所做的更改也会更改调用者值吗?
示例:
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
带有测试子的模块:
'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提供解决方案!