【问题标题】:Passing an empty/optional argument to a VBA function将空/可选参数传递给 VBA 函数
【发布时间】:2018-02-13 14:11:16
【问题描述】:

我的印象是,如果一个函数定义了一些可选参数,那么你可以传递Nothing,它会被视为“根本不传递任何东西” .

但是,我无法做到这一点。这是一个代码 sn-p,如果所有 "fds..." 变量都不为空,但如果有任何参数为空,则抛出 "Invalid procedure call or argument" Nothing:

Dim fdsSortOrders(2) As Variant
Dim fdsKey1 As Variant
Dim fdsKey2 As Variant
Dim fdsKey3 As Variant

' ...skipped...

Call loFinalReport.DataBodyRange.Sort( _
    Header:=xlYes, _
    Key1:=fdsKey1, Order1:=fdsSortOrders(0), _
    Key2:=fdsKey2, Order2:=fdsSortOrders(1), _
    Key3:=fdsKey3, Order3:=fdsSortOrders(2) _
)

有没有办法传递一个 可选 参数或者我应该制作丑陋的复制粘贴代码(“@9​​87654324@)?

更新

这将起作用,因为 Key2/Key3 和 Order2/Order3 是可选的,但我不想编写三个版本的过程调用:

Call loFinalReport.DataBodyRange.Sort( _
    Header:=xlYes, _
    Key1:=fdsKey1, Order1:=fdsSortOrders(0) _
)

【问题讨论】:

  • 澄清:fdsKey1fdsSortOrders(0) 总是什么都不是吗?希望我回家后你能尽快看到这个:D
  • 有两个选项:要么它们包含有用且好的东西(通过健全性检查确认),要么它们什么都没有。我可以让它们不是什么都不是,而是其他任何东西(即 vbNullString)。

标签: vba excel


【解决方案1】:

这是一个带有可选参数的函数头示例:

Function FunctionName(Optional ByVal X As String = "", Optional ByVal Y As Boolean = True)

您需要省略参数传递,以便使用默认值。
在您的示例中,您的默认值将是 fdsKey1fdsSortOrders(0),因此它将按相同的键和相同的顺序对其进行排序。


除了这个,想不出别的了:

Call loFinalReport.DataBodyRange.Sort( _
    Header:=xlYes, _
    Key1:=fdsKey1, Order1:=fdsSortOrders(0), _
    Key2:=IIf(IsNothing(fdsKey2), fdsKey1, fdsKey2), _
    Order2:=IIf(IsNothing(fdsSortOrders(1)), fdsSortOrders(0), fdsSortOrders(1)), _
    Key3:=IIf(IsNothing(fdsKey3), fdsKey1, fdsKey3), _
    Order3:=IIf(IsNothing(fdsSortOrders(2)), fdsSortOrders(0), fdsSortOrders(2)) _
)

请注意,至少 fdsKey1fdsSortOrders(0) 应该......好吧,一些东西。
或者,您可以为所有 3 个键和订单设置此条件并设置默认值。
通过具有相同值的多个键对范围进行排序不应以任何方式影响排序。

【讨论】:

  • 感谢 AntiDrondert;然而,看来你误会了我。我的问题是:如何传递“空”参数而不省略它?即,在您的示例中,我如何编写一个调用,例如 Call FunctionName( myX, myY),如果 myX 是 Nothing(或其他),那么 FunctionName 将采用默认值?..
  • @Alexander 好的,我想我明白了。然后,您将需要在您的子/功能中进行条目检查。否则,您可以在调用之前检查这些变量。这个问题非常相关,你应该看看How do I test if optional arguments are supplied or not?
  • 好吧@AntiDrondert 问题是- .Sort 是Microsoft.Office.Interop.Excel 中的内置方法:)
  • 啊啊啊IIF!我已经忘记了!就在昨天,我正坐着思考“把我的三元 ? : 来自 C++ 的运算符还给我!”我认为您的解决方法非常优雅。 本身仍然不是一个解决方案,但似乎根本没有... Micro$oft...
【解决方案2】:

使用可选变体运行快速测试,使用IsMissing 函数显示NothingMissing 不同:

Option Explicit

Private Function IsItMissing(Optional vTMP As Variant) As Variant
    IsItMissing = CVErr(xlErrNA)
    On Error GoTo FuncErr
    IsItMissing = IsMissing(vTMP)
FuncErr:
End Function

Public Sub TestValues()
    MsgBox IsItMissing("Nope") 'False
    MsgBox IsItMissing 'True
    MsgBox IsItMissing(Nothing) 'False
End Sub

问题在于Nothing 是一个特殊对象,而不是实际上是“无”。这就像 Excel 中空白单元格和没有数据的单元格之间的区别(例如 =""

我怀疑您可能希望将 If 语句与 Is Nothing 链接起来以创建您的排序:

If fdsKey2 Is Nothing Then
    loFinalReport.DataBodyRange.Sort Header:=xlYes, _
        Key1:=fdsKey1, Order1:=fdsSortOrders(0)
ElseIf fsdKey3 Is Nothing Then
    loFinalReport.DataBodyRange.Sort Header:=xlYes, _
        Key1:=fdsKey1, Order1:=fdsSortOrders(0), _
        Key2:=fdsKey2, Order2:=fdsSortOrders(1)
Else
    loFinalReport.DataBodyRange.Sort Header:=xlYes, _
        Key1:=fdsKey1, Order1:=fdsSortOrders(0), _
        Key2:=fdsKey2, Order2:=fdsSortOrders(1), _
        Key3:=fdsKey3, Order3:=fdsSortOrders(2)
End If

{编辑:在 cmets 中讨论之后} 这是一个函数,它使用 2 个数组来计算出哪个键(如果有)不是 Nothing: p>

Private Function SortNothing(Target As Range, Optional Key1 As Variant, Optional Order1 As XlSortOrder = xlAscending, Optional Key2 As Variant, Optional Order2 As XlSortOrder = xlAscending, Optional Key3 As Variant, Optional Order3 As XlSortOrder = xlAscending) As Boolean
    Dim iArr As Integer, aKeys(1 To 3) As Variant, aOrders(1 To 3) As XlSortOrder
    iArr = 0 'This pointer will track how many non-Nothing Keys we have
    SortNothing = False
    On Error GoTo FuncErr
    If Not IsMissing(Key1) Then
        If Not (Key1 Is Nothing) Then
            iArr = iArr + 1
            aKeys(iArr) = Key1
            aOrders(iArr) = Order1
        End If
    End If
    If Not IsMissing(Key2) Then
        If Not (Key2 Is Nothing) Then
            iArr = iArr + 1
            aKeys(iArr) = Key2
            aOrders(iArr) = Order2
        End If
    End If
    If Not IsMissing(Key3) Then
        If Not (Key3 Is Nothing) Then
            iArr = iArr + 1
            aKeys(iArr) = Key3
            aOrders(iArr) = Order3
        End If
    End If

    Select Case iArr
        Case 3:
            Target.Sort Key1:=aKeys(1), Order1:=aOrders(1), Key2:=aKeys(2), Order2:=aOrders(2), Key3:=aKeys(3), Order3:=aOrders(3), Header:=xlYes
        Case 2:
            Target.Sort Key1:=aKeys(1), Order1:=aOrders(1), Key2:=aKeys(2), Order2:=aOrders(2), Header:=xlYes
        Case 1:
            Target.Sort Key1:=aKeys(1), Order1:=aOrders(1), Header:=xlYes
    End Select
    SortNothing = True
FuncErr:
End Function

【讨论】:

  • OP 明确表示他不想要to write three versions of procedure call
  • 啊 - 在我已经开始写作之后,OP 在编辑中添加了这一点。鉴于Nothing 是一个对象,而不是Missing,我认为没有其他方法可以做到这一点。您可以编写一个函数来接受范围和参数,并将 3 版本链放在那里,这样它看起来就像您的主代码中的 1 行 - 但只有当您有多个实例时才值得这样做这种情况
  • 是的@Chronocidal,就像 AntiDrondert 说的:) 这种情况很简单,但是如果函数可以采用这三个参数中的任何一个(即 Key3 和 Key1 或 Key2 和 Key3)呢? d 是 IFs IFs IFs 的可怕排列 :)
  • @Alexander 使用数组和指针?我在响应中添加了一个函数,它将非Nothing 键及其顺序填充到一个数组中,并使用指针跟踪有多少
  • @Alexander 但是,现在你可以说SortNothing loFinalReport.DataBodyRange, fsdKey1, fdsSortOrders(0), fsdKey2, fdsSortOrders(1), fsdKey3, fdsSortOrders(2),它会运行排序并自动排除fdsKey#Nothing 的任何键 - 我虽然那是你想要的?
【解决方案3】:
Private Sub PassingVariables(ByRef strNotOptionalText As String, _
                        Optional ByRef strOptionalText As String = "Random or Null", _
                        Optional ByRef wbMainOptional As Workbook = Nothing)

' Statements
End Sub

Public Sub CallingSub()

' Here I'm passing just the required parameter (strNotOptionalText).
' strOptionalText will be "Random or Null" as default and wbMainOptional will be Nothing as default.
Call PassingVariables("Name")

' Here I'm actually passing personalized variabled and not using the default Optionals.
Call PassingVariables("Name", "My Personlalized Text", ThisWorkbook)
End Sub

这里有一个示例,说明如何使用代码可选参数。永远记住将可选参数放在必需参数之后。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-28
    • 2018-11-03
    • 2019-03-17
    • 1970-01-01
    相关资源
    最近更新 更多