Вопрос: Параметр макроса Excel передается либо с ссылкой, либо с константой


В Excel я написал функцию vba Separate как это:

Function Separate(sp As String, ParamArray ArgList() As Variant)
    Dim paramLoop As Long
    Dim curRng As Range
    Separate = ArgList(0).Cells(1, 1).Value
    Dim flag As Boolean
    flag = False
    For paramLoop = 0 To UBound(ArgList)
        For Each curRng In ArgList(paramLoop)
            If flag Then
                Separate = Separate & sp & curRng.Value
            End If
            flag = True
        Next curRng
    Next paramLoop
End Function

Эта функция предназначена для объединения произвольного количества содержимого, разделенного строкой, заданной в качестве первого аргумента.

Например, =Separate(", ",A1:B2,A2) возвращается Alan, Bill, Carl, Dale, Bill успешно. (Предположим, что эти имена были сохранены в ячейках A1, A2, B1 а также B2.)

Это становится проблемой, если константа, а не ссылка передается во второй (и третий и т. Д.) Аргумент, такой как =Separate(", ","Alan",A2:B2), Это связано с тем, что мой код предполагает, что ArgList() As Variant находятся Range объект.

Как vba может определить, прошел ли каждый аргумент с помощью ссылки или константы? Или как изменить код, чтобы он выполнял одни и те же вещи независимо от того, передан ли аргумент с помощью ссылки или константы?


2
2017-10-03 10:45


Источник




Ответы:


Существует функция VBA, которая будет определять тип переменной: VarType(),

VarType строки является vbString (8); VarType диапазона vbArray+vbVariant (8204). Вам нужно протестировать каждый элемент вашего переданного массива и обработать его соответствующим образом. Один из способов сделать это, с которым легко следовать, - это Select Case:

Function Separate(sp As String, ParamArray ArgList() As Variant)
    Dim paramLoop As Long
    Dim curRng As Range
    Select Case VarType(ArgList(0))
        Case vbArray + vbVariant
            Separate = ArgList(0).Cells(1, 1).Value
        Case vbString
            Separate = ArgList(0)
    End Select
    Dim flag As Boolean
    flag = True
    For paramLoop = 1 To UBound(ArgList)
        Select Case VarType(ArgList(paramLoop))
            Case vbArray + vbVariant
                For Each curRng In ArgList(paramLoop)
                    If flag Then
                        Separate = Separate & sp & curRng.Value
                   End If
                    flag = True
                Next curRng
            Case vbString
                Separate = Separate & sp & ArgList(paramLoop)
        End Select
    Next paramLoop
End Function

И, конечно же, Select могут быть расширены для каждого из vbInteger, vbLong, vbSingle, vbDouble, vbCurrency, vbDate, vbBoolean, vbVariant, vbDecimal, vbByte и даже vbError если у вас есть пустой параметр.


4
2017-10-03 12:00



Спасибо. Интересно, что такое 8204. Почему диапазон составляет 8204? - HYC
8204 - это массив вариантов. (8192 - это массив, а 12 - вариант). - Andrew Leach


Если вы объявите аргумент как Вариант в заголовке функции вы всегда можете определить, что вызывающий ДЕЙСТВИТЕЛЬНО передает вам следующее:

Sub MAIN()
   x = WhatIsIt(Range("A1"))
   y = WhatIsIt("what ever")
End Sub

Public Function WhatIsIt(v As Variant) As String
   WhatIsIt = ""
   MsgBox TypeName(v)
End Function

2
2017-10-03 11:59