我一直在某个特定的应用程序中使用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注意,第2行debug.print显示了在class1.MyData中存储的值是312080296,而不是5.8。
发布于 2014-12-22 21:51:46
这里也是一样的。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(W(1,1))执行debug.print。我发现W(1,1)的myData值和VarPtr值是一一对应的。我假设这是CallByName函数行为的一部分,至于传递地址,而不是值,但我没有时间进一步研究。希望这能有所帮助。
发布于 2014-12-22 22:03:09
我让这条线正常工作,
CallByName class1, "MyData", VbLet, CVar(W(1, 1))
我唯一能想到的是CallByName期望Args()是一个Variant,而W(1,1)不能隐式转换..(出于某种原因)
https://stackoverflow.com/questions/27610176
复制相似问题