Как проверить, нераспределен ли массив вариантов? - PullRequest
11 голосов
/ 30 марта 2011
   Dim Result() As Variant

В моем окне просмотра это выглядит как

Expression | Value | Type
Result     |       | Variant/Variant()

Как проверить следующее:

   if Result is nothing then

или

   if Result is Not Set then

Этоэто в основном то, что я пытаюсь достичь, но первый не работает, а второй не существует.

Ответы [ 5 ]

17 голосов
/ 25 августа 2017

Чтобы избежать обработки ошибок, я использовал это, давно видел на форуме и с тех пор использовал успешно:

If (Not Not Result) <> 0 Then 'Means it is allocated

или альтернативно

If (Not Not Result) = 0 Then 'Means it is not allocated

Я использовал это главным образом для расширения размера массива из неустановленного массива таким образом

'Declare array
Dim arrIndex() As Variant        

'Extend array
If (Not Not Result) = 0 Then
    ReDim Preserve Result(0 To 0)
Else
    ReDim Preserve Result(0 To UBound(Result) + 1)
End If
11 голосов
/ 30 марта 2011

В ближайшем окне вы можете использовать следующее:

?Result Is Nothing
?IsNull( Result )
?IsEmpty( Result )
?IsMissing( Result )

Первое просто для полноты. Поскольку Result не является объектом, Result Is Nothing выдаст ошибку. Empty для вариантов, которые не были инициализированы , включая массивы, которые не были измерены. .

(Обновление) При выполнении некоторой дополнительной проверки я обнаружил, что IsEmpty никогда не вернет true в объявленном массиве (независимо от того, был ли Redim или нет) только с одним исключением. Единственное исключение, которое я обнаружил, - это когда массив объявляется на уровне модуля, а не как Public, и только тогда, когда вы проверяете его в ближайшем окне.

Missing если для необязательных значений передаются функции или подпрограмме. Хотя вы не можете объявить Optional Foo() As Variant, у вас может быть что-то вроде ParamArray Foo() As Variant, и в этом случае, если ничего не передано, IsMissing вернет true.

Таким образом, единственный способ определить, инициализирован ли массив, - написать процедуру, которая проверила бы:

Public Function IsDimensioned(vValue As Variant) As Boolean
    On Error Resume Next
    If Not IsArray(vValue) Then Exit Function
    Dim i As Integer
    i = UBound(Bar)
    IsDimensioned = Err.Number = 0
End Function

Кстати, следует заметить, что эта подпрограмма (или библиотека, опубликованная Жаном-Франсуа Корбеттом) вернет false, если массив будет измерен, а затем удален.

8 голосов
/ 30 марта 2011

Чип Пирсон создал полезный модуль с именем modArraySupport , который содержит набор функций для проверки подобных вещей.В вашем случае вы хотели бы использовать IsArrayAllocated.

Public Function IsArrayAllocated(Arr As Variant) As Boolean

Эта функция возвращает значение ИСТИНА или ЛОЖЬ, указывающее, выделен ли указанный массив (не пустой).Возвращает TRUE массива - статический массив или динамический объект, который был выделен с помощью оператора Redim.Возвращает FALSE, если массив является динамическим массивом, размер которого еще не был измерен с помощью ReDim или который был освобожден с помощью оператора Erase.Эта функция в основном противоположна ArrayIsEmpty.Например,

Dim Result() As Variant
Dim R As Boolean
R = IsArrayAllocated(Result)  ' returns false
ReDim V(1 To 10)
R = IsArrayAllocated(Result)  ' returns true

Используемая методика в основном заключается в проверке границ массива (как предложено @Tim Williams) НО с дополнительной ошибкой.

Чтобы проверить в вашем ближайшем окне:

?IsArrayAllocated(Result)

Тестирование в окне Watch: могут быть способы сделать это;например, добавьте часы на R и в разделе «Тип часов» выберите «Перерыв при изменении значения».

0 голосов
/ 06 апреля 2018

Я рекомендую немного другой подход, потому что я думаю, что использование языковых артефактов, таких как (Not Array) = -1, для проверки инициализации трудно читать и вызывает головные боли при обслуживании.

Если вам нужно проверить выделение массива, скорее всегоэто потому, что вы пытаетесь создать свой собственный «векторный» тип: массив, который увеличивается во время выполнения для размещения данных по мере их добавления.VBA упрощает реализацию векторного типа, если вы используете систему типов.

Type Vector
    VectorData() As Variant
    VectorCount As Long
End Type

Dim MyData As Vector

Sub AddData(NewData As Variant)
    With MyData
        ' If .VectorData hasn't been allocated yet, allocate it with an
        ' initial size of 16 elements.
        If .VectorCount = 0 Then ReDim .VectorData(1 To 16)

        .VectorCount = .VectorCount + 1

        ' If there is not enough storage for the new element, double the
        ' storage of the vector.
        If .VectorCount > UBound(.VectorData) Then
            ReDim Preserve .VectorData(1 To UBound(.VectorData) * 2)
        End If

        .VectorData(.VectorCount) = NewData
    End With
End Sub

' Example of looping through the vector:
For I = 1 To MyData.VectorCount
    ' Process MyData.VectorData(I)
Next

Обратите внимание, что в этом коде нет необходимости проверять распределение массивов, потому что мы можем просто проверить VectorCount переменная.Если он равен 0, мы знаем, что к вектору еще ничего не добавлено, и, следовательно, массив нераспределен.

Мало того, что этот код прост и понятен, векторы также имеют все преимущества производительности массива, иАмортизированная стоимость для добавления элементов на самом деле O (1), что очень эффективно.Единственным компромиссом является то, что из-за того, что память удваивается каждый раз, когда вектору не хватает места, в худшем случае 50% памяти вектора теряется.

0 голосов
/ 30 марта 2011

Проверьте LBound массива. Если вы получили сообщение об ошибке, оно не было инициализировано.

...