请考虑以下代码:
Option Explicit
Public Property Let Dummy(v() As Integer)
End Property
Public Sub LetDummy(v() As Integer)
End Sub
Sub Foo()
ReDim i(0 To 2) As Integer
i(0) = 3
i(1) = 45
i(2) = 10
Bar i ' internal error 51
End Sub
Sub Foo2()
ReDim i(0 To 2) As Integer
i(0) = 3
i(1) = 45
i(2) = 10
Bar2 i ' no error
End Sub
Sub Foo3()
ReDim i(0 To 2) As Integer
i(0) = 3
i(1) = 45
i(2) = 10
Dummy = i ' no error
End Sub
Sub Bar(j() As Integer)
Dummy = j
End Sub
Sub Bar2(j() As Integer)
LetDummy j
End Sub
当我运行宏观' Foo'我收到消息'内部错误51'但是' Foo2'和' Foo3'运行正常。这种行为的原因是什么?或者它只是VBA中的一个错误?如何解决这个错误?
背景:在我的应用程序中,我想将作为函数参数提供的数组赋值给array类型的属性。
答案 0 :(得分:4)
对我来说这看起来像个错误,因为错误51说如果你得到它就联系MS。
如果我创建一个局部变量,分配它,然后传递它似乎工作。
非常hacky。
Option Explicit
Private ary() As Integer
Public Property Get Dummy() As Integer()
Dummy = ary
End Property
Public Property Let Dummy(v() As Integer)
Debug.Print "In Dummy" & UBound(v)
ary = v
End Property
Public Sub LetDummy(v() As Integer)
Debug.Print "In LetDummy" & UBound(v)
End Sub
Sub Foo()
ReDim i(0 To 2) As Integer
i(0) = 3
i(1) = 45
i(2) = 10
Call Bar(i) ' internal error 51
End Sub
Sub Foo2()
ReDim i(0 To 2) As Integer
i(0) = 3
i(1) = 45
i(2) = 10
Bar2 i ' no error
End Sub
Sub Foo3()
ReDim i(0 To 2) As Integer
i(0) = 3
i(1) = 45
i(2) = 10
Dummy = i ' no error
End Sub
Sub Bar(j() As Integer)
Dim i() As Integer
i = j
Dummy = i
Dim x As Integer
Dim myary() As Integer
myary = Dummy
For x = 0 To 2
Debug.Print myary(x)
Next
End Sub
Sub Bar2(j() As Integer)
LetDummy j
End Sub
答案 1 :(得分:1)
使用 $html="";
$pqr = mysqli_query($link,$sql);
while($row = mysqli_fetch_row($pqr))
{
$html .= "<a class='fancybox' rel='gallery1' href='".$row[2].$row[3]."' width='270'>";
$html .= "<img src='".$row[2].$row[3]."' width='270'>";
$html .= "</a>";
}
echo $html;
}
echo $html;
Variant
答案 2 :(得分:1)
这是一个非常有趣的错误。在尝试重现它时,我提出了这个:
Public Property Let Foo(ByRef values() As Long)
End Property
Public Sub Test()
Dim values(0 To 1) As Long
values(0) = 1
values(1) = 2
IllegalByRefArray values
End Sub
Private Sub IllegalByRefArray(ByRef values() As Long)
Stop 'break here or crash Excel
Foo = values
End Sub
而不是运行时错误51,我遇到了严重的崩溃。 “Excel已经停止工作了”,而且噗不通。运行64位Excel 2010。
在附加了Visual Studio调试器的情况下运行Excel,我可以看到EXCEL.EXE进程如何彻底破坏Foo = values
任务:
EXCEL.EXE中0x00007FFF834E4B90(ntdll.dll)处的未处理异常:0xC0000028:在展开操作期间遇到无效或未对齐的堆栈
所以肯定会发生一些可疑的事情。事实上,暴露数组的属性首先是一种奇怪的东西:通常你将封装数组并公开索引属性,即这样的事情:
Private internal() As Long 'todo initialize
Public Property Let Foo(ByVal index As Long, ByVal value As Long)
internal(index) = value
End Property
Public Property Get Foo(ByVal index As Long) As Long
Foo = internal(index)
End Property
尽管如此,该语言并没有明确禁止将数组暴露为属性......或者它是什么?
这是一个编译时错误,即 无法分配给数组 :
Public Property Let Foo(ByRef values() As Long)
End Property
Public Sub Test()
Dim values(0 To 1) As Long
values(0) = 1
values(1) = 2
Foo = values ' compile error / can't assign to array
End Sub
所以将数组传递给一个程序然后将它传递给Property Let
似乎是一个利用VBE相当差的静态代码分析的黑客,以便绕过编译错误,这可能是有原因的。< / p>
我们知道我们无法在VBA中传递数组ByVal
。尝试这样做甚至不是编译错误,它是语法错误,VBE显然对它不满意:
这指向隐式传递参数ByVal
的属性的Rory's comment。这是一些证据:
Public Property Let Foo(ByRef values As Variant)
Debug.Print "Foo: " & VarPtr(values)
End Property
Public Sub Test()
Dim values(0 To 1) As Long
values(0) = 1
values(1) = 2
Dim v As Variant
v = values
Debug.Print "Test: " & VarPtr(v)
IllegalByRefArray v
End Sub
Private Sub IllegalByRefArray(ByRef values As Variant)
Debug.Print "IllegalByRefArray: " & VarPtr(values)
Foo = values
End Sub
运行Test
过程会打印此(或类似)输出:
Test: 196542488
IllegalByRefArray: 196542488
Foo: 196542352
请注意,变量指针在Test
和IllegalByRefArray
中是相同的,但Foo
,中的变量指针不同,而不管ByRef
修饰符。如果您将IllegalByRefArray
中的修饰符更改为ByVal
,则会获得3个不同的值:
Test: 196542488
IllegalByRefArray: 196542384
Foo: 196542336
从接受的答案:
如果我创建一个局部变量,分配它,然后传递它似乎工作。
当然可以;你现在传递的指针不同于你收到的指针,VBA通过上面描述的几种方式尝试,以阻止你将指向数组的指针传递给Property Let
mutator:VBA试图告诉你很多方面,你所做的不是你应该做的事情。
以正确的方式执行操作,保持数组封装,并公开索引属性,而不是允许数组本身被覆盖。
如果你不关心封装,那么把它变成一个公共领域:该属性实际上没有用处。
Public Values() As Long
在那里,随意分配。
如果必须为该数组提供Property Let
mutator,那么干净的解决方案是pass the array as a Variant
;是的,这意味着您需要调整代码的其余部分。
ByRef
mutator 上的Property Let
修饰符毫无意义:这是公然谎言(它是不通过引用传递!)并使您的代码非常混乱。不要在ByRef
值参数上粘贴Property Let
修饰符只是为了满足语言语法,否则会拒绝传递数组参数 - 您正在扭曲VBA的手臂,危及用户未保存的工作,以及让你的代码说谎。
改为传递Variant
,或通过索引属性正确封装数组。其他任何东西只是一个肮脏的恶臭黑客。