Функция IsEmpty () для массива - PullRequest
2 голосов
/ 11 июня 2019

Я хотел бы проверить, если мой массив пуст или нет.

Я пытался использовать функцию IsEmpty(), но функция всегда возвращает False.И не вводите в условии if.

Мой код ниже:

Sub Freeze()

    Dim tab_freeze() as variant

    If IsEmpty(tab_freeze) Then
        ReDim tab_freeze(0)
    Else
        ReDim Preserve tab_freeze(UBound(tab_freeze) + 1)
        tab_freeze(UBound(tab_freeze)) = "As you want here"
     End If

End Sub

Я бы хотел, чтобы функция знала, пуст ли мой массив tab_freeze или нет.Или понять, почему IsEmpty(tab_freeze) возвращает False в первый раз.

Ответы [ 5 ]

3 голосов
/ 11 июня 2019

IsEmpty - это стандартная библиотечная функция, которая возвращает True, когда переменная типа Variant имеет подтип Empty (Variant/Empty), что имеет место для Range.Value, когда нетсодержимое в ячейке.

В вашем случае вы не имеете дело с Variant, вы имеете дело с динамическим массивом Variants. Динамический означает, что сначала вы должны выделить место для определенного количества элементов с помощью команды ReDim.Вы можете использовать IsEmpty(tab_freeze(1)), чтобы проверить, был ли инициализирован первый элемент - но это, вероятно, не то, что вам нужно.

К сожалению, в VBA нет встроенной функции, которая проверяла бы, выделен ли динамический массив.Есть несколько предложений, как проверить, см., Например, Как проверить пустой массив в макросе vba .Лично я использую следующую процедуру.Он проверяет, объявлена ​​ли переменная как массив и его границы.Если массив не выделен, LBound и UBound возвращают ошибку времени выполнения (и поэтому функция не получит True).Но он также обрабатывает возвращаемое значение split("") - что даст LBound 0 и UBound -1

Function IsArrayAllocated(arr As Variant) As Boolean
    On Error Resume Next
    IsArrayAllocated = isArray(arr) _
                   And Not IsError(LBound(arr, 1)) _
                   And LBound(arr, 1) <= UBound(arr, 1)
End Function
2 голосов
/ 11 июня 2019

В зависимости от того, что вы понимаете под «пустым массивом», могут быть разные ответы.Если вы рассматриваете Dim tab_freeze() as variant как пустой массив, поскольку в нем нет измерений, это может сработать:

Public Function IsArrayEmpty(myArray As Variant) As Boolean

    On Error GoTo IsArrayEmpty_Error

    Dim tempVar As Variant
    tempVar = myArray(0)

    IsArrayEmpty = False

    On Error GoTo 0
    Exit Function

IsArrayEmpty_Error:

    IsArrayEmpty = True

End Function

Будут проблемы, если кто-то использует Option Base 1, таким образом,первый элемент не 0, а 1.В общем, это считается, безразмерный массив, но вы можете называть его как хотите (если вы программируете один, что, вероятно, имеет место в VBA :)).

Если вы рассматриваете Dim testArray(10) as Variant как «пустой» массив, то это будет работать:

Public Function IsArrayWithValuesAtAll(myArray As Variant) As Boolean
    IsArrayWithValuesAtAll = IsError(Application.Match("*", (myArray), 0))
End Function
0 голосов
/ 11 июня 2019

Почему бы не использовать небольшую магию VB, о которой говорил Мерри в этом потоке vbforums , вместо использования Variant для замены массива типа Variant.

Одна из распространенных проблем при работе с массивами - это знать, когда массив был инициализирован, а когда нет. К счастью, есть простое решение с собственным кодом VB:

Not Not ArrayName

Для этого нужно взять 32-битное значение указателя в переменной массива, отразить биты, а затем отразить их снова. Теперь вы эффективно знаете указатель на безопасную структуру массива. В качестве побочного эффекта вы также знаете, можете ли вы получить доступ к массиву с помощью LBound и UBound.

Private Sub ArrayTest()
    Dim testArr() as Variant
    ' Prints False
    Debug.Print Not Not testArr

    ReDim testArr(0)
    ' This prints True
    Debug.Print Not Not testArr
End Sub

Мерри также говорил о проблемах, которые могут возникнуть, о которых я еще не сталкивался, и мы должны помнить, что этот пост посвящен Visual Basic, а не Visual Basic для приложений. (Имейте в виду, я перефразирую)
Очевидно, что в некоторых ситуациях при использовании этого метода возникает ошибка, которую можно обойти, выполнив простой Dim IDEbug() As Long: Debug.Assert Not IDEbug Or App.hInstance один раз в VB IDE.
Цитирую еще раз:

Что происходит здесь, так это то, что сначала мы делаем вызов, чтобы выдвинуть условие возможной ошибки. Затем мы вызываем App.hInstance: мы можем сделать вызов почти любому VB-методу, но поскольку hInstance возвращает Long, мы используем его. Это по какой-то причине делает все следующие вызовы Not ArrayName безупречно. После того, как строка однажды была выполнена в IDE, вы можете даже прокомментировать строку, и ее эффекты все еще остаются. Только закрыв VB и открыв его снова, вы сбросите условие, так что вам нужно будет повторить вызов.

Хочу подчеркнуть, что я не придумал это решение, но оно мне очень помогло. Я также хочу отметить, что я никогда не выполнял Debug.Assert Not someArray Or Application.Hinstance и еще не сталкивался с какими-либо проблемами. Это, очевидно, может быть связано с тем фактом, что VBA немного отличается от VB, но я точно не могу этого сказать.

0 голосов
/ 11 июня 2019

Спасибо за все ответы.

Но я нашел решение. Vba считают, что для Dim tab_freeze() As Variant tab_freeze не пусто, но UBound(tab_freeze) вызывает ошибку.

Итак, я только что удалил скобки в Dim:

Sub Freeze()

    Dim tab_freeze as variant

    If IsEmpty(tab_freeze) Then
        ReDim tab_freeze(0)
    Else
        ReDim Preserve tab_freeze(UBound(tab_freeze) + 1)
        tab_freeze(UBound(tab_freeze)) = "As you want here"
     End If

End Sub
0 голосов
/ 11 июня 2019

Для проверки, является ли массив пустым, я обычно Join() его без разделителя и проверяю его длину.

Sub Freeze()

    Dim tab_freeze() As Variant

    Dim jArr As String

    jArr = Join(tab_freeze, "")

    If Len(jArr) = 0 Then
        ReDim tab_freeze(0)
    Else
        ReDim Preserve tab_freeze(UBound(tab_freeze) + 1)
        tab_freeze(UBound(tab_freeze)) = "As you want here"
    End If

End Sub

Хотя, приятно отметить, что для массива Empty он будет возвращать то же самое, что и для безразмерного.

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