VBA:是什么导致传递给 ParamArray 的字符串参数更改为数字(看起来可疑地像指针)?
最终编辑:它确实似乎是一个编译器错误 - 请参阅已接受的答案。
在 Excel 2007 中使用 VBA,我在“Class1”中有以下代码:
Option Explicit
Public Function strange(dummy As String, ParamArray pa())
Debug.Print pa(LBound(pa))
End Function
Public Sub not_strange(dummy As String, ParamArray pa())
Debug.Print pa(LBound(pa))
End Sub
Public Function also_not_strange(ParamArray pa())
Debug.Print pa(LBound(pa))
End Function
以及模块中的一些模式代码:
Option Explicit
Public Function not_strange_either(dummy As String, ParamArray pa())
Debug.Print pa(LBound(pa))
End Function
Public Sub outer(v)
Dim c As Class1
Set c = New Class1
Call c.strange("", v(LBound(v)))
Call c.not_strange("", v(LBound(v)))
Call c.also_not_strange(v(LBound(v)))
Call not_strange_either("", v(LBound(v)))
End Sub
如果从“立即”窗口调用“外部”,如下所示:
call outer(array("a"))
我得到的输出看起来很奇怪:
102085832
a
a
a
似乎很重要被调用的例程是否在类模块中,无论它是 Sub 还是 Function,以及是否有初始参数。我是否遗漏了有关 VBA 应该如何工作的信息?有什么想法吗?
这个奇怪的数字在每次运行中都会发生变化。我说“看起来可疑地像一个指针”,因为如果我这样称呼:
Public Sub outer2(v)
Dim c As Class1
Set c = New Class1
Dim ind As Long
For ind = LBound(v) To UBound(v)
Call c.strange("", v(ind))
Next ind
End Sub
就像这样:
call outer2(array("a","b","c"))
我得到的输出如下:
101788312
101788328
101788344
增量 16 让我怀疑,但我真的不知道。另外,传递一个值,例如通过调用:
Call c.strange("", CStr(v(ind)))
工作得很好。
编辑:更多信息...如果我将“c.strange”的返回值分配给某个东西而不是扔掉它,我会得到相同的行为:
Public Sub outer3(v)
Dim c As Class1
Set c = New Class1
Dim x
x = c.strange("", v(LBound(v)))
Call c.not_strange("", v(LBound(v)))
Call c.also_not_strange(v(LBound(v)))
Call not_strange_either("", v(LBound(v)))
End Sub
有趣的是,如果我如上所述调用我的测试例程,并带有一个参数由于调用“Array”,假定的指针值发生变化。但是,如果我这样调用:
call outer([{1,2,3}])
即使我重复拨打电话,我也会得到相同的号码。 (如果我切换到 Windows 中的另一个应用程序,例如我的浏览器,该数字会发生变化。)所以,现在我很好奇 Excel 求值器(用括号调用)似乎会缓存其结果......
FINAL EDIT: It does indeed appear to be a compiler bug - see the accepted answer.
Using VBA within Excel 2007, I have the following code in 'Class1':
Option Explicit
Public Function strange(dummy As String, ParamArray pa())
Debug.Print pa(LBound(pa))
End Function
Public Sub not_strange(dummy As String, ParamArray pa())
Debug.Print pa(LBound(pa))
End Sub
Public Function also_not_strange(ParamArray pa())
Debug.Print pa(LBound(pa))
End Function
and some mode code in a module:
Option Explicit
Public Function not_strange_either(dummy As String, ParamArray pa())
Debug.Print pa(LBound(pa))
End Function
Public Sub outer(v)
Dim c As Class1
Set c = New Class1
Call c.strange("", v(LBound(v)))
Call c.not_strange("", v(LBound(v)))
Call c.also_not_strange(v(LBound(v)))
Call not_strange_either("", v(LBound(v)))
End Sub
If call 'outer' from the Immediate window like this:
call outer(array("a"))
I get back output that seems strange:
102085832
a
a
a
It seems to matter whether the called routine is in a class module or not, whether it is a Sub or a Function, and whether or not there is an initial argument. Am I missing something about how VBA is supposed to work? Any ideas?
The strange number changes from run to run. I say "looks suspiciously like a pointer" because if I call this:
Public Sub outer2(v)
Dim c As Class1
Set c = New Class1
Dim ind As Long
For ind = LBound(v) To UBound(v)
Call c.strange("", v(ind))
Next ind
End Sub
like so:
call outer2(array("a","b","c"))
I get back output like:
101788312
101788328
101788344
It's the increment by 16 that makes me suspicious, but I really don't know. Also, passing a value, say by calling:
Call c.strange("", CStr(v(ind)))
works just fine.
EDIT: A little more info...If I assign the return value from 'c.strange' to something instead of throwing it away, I get the same behavior:
Public Sub outer3(v)
Dim c As Class1
Set c = New Class1
Dim x
x = c.strange("", v(LBound(v)))
Call c.not_strange("", v(LBound(v)))
Call c.also_not_strange(v(LBound(v)))
Call not_strange_either("", v(LBound(v)))
End Sub
Interestingly, if I call my test routines as above, with an argument that results from calling 'Array', the supposed-pointer value changes. However, if I call it like this:
call outer([{1,2,3}])
I get back the same number, even if I make the call repeatedly. (The number changes if I switch to another app in Windows, like my browser.) So, now I'm intrigued that the Excel evaluator (invoked with the brackets) seemingly caches its results...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
现在这太棒了。
转载于 Office 2003。
看起来像一个编译器错误。
问题出在这一行:
这里编译器创建一个
Variant
,它保存一个Variant
的一维数组,其中唯一的元素是指针而不是值。然后,该指针转到奇怪的函数,该函数实际上并不奇怪,它只打印传递给它的 Variant\Long 值。这个技巧使编译器恢复理智:
编辑
是的,这个幻数是指向 VARIANT 结构的指针,该结构应该传递给奇怪的方法。第一个字段是
8
,即vbString
,数据字段包含一个指向实际字符串"a"
的指针。因此,这绝对是一个编译器错误...又一个关于数组的 VB 编译器错误;)
Now this is awesome.
Reproduced on office 2003.
Looks like a compiler bug.
The problem is in this line:
Here the compiler creates a
Variant
that holds a 1D array ofVariant
's, the only element of which is a pointer instead of the value. This pointer then goes to thestrange
function which actually is not strange, it only prints theVariant\Long
value passed to it.This trick brings the compiler sanity back:
EDIT
Yes, this magic number is a pointer to the VARIANT structure which is supposed to be passed to the
strange
method. The first field of which is8
, which isvbString
, and the data field contains a pointer to the actual string"a"
.Therefore, it is definitely a compiler bug... Yet another VB compiler bug in regard of arrays ;)