VBA没有为可选参数指定值

时间:2017-02-01 21:49:35

标签: vba

我想使用类似

的语句添加到集合中
myCollection.Add myItem, After:=Iif(myCollection.Count > 0, myCollection.Count, vbNull)

换句话说,我想决定是否要指定参数" After",如果我不想,那么我想在其中传递非值值'的地方。

比为每个场景单独调用要简单得多。

这可以在VBA中使用吗?

3 个答案:

答案 0 :(得分:5)

是的,可以在VBA中(更新以避免CopyMemory的复杂化)

使用以下代码将新模块 mdlMissingVariant 添加到您的VBA项目中:

Public Function getMissingVariant(Optional v As Variant) As Variant
    getMissingVariant = v
End Function

现在,只要您想让VBA认为您没有为参数提供值,请使用getMissingVariant()(不提供参数)。例如,定义以下函数:

Public Sub testOpt(Optional v As Variant)
    Debug.Print IsMissing(v)
End Sub

用...测试

testOpt getMissingVariant()

...看到VBA IsMissing函数检测到未提供参数。这可行的原因是Variant is a 16-byte structure,其中包含2-byte code describing the type of data it contains。其中一种类型(实际上是10种)是VT_ERROR。如果未向可选Variant提供参数,则内部VBA会将Variant的类型更改为“VT_ERROR”并指定值& H80020004(Long),即the Windows error code for "Parameter not found"

修改

我的立场得到了纠正 - 正如@Nik指出的那样,“缺失的”Variant 可以用作IIF的参数,因此您的代码可以正常工作!

答案 1 :(得分:5)

我将首先提出一个警告,即Collection.Add使用IIf语句调用{strong> &#34 ;清洁"而不是有两个不同的电话。 IIf函数,带有函数调用的开销。此外,由于true部分和false部分都作为参数传递, 的评估 ,无论 条件是真还是假。这意味着您总是两次致电myCollection.Count。除了效率低得多之外,它的可读性要低得多。除非你code golfing,否则根本没有充分理由使用IIf。这在几个层面上要好得多:

If myCollection.Count > 0 Then
    myCollection.Add myItem, , myCollection.Count
Else
    myCollection.Add myItem
End If

此外,正如评论中所述,Collection 保留已添加项目的顺序,因此上述代码与以下代码相同:

myCollection.Add myItem

好的,如果您真的感到被迫这样做了......另一个选择是简单地提供您自己的IIf重载和可选参数:< / p>

Private Function IIf(condition As Boolean, Optional truepart As Variant, _
                     Optional falsepart As Variant)
    IIf = VBA.IIf(condition, truepart, falsepart)
End Function

请注意,这&#34;隐藏&#34;您声明函数的范围内的内置VBA函数,因此您应该对其进行大量注释,并确保它不会破坏代码中其他位置的IIf的其他调用。提供重载后,您可以像内置一样使用它,但省略参数:

Public Sub Example()
     ValueOfIIf IIf(True, , "Foo")
End Sub

Public Sub ValueOfIIf(result As Variant)
    Debug.Print IsMissing(result)    '<--True
End Sub

答案 2 :(得分:2)

除了在这个特殊情况下,我认为它是多余的,因为它们应该按顺序添加到集合中,而不指定“后”;我想到了两件事:

1)您可以使用iif功能并利用“缺失”属性(不确定是否有更好的方法)。

Sub my_collection(Optional b As Variant)

    Dim x As Collection
    Set x = New Collection

    'if you just run my_collection without passing anything
    'b will be "missing"
    x.Add "Test", After:=IIf(x.Count, x.Count, b)

End Sub

因为你从未将b传递给my_collection,所以b将永远“缺失”(你可以使用IsMissing()进行测试)

2)添加值的功能

Sub my_collection()

    Dim x As Collection
    Set x = New Collection
    Dim v As String
    v = "test"
    Call add_to_collection(x, v)

End Sub
Sub add_to_collection(ByRef y As Collection, q As Variant)
    If y.Count Then
        y.Add q, After:=y.Count
    Else
        y.Add q
    End If
End Sub