Почему Join () нуждается в двойном транспонировании 1-dim массива Long? - PullRequest
1 голос
/ 23 марта 2020

Почему Join () требуется двойное преобразование массива 1-dim Long?

Из-за MS Help для функции Join () требуется sourcearray как «одномерный массив, содержащий подстроки, которые нужно объединить» (кстати, сайт справки не имеет значения, является ли он вариантом или длинным) .

Примечание. В глоссарии VBE массив определяется как набор последовательно проиндексированных элементов с одинаковым типом данных intrinsi c.

Нет проблем с подключением массивов 1-dim Variant через Join(), и даже возможно объединить числа, так как они кажутся внутренне интерпретированными как "преобразовать нас в строки".

Проблема с Массив 1-dim, объявленный как Long

В некоторых случаях я хочу ограничить тип элементов Long и избегать решения Variant, упомянутого выше. - Объявление "плоского" массива - здесь: Numbers() - как Long , однако вызывает Ошибка 5"Недопустимый вызов процедуры или аргумент", если вы пытаетесь соединить результаты с помощью простого

'[2] Failing
Join(Numbers, "|") .

Я нашел интересную работу ► вокруг с помощью в основном избыточного двойного преобразования (c .f. [1]) , поскольку он «конвертирует» массив flat 1-dim, в конце концов, обратно в то же измерение.

'[1] work around
Join(Application.Transpose(Application.Transpose(Numbers)), "|")

Вопрос

Какая внутренняя разница в том, как VBA обрабатывает оба случая, и почему Join() требуется двойное преобразование 1-dim Long массив здесь?


Пример вызова для присоединения к "плоскому" массиву, объявленному как Long

Для того, чтобы показать строку кода обхода [1] наряду с строкой кода ошибки [2], я интегрировал основную обработку ошибок c, показывающую также определенные пользователем строки ошибок (ERL).

Непосредственное окно VB Editor показывает ошибку 5 в ERL 200:

 OK: [1] 3 elems: ~> 100|200|300
ERL: 200 Error No 5 Invalid procedure call or argument

Пример вызова

Sub JoinArr()
    Dim Numbers() As Long      ' provide for long array Numbers()
    FillNumbers 3, Numbers      ' call sub procedure to assign 3 numbers to array Nums
    ' Numbers is now an array of 3 numbers

    On Error GoTo oops
    '[1] work around - why does Join() need a double transposition in a 1-dim array?
100 Debug.Print " OK: [1] " & UBound(Numbers) & " elems:" & _
                " ~> " & Join(Application.Transpose(Application.Transpose(Numbers)), "|")

    '[2] join an already existing "flat" array raises Error 5 "Invalid procedure call or argument" 
200 Debug.Print " OK [2] " & UBound(Numbers) & " elems:" & _
                " ~> " & Join(Numbers, "|")

Exit Sub

oops:     Debug.Print "ERL: " & Erl & " Error No " & Err.Number & " " & Err.Description
End Sub

Sub FillNumbers, вызываемый вышеуказанной основной процедурой

Sub FillNumbers(ByVal n As Long, arr)  
    ReDim arr(1 To n)
    arr(1) = 100
    arr(2) = 200
    arr(3) = 300
End Sub

1 Ответ

1 голос
/ 24 марта 2020

При попытке Join() массив из Long s завершится неудачей:

Sub JoinTestFails()
    Dim Numbers(0 To 2) As Long, msg As String
    Numbers(0) = 0
    Numbers(1) = 1
    Numbers(2) = 2
    With Application.WorksheetFunction
        msg = Join(Numbers, "|")
    End With
    MsgBox msg
End Sub

enter image description here

Двойное использование TRANSPOSE() получает вокруг этого путем создания одномерного, основанного на одном массиве Variant s:

Sub JoinTest()
    Dim Numbers(0 To 2) As Long, msg As String

    Numbers(0) = 0
    Numbers(1) = 1
    Numbers(2) = 2

    With Application.WorksheetFunction
        Arr = .Transpose(.Transpose(Numbers))
        msg = LBound(Arr) & "**" & UBound(Arr) & vbCrLf
        msg = msg & Join(.Transpose(.Transpose(Numbers)), "|") & vbCrLf & TypeName(Arr)
    End With
    MsgBox msg
End Sub

enter image description here

Для меня это использование TRANSPOSE не является интуитивно понятным. Я бы предпочел сделать массив Variant с:

Public Function MkVar(arr() As Long) As Variant
'   make a variant array from a long array

    Dim temp() As Variant, i As Long
    ReDim temp(LBound(arr) To UBound(arr))
    For i = LBound(arr) To UBound(arr)
        temp(i) = arr(i)
    Next i
    MkVar = temp

End Function

и затем:

Sub JoinTest2()
    Dim Numbers(0 To 2) As Long, msg As String

    Numbers(0) = 0
    Numbers(1) = 1
    Numbers(2) = 2

    arr = MkVar(Numbers)

    msg = LBound(arr) & "**" & UBound(arr) & vbCrLf
    msg = msg & Join(MkVar(Numbers), "|") & vbCrLf & TypeName(arr)

    MsgBox msg
End Sub
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...