如何测试是否提供了可选参数?

87

我该如何测试可选参数是否提供?--在VB6 / VBA中

Function func (Optional ByRef arg As Variant = Nothing)

    If arg Is Nothing Then   <----- run-time error 424 "object required"
        MsgBox "NOT SENT"
    End If

End Function 
9个回答

113

使用 IsMissing

If IsMissing(arg) Then
    MsgBox "Parameter arg not passed"
End If

然而,如果我没记错,当为参数提供默认值时,这种方法不起作用,而且在任何情况下都使使用默认参数变得多余。


33
我认为IsMissing只有在参数声明为Variant类型时才起作用。 - Jon Fournier
5
@Jon: 是的,因为IsMissing是基于VARIANT结构中的标志实现的(如果我没记错的话是VT_EMPTY)。我没有提到这一点,因为OP的问题已经使用了Variant - Konrad Rudolph

25

你可以使用IsMissing()函数。但是该函数仅适用于Variant数据类型。

Sub func(Optional s As Variant)
   If IsMissing(s) Then
      ' ...
   End If
End Sub

10

如果您正在使用字符串或数字变量,可以检查变量的值。例如:

Function func (Optional Str as String, Optional Num as Integer)

If Str = "" Then
    MsgBox "NOT SENT"
End If

If Num = 0 Then
    MsgBox "NOT SENT"
End If

End Function

这使您能够使用非变量变量。


4
它无法完美地区分有效的用法,例如: func("", 0) 将错误地标记未设置的参数。一般情况下,除非使用“变量”,否则没有办法做到这种区分。 - Konrad Rudolph
@KonradRudolph 非常好的观点。您需要确保在可能发送空字符串或零数量的情况下永远不要使用它。 - OSUZorba
如果Num = 0,则对于Int值存在问题。如果用户手动将参数设置为0,您会怎么做? - Hasan Merkit

7
您可以使用以下方式:

您可以使用以下方式:

function func(optional vNum as integer:=&HFFFF) '&HFFFF value that is NEVER set on vNum

If vNum = &HFFFF Then
    MsgBox "NOT SENT"
End If

End Function

这个很聪明。推荐的“isMissing”仅适用于变体数据类型,而这个原则是相当普遍的。 - Eleshar
1
这是微软的正确答案:“过程无法在运行时检测到是否省略了给定参数...将一个不太可能的值设置为默认值。”。https://learn.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/procedures/optional-parameters - DaveP
在VBA中无法工作,计算结果为-1。 - drgs

4

大多数情况下,这些是针对变体类型的引用,或者用于测试值是否为空。

然而,有时候你想要检查一个范围、工作簿、工作表或其他类型的对象是否未传递,而不必检查诸如工作表名称之类的内容。

在这种情况下:

DesiredRange is Nothing

返回布尔值。例如:
    If DestinationRange Is Nothing Then
        MsgBox "Need a destination range when importing data"
    Else
        'We're happy
    End If

1
棘手的部分是,并非每种类型的对象都可以使用is Nothing进行检查,而任何对象都可以存储在Variant类型中。因此,要明确的是,这适用于像RangeWorksheet这样的对象的解决方案,但不适用于其他类型,如String - Marcucciboy2

3
如果 IsMissing(arg) 为真,则...

2
如果我要使用变体,我会使用NZ函数:
Function func (Optional ByRef arg As Variant = Nothing)
    If nz ( arg, 0 ) = 0 Then
        MsgBox "NOT SENT"
    End If
End Function 

它也可以与其他数据类型一起使用,只需记住零既不计算为空值,也不计算长度为零的值,因此nz(0,"")仍然返回0。


0

对于变量,使用"IsMissing(var)"
对于字符串,使用"StrPtr(var) = 0"

对于其他数据类型,没有完美的解决方案,只能测试它们的默认值,因此无法区分未传递的参数和传递的参数的默认值。


-1

"IsMissing"...我想肯定有办法。谢谢大家!

SQL有一个函数In(),可以传递多个参数来查看目标值是否在列表中。我一直喜欢这种解决方案,所以这是我的方法,希望能帮到你:

Public Function IsIn(ByVal TestVal, ByVal VersusVal1, _
            Optional ByVal VersusVal2, Optional ByVal VersusVal3, _
            Optional ByVal VersusVal4, Optional ByVal VersusVal5, _
            Optional ByVal VersusVal6, Optional ByVal VersusVal7, _
            Optional ByVal VersusVal8, Optional ByVal VersusVal9, _
            Optional ByVal VersusVal10, Optional ByVal VersusVal11, _
            Optional ByVal VersusVal12, Optional ByVal VersusVal13, _
            Optional ByVal VersusVal14, Optional ByVal VersusVal15, _
            Optional ByVal VersusVal16, Optional ByVal VersusVal17, _
            Optional ByVal VersusVal18, Optional ByVal VersusVal19, _
            Optional ByVal VersusVal20) As Boolean

Dim CheckVals(1 To 20) as Variant
VersusVals(1) = VersusVal1
VersusVals(2) = VersusVal2
VersusVals(3) = VersusVal3
VersusVals(4) = VersusVal4
VersusVals(5) = VersusVal5
VersusVals(6) = VersusVal6
VersusVals(7) = VersusVal7
VersusVals(8) = VersusVal8
VersusVals(9) = VersusVal9
VersusVals(10) = VersusVal10
VersusVals(11) = VersusVal11
VersusVals(12) = VersusVal12
VersusVals(13) = VersusVal13
VersusVals(14) = VersusVal14
VersusVals(15) = VersusVal15
VersusVals(16) = VersusVal16
VersusVals(17) = VersusVal17
VersusVals(18) = VersusVal18
VersusVals(19) = VersusVal19
VersusVals(20) = VersusVal20

On Error Goto 0

IsIn = False

For x = 1 To 20
   If Not IsMissing(VersusVals(x)) Then
      If TestVal = VersusVals(x) Then
         IsIn = True
         Exit For
      End If
   End If
Next x

End Function

所以,这就是为什么我需要“IsMissing”的明显原因;没有它就无法工作。


5
这里实际上不需要也不应该使用 IsMissing。相反,这是对“ParamArray”的应用。 - Konrad Rudolph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接