将函数的结果写入变量,其中结果可以是对象



如果我有一个可能返回对象或基元类型的函数 - 在其中我可以执行以下操作来处理这两种情况:

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

我正在尝试将一系列对象/非对象写入变体类型的数组

一种可能的解决方案是通过将其传递给变量来直接写入变量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

例如,一个类的代码片段,它处理动态调用类函数。如果可以基于RubberDuck Reflection API实现一些基本的VBA反射,那么原型设计的工作正在进行中。由于我动态调用类和模块函数,因此没有可靠的方法可以提前知道是否将从函数调用返回原语或对象类型。

注意 我尚未测试代码,需要向 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 扩展库中的代码

' 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(( 函数并将函数或属性输出包装在其中。
当我测试我的原始解决方案时,从内存中,它不适用于值来自仅类函数的属性的位置。在使用接口或直接使用属性并获取变体结果时,这是一个问题。
注意:我认为它不适用于返回 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

相关内容

  • 没有找到相关文章

最新更新