我一直在特定应用程序中使用CallByName并获得无法解释的结果。它们在具有以下条件的简单测试中是可重复的
我很感激这种行为的解释。以下代码应该重现它(至少在Excel 2007 / Windows 7中)
工作表单元格 A1 包含 5.8
A2 包含 1.3 ,而A列中的其余单元格为空白。
课程模块(class1)
Private pMyData
Public Property Get MyData()
MyData = pMyData
End Property
Public Property Let MyData(Value)
pMyData = Value
End Property
常规模块
Option Explicit
Sub foo()
Dim class1 As class1
Dim V(1 To 2, 1 To 1) As Variant
V(1, 1) = [a1]
V(2, 1) = [a2]
Set class1 = New class1
CallByName class1, "MyData", VbLet, V(1, 1)
Debug.Print V(1, 1), class1.MyData ' <-- 5.8 5.8
Dim W As Variant
W = Range("A1:A2")
Set class1 = New class1
CallByName class1, "MyData", VbLet, W(1, 1)
Debug.Print W(1, 1), class1.MyData ' <-- 5.8 312080296
CallByName class1, "MyData", VbLet, CDbl(W(1, 1))
Debug.Print W(1, 1), class1.MyData ' <-- 5.8 5.8
End Sub
注意第二个debug.print行显示存储在class1.MyData中的值是312080296而不是5.8。
答案 0 :(得分:3)
这里也是一样的。获取145842640.如果它有帮助您不必使用CallByName。使用以下行可以帮我将其正确设置为5.8。
class1.MyData = W(1, 1)
也可能有助于将pMyData声明为double,也可以在Let / Get语句中声明。然后你会在尝试分配时遇到错误,比如第一个V(1,1),它会强制你明确地声明转换,这在这种情况下似乎是一件好事(或者说是必要的)。
无法找到一个很好的快速理由,为什么它会这样做,或转换实际上在做什么。希望有人知道,我现在很好奇。
编辑 - 看起来CallByName实际上是将W(1,1)的地址传递给Let语句。 (换句话说,传递指针的值。)它似乎通过CDbl解引用转换指针,获取值,这就是它与显式转换一起工作的原因。 (或者我认为无论如何。)
尝试添加此功能:
Public Declare PtrSafe Function VarPtrArray Lib "VBE7" Alias _
"VarPtr" (Var() As Any) As LongPtr
然后为W(1,1)执行debug.pring,为VarPtr执行debug.print(W(1,1))。我发现W(1,1)的myData和VarPtr值是同一个。我认为这是CallByName函数行为的一部分,只要传递地址,而不是值,但我没有时间进一步研究。希望有所帮助。
答案 1 :(得分:0)
我让这条线正常工作,
CallByName class1, "MyData", VbLet, CVar(W(1, 1))
我唯一能想到的是CallByName
期望Args()
为Variant
,W(1,1)
无法隐式投放..(出于某种原因)