0

I need to do a is nothing check on a Variant array to exclude empty indexes from being used. I use is nothing to capture empty indexes which hold (empty) objects, it works fine but for indexes that hold regular data types (not objects), it throws an exception.

    Dim arrArray() as Variant
    '... fill array with values but leave some indexes out

    'Loop through the array
    For i = LBound(arrArray) To UBound(arrArray)

        'Check if the current array item is an empty object
        If arrArray(i) Is Nothing Then
            'don't debug.print
        
        'Debug if it's not an empty object 
            Else
            Debug.Print arrArray(i)
            End If

        Next

I could use on error resume next but since error handling is done dynamically it would change the error handling status so I would like to avoid that. If it can't be avoided please check my other question.

Note: Currently I just work with empty objects, at some point in the future I might get an actual object. So in the long run I will have to check if the index contains an existing object (otherwise - I presume - debug.print will throw an error).

Albin
  • 1,000
  • 1
  • 11
  • 33
  • put your check in an extra sub - if you set `on error resume next` it will only affect this routine, not the error handling of the calling routine – Ike Jun 06 '22 at 09:38
  • Is it the array in discussion an array of Objects? If not, `Is Nothing` is not so appropriate. You should simple check `If array(i) = "" then`... How do you fill the array? – FaneDuru Jun 06 '22 at 09:41
  • @FaneDuru the array can hold (empty) objects as well as regular data types (string, etc.), I edited the question, hope is clearer now. – Albin Jun 06 '22 at 12:05
  • Well, not so easy to check all sorts of elements which `Variant` array accepts... I tried some time ago creating a function to return the cleaned array for Strings, Variants from the sheet ranges, Integers, Ranges, Sheets... I will try searching it and posting. If you do not need it as it is, even if the return array is exactly what you need to iterate without restriction, you can be inspired by the way I used to check each array type... I am not sure it was completely optimized, I just needed to prove something and, if I remembered well, it worked as I imagined... – FaneDuru Jun 06 '22 at 13:10
  • You need to define what "empty" means for you. So far it would seem you only include "if IsObject and is Nothing". Is a zero "empty"? Is a zero length string "empty"? – GSerg Jun 06 '22 at 13:45

2 Answers2

1

Please, try the next function. It will return a cleaned array (without empty elements) for a wide range of elements type:

Function elimEmptyArrayElements(arrX As Variant) As Variant
 Dim i As Long, arrNoEmpty, k As Long
 ReDim arrNoEmpty(UBound(arrX)): k = 0
 For i = LBound(arrX) To UBound(arrX)
    If Not IsMissing(arrX(i)) Then
       If Not IsObject(arrX(i)) Then
            If TypeName(arrX(i)) = "String" Then
                If arrX(i) <> "" Then
                    arrNoEmpty(k) = arrX(i): k = k + 1
                End If
            Else
                If Not IsEmpty(arrX(i)) Then
                    arrNoEmpty(k) = arrX(i): k = k + 1
                End If
            End If
       Else
            Set arrNoEmpty(k) = arrX(i): k = k + 1
       End If
    End If
 Next i
 ReDim Preserve arrNoEmpty(k - 1)
 elimEmptyArrayElements = arrNoEmpty
End Function

Please, test it using the next Sub. It will stop on each pair of initial/cleaned array representation. When possible, both arrays are joined in Immediate Window.

If not possible, only the number of their elements (Ubound(arr)) is returned. You may iterate between each array elements and see that no empty one exists:

Sub testElimEmptyArrayElements()
   Dim arr
   arr = Split("1,7,9,,10,5,6,,2,8,3,4", ",")
   Debug.Print Join(arr, "|") 'just to visually see the initial array content
   
   arr = elimEmptyArrayElements(arr)
   Debug.Print Join(arr, "|"): Stop 'the cleaned array
   
   arr = Application.Transpose(Range("A2:A20").value) 'a 1D array extracted from a column range
   Debug.Print Join(arr, "|")

    arr = elimEmptyArrayElements(arr)
    Debug.Print Join(arr, "|"): Stop 'the cleaned array

    arr = Array(1, 2, 3, , 4, , 5): Debug.Print "Initial number of numeric elements: " & UBound(arr)
    arr = elimEmptyArrayElements(arr): Debug.Print "Cleaned array number of numeric elements: " & UBound(arr): Stop

    arr = Array(Range("A2"), Range("A3"), , Range("A6")): Debug.Print "Initial number of Range Object elements: " & UBound(arr)
    arr = elimEmptyArrayElements(arr): Debug.Print "Cleaned array number of Range elements: " & UBound(arr): Stop
    
    arr = Array(ActiveSheet, , ActiveSheet.Next): Debug.Print "Initial number of Sheet Object elements: " & UBound(arr)
    arr = elimEmptyArrayElements(arr): Debug.Print "Cleaned array number of Sheet Object elements: " & UBound(arr): Stop
    
    arr = Array("my string", 100, Range("A2"), , ActiveSheet, , ThisWorkbook, "test", 6): Debug.Print "Initial number of variate elements: " & UBound(arr)
    arr = elimEmptyArrayElements(arr): Debug.Print "Cleaned array number of variate types elements: " & UBound(arr)
      Debug.Print arr(2).value        'the cell value
      Debug.Print arr(3).name         'the activesheet name
      Debug.Print arr(4).Sheets.count 'activeworkbook number of sheets
End Sub
FaneDuru
  • 38,298
  • 4
  • 19
  • 27
  • Thanks for your input, you gave me an idea, so the solution was actually quite easy: before checking if the array item contains an empty object I just added a check if the array item contains an object. Sometimes... – Albin Jun 10 '22 at 05:14
-1

You can simply check and filter your array for empty slots with if YourArray(i)<>"" then syntax

Beside that, I see some wrong declaration issues in first line of your code: 1-You can't use Array as a name for your array 2-You should use parentheses after you array name (e.g. Dim myArray() as variant) 3-Variable type can not have parentheses (As far as I know)

I recommend to declare your array like following:

dim arr()

This way it automatically considered as an array of variants. So my suggested code would be like this:

Dim arr()
'... fill array with values but leave some indexes out
For i = LBound(arr) To UBound(arr)
    If arr(i)<>"" Then
        'do nothing
    Else
        'do something
    end if
Next i
Milad
  • 77
  • 11
  • Sorry, `Dim array...` was just pseudocode I didn't write correctly (the actual code works), I corrected my question. – Albin Jun 06 '22 at 11:09
  • 1
    Your solution works for regular data types, unfortunately for objects, it throws an exception. (I thought it was clear I'm using objects as well, sorry about that) – Albin Jun 06 '22 at 12:07