为什么我的函数假定存在一个缺失的参数?

Why does my function assume a missing argument is there?

我有一个更新表单的功能,"LoadingInterface"。该函数如下所示:

Private Sub updateLoadingBar(Optional tekst As String, Optional barOnePerc As Long, Optional barTwoPerc As Long)
    If Not IsMissing(tekst) Then
        LoadingInterface.Label1.Caption = tekst
    End If
    If Not IsMissing(barOnePerc) Then
        LoadingInterface.Bar.Width = barOnePerc * 1.68
        LoadingInterface.prosent.Caption = barOnePerc & "%"
        LoadingInterface.prosent.Left = barOnePerc * 1.68 / 2 - 6
    End If
    If Not IsMissing(barTwoPerc) Then
        LoadingInterface.SubBar.Width = barTwoPerc * 1.68
    End If
    LoadingInterface.Repaint
End Sub

然后我这样调用函数,希望它只更新文本字段,因为缺少其他两个参数。

Call updateLoadingBar(tekst:="Test")

这适用于更新 Label1,但不幸的是其他两个值也被更新了 - 似乎在函数调用中不包含任何值使得 VBA 假设两个变量值是0. 更何况IsMissing函数在调用函数的时候好像没有检测到两个值缺失,这才是更大的问题。使用 F8 单步执行代码确认确实输入了所有 if 语句。

如果没有为参数 barOnePercbarTwoPerc 提供值,是否有任何方法可以使代码跳过函数中最下面的两个 if 语句?

IsMissing 仅当参数声明为 Variant 时有效。

我认为您无法有效地区分 Long 的 0 和未传递参数。在这种情况下,您需要在签名中声明为 Variant。如果需要,您可以稍后投射。

我猜你可以设置一个默认值(不太可能的数字)并进行测试。注意:我不会建议这样做。这只是尖叫 "Bug"。

IsMissing:

IsMissing returns a Boolean value indicating whether an optional Variant argument has been passed to a procedure.

Syntax: IsMissing(argname)

The required argname argument contains the name of an optional Variant procedure argument.

Remarks: Use the IsMissing function to detect whether or not optional Variant arguments have been provided in calling a procedure. IsMissing returns True if no value has been passed for the specified argument; otherwise, it returns False.

两种方法:

Option Explicit

Public Sub Test()
    RetVal
    RetVal2
End Sub

Public Function RetVal(Optional ByVal num As Long = 1000000) As Long

    If num = 1000000 Then

        MsgBox "No value passed"
        RetVal = num
    Else

        MsgBox "Value passed " & num
        RetVal = num
    End If

End Function


Public Function RetVal2(Optional ByVal num As Variant) As Long

    If IsMissing(num) Then

        MsgBox "No value passed"

    Else

        MsgBox "Value passed " & num
        RetVal2 = CLng(num)
    End If

End Function