将函数的结果写入变量,其中结果可以是对象
Write result of function to a variable, where result could be an object
如果我有一个可以 return 对象或基本类型的函数 - 在其中我可以执行以下操作来处理这两种情况:
Function Result() As Variant 'may be object or not
'... get item - the return value
If IsObject(item) Then
Set Result = item
Else
Result = item
End If
End Function
但是,如何在没有运行函数的情况下对存储Result
的变量进行两次相同的测试?例如
Dim myResult As Variant
If IsObject(Result) Then 'test return type of function
Set myResult = Result
Else
myResult = Result
End If
作为
myResult = Result 'fails if Result returns object
Set myResult = Result 'fails if Result returns non-object
我正在尝试将一系列 objects/non 对象写入变体类型的数组
嗯,一种可能的解决方案是直接写入变量,通过传递它 ByRef
。在标准模块中:
Property Let LetSet(ByRef variable As Variant, ByVal value As Variant)
If IsObject(value) Then
Set variable = value
Else
variable = value
End If
End Sub
叫得像
Dim myResult As Variant
LetSet(myResult) = 123 'myResult = 123
LetSet(myResult) = New Collection 'Set myResult = New Collection
例如来自 class 的片段,它处理动态调用 class 函数。如果可以基于 RubberDuck Reflection API 实现一些基本的 VBA 反射,原型制作正在进行中。当我动态调用 class 和模块函数时,没有可靠的方法可以提前知道函数调用返回的是原始类型还是对象类型。
请注意,我还没有测试代码,需要在 InvokeMember 函数中添加一些错误处理。
Greedo 的解决方案类似,期望函数结果是一个单独的引用参数,这样可以放入函数调用中,例如。 CallByName 作为第二个参数。第一个参数是存储引用调用结果的变量。函数结果参数 y 通过引用作为数组可能的结果,并避免在传入时将整个数组复制到内存中。
Public Function InvokeMember(ByVal obj As Object, ParamArray args() As Variant) As Variant
Assign InvokeMember, CallByName(obj, Me.FullName, Me.CallType, args)
End Function
在模块中,来自 VBA Extension Library
的代码
' Assign x to y regardless of object or primitive
Public Sub Assign(ByRef x as Variant, ByRef y as Variant)
If IsObject(y) Then
Set x = y
Else
x = y
End If
End Sub
感谢您的提问,它帮助我解决了同样的问题,避免在处理返回的对象、数组或原始数据类型时调用同一个函数两次。
另一种解决方案是使用 Array() 函数并将函数或 属性 输出包装在其中。
根据记忆,当我测试我的原始解决方案时,它不适用于值来自 class 的 属性 的地方。这是使用接口或直接使用 属性 并获得变体结果时的问题。
注意:我认为它不适用于 functions/properties 返回 UDT 或固定字符串长度。
对于您的示例,请使用以下内容:
Dim myResult As Variant
Dim resultOutput as Variant
resultOutput = Array(Result)
If VBA.IsObject(resultOutput(0)) Then
set myResult = resultOutput(0)
Else
myResult = resultOutput(0)
End If
如果我有一个可以 return 对象或基本类型的函数 - 在其中我可以执行以下操作来处理这两种情况:
Function Result() As Variant 'may be object or not
'... get item - the return value
If IsObject(item) Then
Set Result = item
Else
Result = item
End If
End Function
但是,如何在没有运行函数的情况下对存储Result
的变量进行两次相同的测试?例如
Dim myResult As Variant
If IsObject(Result) Then 'test return type of function
Set myResult = Result
Else
myResult = Result
End If
作为
myResult = Result 'fails if Result returns object
Set myResult = Result 'fails if Result returns non-object
我正在尝试将一系列 objects/non 对象写入变体类型的数组
嗯,一种可能的解决方案是直接写入变量,通过传递它 ByRef
。在标准模块中:
Property Let LetSet(ByRef variable As Variant, ByVal value As Variant)
If IsObject(value) Then
Set variable = value
Else
variable = value
End If
End Sub
叫得像
Dim myResult As Variant
LetSet(myResult) = 123 'myResult = 123
LetSet(myResult) = New Collection 'Set myResult = New Collection
例如来自 class 的片段,它处理动态调用 class 函数。如果可以基于 RubberDuck Reflection API 实现一些基本的 VBA 反射,原型制作正在进行中。当我动态调用 class 和模块函数时,没有可靠的方法可以提前知道函数调用返回的是原始类型还是对象类型。
请注意,我还没有测试代码,需要在 InvokeMember 函数中添加一些错误处理。
Greedo 的解决方案类似,期望函数结果是一个单独的引用参数,这样可以放入函数调用中,例如。 CallByName 作为第二个参数。第一个参数是存储引用调用结果的变量。函数结果参数 y 通过引用作为数组可能的结果,并避免在传入时将整个数组复制到内存中。
Public Function InvokeMember(ByVal obj As Object, ParamArray args() As Variant) As Variant
Assign InvokeMember, CallByName(obj, Me.FullName, Me.CallType, args)
End Function
在模块中,来自 VBA Extension Library
的代码' Assign x to y regardless of object or primitive
Public Sub Assign(ByRef x as Variant, ByRef y as Variant)
If IsObject(y) Then
Set x = y
Else
x = y
End If
End Sub
感谢您的提问,它帮助我解决了同样的问题,避免在处理返回的对象、数组或原始数据类型时调用同一个函数两次。
另一种解决方案是使用 Array() 函数并将函数或 属性 输出包装在其中。
根据记忆,当我测试我的原始解决方案时,它不适用于值来自 class 的 属性 的地方。这是使用接口或直接使用 属性 并获得变体结果时的问题。
注意:我认为它不适用于 functions/properties 返回 UDT 或固定字符串长度。
对于您的示例,请使用以下内容:
Dim myResult As Variant
Dim resultOutput as Variant
resultOutput = Array(Result)
If VBA.IsObject(resultOutput(0)) Then
set myResult = resultOutput(0)
Else
myResult = resultOutput(0)
End If