How do I determine if an array is initialized in VB6?
Asked Answered
W

24

63

Passing an undimensioned array to the VB6's Ubound function will cause an error, so I want to check if it has been dimensioned yet before attempting to check its upper bound. How do I do this?

Waltner answered 8/10, 2008 at 15:22 Comment(0)
W
15

Here's what I went with. This is similar to GSerg's answer, but uses the better documented CopyMemory API function and is entirely self-contained (you can just pass the array rather than ArrPtr(array) to this function). It does use the VarPtr function, which Microsoft warns against, but this is an XP-only app, and it works, so I'm not concerned.

Yes, I know this function will accept anything you throw at it, but I'll leave the error checking as an exercise for the reader.

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
  (pDst As Any, pSrc As Any, ByVal ByteLen As Long)

Public Function ArrayIsInitialized(arr) As Boolean

  Dim memVal As Long

  CopyMemory memVal, ByVal VarPtr(arr) + 8, ByVal 4 'get pointer to array
  CopyMemory memVal, ByVal memVal, ByVal 4  'see if it points to an address...  
  ArrayIsInitialized = (memVal <> 0)        '...if it does, array is intialized

End Function
Waltner answered 14/1, 2009 at 21:42 Comment(5)
RtlMoveMemory is slower than the native GetMem4. GetMem4 is over twice as fast: vbforums.com/archive/index.php/t-360672.htmlHammon
+1, unlike the top-voted answer, this one does appear to work with string arrays.Hacksaw
From a discussion linked to by another comment, Karl Peterson provided a similar function that includes some additional validation.Kelt
Just noted this does not work for arrays of type Object (or of type SomeClass, where SomeClass is a class as opposed to a UDT). Always returns True. Whereas ArrPtr works in this case.Pundit
Can be fixed by adding the last line to the function: If ArrayIsInitialized Then ArrayIsInitialized = Ubound(arr) >= Lbound(arr).Pundit
P
25

Note: the code has been updated, the original version can be found in the revision history (not that it is useful to find it). The updated code does not depend on the undocumented GetMem4 function and correctly handles arrays of all types.

Note for VBA users: This code is for VB6 which never got an x64 update. If you intend to use this code for VBA, see https://mcmap.net/q/245387/-vba-array-slices-not-in-the-pythonic-sense for the VBA version. You will only need to take the CopyMemory declaration and the pArrPtr function, leaving the rest.

I use this:

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(ByRef Destination As Any, ByRef Source As Any, ByVal length As Long)

Private Const VT_BYREF As Long = &H4000&

' When declared in this way, the passed array is wrapped in a Variant/ByRef. It is not copied.
' Returns *SAFEARRAY, not **SAFEARRAY
Public Function pArrPtr(ByRef arr As Variant) As Long
  'VarType lies to you, hiding important differences. Manual VarType here.
  Dim vt As Integer
  CopyMemory ByVal VarPtr(vt), ByVal VarPtr(arr), Len(vt)

  If (vt And vbArray) <> vbArray Then
    Err.Raise 5, , "Variant must contain an array"
  End If

  'see https://msdn.microsoft.com/en-us/library/windows/desktop/ms221627%28v=vs.85%29.aspx
  If (vt And VT_BYREF) = VT_BYREF Then
    'By-ref variant array. Contains **pparray at offset 8
    CopyMemory ByVal VarPtr(pArrPtr), ByVal VarPtr(arr) + 8, Len(pArrPtr)  'pArrPtr = arr->pparray;
    CopyMemory ByVal VarPtr(pArrPtr), ByVal pArrPtr, Len(pArrPtr)          'pArrPtr = *pArrPtr;
  Else
    'Non-by-ref variant array. Contains *parray at offset 8
    CopyMemory ByVal VarPtr(pArrPtr), ByVal VarPtr(arr) + 8, Len(pArrPtr)  'pArrPtr = arr->parray;
  End If
End Function

Public Function ArrayExists(ByRef arr As Variant) As Boolean
  ArrayExists = pArrPtr(arr) <> 0
End Function

Usage:

? ArrayExists(someArray)

Your code seems to do the same (testing for SAFEARRAY** being NULL), but in a way which I would consider a compiler bug :)

Pundit answered 8/10, 2008 at 16:31 Comment(1)
Sorry this answer wasn't chosen as it is the most elegant and flexible solution. I'm going to tuck this away for future use. ThanksScrivings
W
23

I just thought of this one. Simple enough, no API calls needed. Any problems with it?

Public Function IsArrayInitialized(arr) As Boolean

  Dim rv As Long

  On Error Resume Next

  rv = UBound(arr)
  IsArrayInitialized = (Err.Number = 0)

End Function

Edit: I did discover a flaw with this related to the behavior of the Split function (actually I'd call it a flaw in the Split function). Take this example:

Dim arr() As String

arr = Split(vbNullString, ",")
Debug.Print UBound(arr)

What is the value of Ubound(arr) at this point? It's -1! So, passing this array to this IsArrayInitialized function would return true, but attempting to access arr(0) would cause a subscript out of range error.

Waltner answered 8/10, 2008 at 21:2 Comment(5)
Beat me to it ;-) That's usually how I do it. One small critique: the above code ignores any error that might occur, which is not ideal. For example, if someone passes in a plain Integer by mistake, you would want the function to raise a "Type Mismatch" error back to the caller, not ignore it.Kasher
To expand on my last comment, error 9 ("Subscript out of range") is the specific error that will occur when you pass an uninitialized array to the LBound and UBound functions, so you can assume the array is empty if Err.Number=9. If a different error occurred, then rethrow.Kasher
>> Any problems with it? In compiled .exe, my check takes 0.06 seconds to execute a million times, whlie this one takes 8 seconds (yes, much less in the IDE, but that's not relevant). Exceptions are expensive, you know...Pundit
Exceptions are expensive, but I don't think I'll be needing to check the existence of an array a million times any time soon, and if I do, 8 seconds will be just fine. This code is clean and concise, and doesn't require an understanding of Win32 API obscura... Your answer has a lot of value too, but this one is better. +1Yovonnda
Yes, it worked for me too. But I got an error "Only public user defined types defined in public object modules can be used as parameters or return types for public procedures of class modules or as fields of public user defined types". I had to specify the exact type of array in function call. That was array of structsSpancake
W
15

Here's what I went with. This is similar to GSerg's answer, but uses the better documented CopyMemory API function and is entirely self-contained (you can just pass the array rather than ArrPtr(array) to this function). It does use the VarPtr function, which Microsoft warns against, but this is an XP-only app, and it works, so I'm not concerned.

Yes, I know this function will accept anything you throw at it, but I'll leave the error checking as an exercise for the reader.

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
  (pDst As Any, pSrc As Any, ByVal ByteLen As Long)

Public Function ArrayIsInitialized(arr) As Boolean

  Dim memVal As Long

  CopyMemory memVal, ByVal VarPtr(arr) + 8, ByVal 4 'get pointer to array
  CopyMemory memVal, ByVal memVal, ByVal 4  'see if it points to an address...  
  ArrayIsInitialized = (memVal <> 0)        '...if it does, array is intialized

End Function
Waltner answered 14/1, 2009 at 21:42 Comment(5)
RtlMoveMemory is slower than the native GetMem4. GetMem4 is over twice as fast: vbforums.com/archive/index.php/t-360672.htmlHammon
+1, unlike the top-voted answer, this one does appear to work with string arrays.Hacksaw
From a discussion linked to by another comment, Karl Peterson provided a similar function that includes some additional validation.Kelt
Just noted this does not work for arrays of type Object (or of type SomeClass, where SomeClass is a class as opposed to a UDT). Always returns True. Whereas ArrPtr works in this case.Pundit
Can be fixed by adding the last line to the function: If ArrayIsInitialized Then ArrayIsInitialized = Ubound(arr) >= Lbound(arr).Pundit
W
14

I found this:

Dim someArray() As Integer

If ((Not someArray) = -1) Then
  Debug.Print "this array is NOT initialized"
End If

Edit: RS Conley pointed out in his answer that (Not someArray) will sometimes return 0, so you have to use ((Not someArray) = -1).

Waltner answered 8/10, 2008 at 15:22 Comment(5)
Usage of the Not hack is not advised because isn't actually a language feature. Instead, it results from a bug in the compiler and the behaviour may have unexpected consequences. Use GSerg's way instead.Firestone
@Konrad, that's interesting. Do you know of a source that describes more about the bug?Mainsheet
@jtolle: unfortunately, no. As far as I know it was never acknowledged in the MSDN but it’s been known to the VB6 community for years.Firestone
Here is a good German description of the error, maybe Google Translate will help non-Germans who are interested: classic.vb-faq.de/…Durrell
using this way may cause some dangerous problem in program, like bad errors in using floating points.Frida
A
9

Both methods by GSerg and Raven are undocumented hacks but since Visual BASIC 6 is no longer being developed then it is not a issue. However Raven's example doesn't work on all machines. You have to test like this.

If (Not someArray) = -1 Then

On some machines it will return a zero on others some large negative number.

Auxochrome answered 8/10, 2008 at 19:16 Comment(4)
You know, the example originally had that syntax but I edited because I thought it was pointless. Now I know better.Waltner
This is what I use. Only it is really confusing to read, so I made a function.Urbanite
Karl Peterson says this can cause problems. That's a good enough reason to avoid it IMHO groups.google.co.uk/group/…Phonoscope
E.g. try running this code from the IDE. I get an error 16 expression too complex on the last MsgBox. Private Sub Form_Load() Dim X() As Long If Not Not X Then MsgBox "Yay" Debug.Assert App.hInstance MsgBox CLng(0.1@) If Not Not X Then MsgBox "Yay" MsgBox CLng(0.1@) End SubPhonoscope
E
5

In VB6 there is a function called "IsArray", but it does not check if the array has been initialized. You will receive Error 9 - Subscript out of range if you attempt to use UBound on an uninitialized array. My method is very similar to S J's, except it works with all variable types and has error handling. If a non-array variable is checked, you will receive Error 13 - Type Mismatch.

Private Function IsArray(vTemp As Variant) As Boolean
    On Error GoTo ProcError
    Dim lTmp As Long

    lTmp = UBound(vTemp) ' Error would occur here

    IsArray = True: Exit Function
ProcError:
    'If error is something other than "Subscript
    'out of range", then display the error
    If Not Err.Number = 9 Then Err.Raise (Err.Number)
End Function
Encyst answered 24/9, 2012 at 19:31 Comment(0)
O
4

Since wanted comment on here will post answer.

Correct answer seems is from @raven:

Dim someArray() As Integer

If ((Not someArray) = -1) Then
  Debug.Print "this array is NOT initialized"
End If

When documentation or Google does not immediately return an explanation people tend to call it a hack. Although what seems to be the explanation is that Not is not only a Logical, it is also a Bitwise operator, so it handles the bit representation of structures, rather than Booleans only.

For example of another bitwise operation is here:

Dim x As Integer
x = 3 And 5 'x=1

So the above And is also being treated as a bitwise operator.

Furthermore, and worth to check, even if not the directly related with this,

The Not operator can be overloaded, which means that a class or structure can redefine its behavior when its operand has the type of that class or structure. Overloading

Accordingly, Not is interpreting the array as its bitwise representation and it distinguishes output when array is empty or not like differently in the form of signed number. So it can be considered this is not a hack, is just an undocumentation of the array bitwise representation, which Not here is exposing and taking advantage of.

Not takes a single operand and inverts all the bits, including the sign bit, and assigns that value to the result. This means that for signed positive numbers, Not always returns a negative value, and for negative numbers, Not always returns a positive or zero value. Logical Bitwise

Having decided to post since this offered a new approach which is welcome to be expanded, completed or adjusted by anyone who has access to how arrays are being represented in their structure. So if anyone offers proof it is actually not intended for arrays to be treated by Not bitwise we should accept it as not a hack and actually as best clean answer, if they do or do not offer any support for this theory, if it is constructive comment on this is welcome of course.

Oslo answered 20/10, 2019 at 12:24 Comment(0)
N
3

This is modification of raven's answer. Without using API's.

Public Function IsArrayInitalized(ByRef arr() As String) As Boolean
'Return True if array is initalized
On Error GoTo errHandler 'Raise error if directory doesnot exist

  Dim temp As Long
  temp = UBound(arr)

  'Reach this point only if arr is initalized i.e. no error occured
  If temp > -1 Then IsArrayInitalized = True 'UBound is greater then -1

Exit Function
errHandler:
  'if an error occurs, this function returns False. i.e. array not initialized
End Function

This one should also be working in case of split function. Limitation is you would need to define type of array (string in this example).

Notability answered 14/6, 2012 at 15:53 Comment(0)
S
2

When you initialite the array put an integer or boolean with a flag = 1. and query this flag when you need.

Severen answered 21/1, 2012 at 22:54 Comment(0)
E
2
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function ArrPtr Lib "msvbvm60" Alias "VarPtr" (arr() As Any) As Long

Private Type SafeArray
    cDims As Integer
    fFeatures As Integer
    cbElements As Long
    cLocks As Long
    pvData As Long
End Type

Private Function ArrayInitialized(ByVal arrayPointer As Long) As Boolean
    Dim pSafeArray As Long

    CopyMemory pSafeArray, ByVal arrayPointer, 4

    Dim tArrayDescriptor As SafeArray

    If pSafeArray Then
        CopyMemory tArrayDescriptor, ByVal pSafeArray, LenB(tArrayDescriptor)

        If tArrayDescriptor.cDims > 0 Then ArrayInitialized = True
    End If

End Function

Usage:

Private Type tUDT
    t As Long
End Type

Private Sub Form_Load()
    Dim longArrayNotDimmed() As Long
    Dim longArrayDimmed(1) As Long

    Dim stringArrayNotDimmed() As String
    Dim stringArrayDimmed(1) As String

    Dim udtArrayNotDimmed() As tUDT
    Dim udtArrayDimmed(1) As tUDT

    Dim objArrayNotDimmed() As Collection
    Dim objArrayDimmed(1) As Collection


    Debug.Print "longArrayNotDimmed " & ArrayInitialized(ArrPtr(longArrayNotDimmed))
    Debug.Print "longArrayDimmed " & ArrayInitialized(ArrPtr(longArrayDimmed))

    Debug.Print "stringArrayNotDimmed " & ArrayInitialized(ArrPtr(stringArrayNotDimmed))
    Debug.Print "stringArrayDimmed " & ArrayInitialized(ArrPtr(stringArrayDimmed))

    Debug.Print "udtArrayNotDimmed " & ArrayInitialized(ArrPtr(udtArrayNotDimmed))
    Debug.Print "udtArrayDimmed " & ArrayInitialized(ArrPtr(udtArrayDimmed))

    Debug.Print "objArrayNotDimmed " & ArrayInitialized(ArrPtr(objArrayNotDimmed))
    Debug.Print "objArrayDimmed " & ArrayInitialized(ArrPtr(objArrayDimmed))

    Unload Me
End Sub
Eloquent answered 8/4, 2015 at 17:54 Comment(3)
Please correct your code format according S.O. FormattingCulberson
Looks like "Celeo" corrected it for me. Thanks, I'm new to posting here.Eloquent
@Eloquent for code blocks like this, place 4 spaces in front of each line of code, in addition to the code's intrinsic spacing / indentation. You can paste a block of code and with it selcted, use the "code sample" button in the editor or ctrl+k, which will add the spaces for you. And remember, always check the question preview before posting.Ceasefire
H
1

Based on all the information I read in this existing post this works the best for me when dealing with a typed array that starts as uninitialized.

It keeps the testing code consistent with the usage of UBOUND and It does not require the usage of error handling for testing.

It IS dependent on Zero Based Arrays (which is the case in most development).

Must not use "Erase" to clear the array. use alternative listed below.

Dim data() as string ' creates the untestable holder.
data = Split(vbNullString, ",") ' causes array to return ubound(data) = -1
If Ubound(data)=-1 then ' has no contents
    ' do something
End If
redim preserve data(Ubound(data)+1) ' works to increase array size regardless of it being empty or not.

data = Split(vbNullString, ",") ' MUST use this to clear the array again.
Hypocycloid answered 30/4, 2015 at 20:6 Comment(0)
B
1

The easiest way to handle this is to insure that the array is initialized up front, before you need to check for the Ubound. I needed an array that was declared in the (General) area of the form code. i.e.

Dim arySomeArray() As sometype

Then in the form load routine I redim the array:

Private Sub Form_Load()

ReDim arySomeArray(1) As sometype 'insure that the array is initialized

End Sub 

This will allow the array to be re-defined at any point later in the program. When you find out how big the array needs to be just redim it.

ReDim arySomeArray(i) As sometype 'i is the size needed to hold the new data
Bartram answered 22/9, 2017 at 16:20 Comment(0)
D
1

The title of the question asks how to determine if an array is initialized, but, after reading the question, it looks like the real problem is how to get the UBound of an array that is not initialized.

Here is my solution (to the the actual problem, not to the title):

Function UBound2(Arr) As Integer
  On Error Resume Next
  UBound2 = UBound(Arr)
  If Err.Number = 9 Then UBound2 = -1
  On Error GoTo 0
End Function

This function works in the following four scenarios, the first three that I have found when Arr is created by an external dll COM and the fourth when the Arr is not ReDim-ed (the subject of this question):

  • UBound(Arr) works, so calling UBound2(Arr) adds a little overhead, but doesn't hurt much
  • UBound(Arr) fails in in the function that defines Arr, but succeeds inside UBound2()
  • UBound(Arr) fails both in the function that defines Arr and in UBound2(), so the error handling does the job
  • After Dim Arr() As Whatever, before ReDim Arr(X)
Depressed answered 15/2, 2018 at 0:36 Comment(0)
H
1

For any variable declared as an array, you can easily check if the array is initialized by calling the SafeArrayGetDim API. If the array is initialized, then the return value will be non-zero, otherwise the function returns zero.

Note that you can't use this function with variants that contain arrays. Doing so will cause a Compile error (Type mismatch).

Public Declare Function SafeArrayGetDim Lib "oleaut32.dll" (psa() As Any) As Long

Public Sub Main()
    Dim MyArray() As String

    Debug.Print SafeArrayGetDim(MyArray)    ' zero

    ReDim MyArray(64)
    Debug.Print SafeArrayGetDim(MyArray)    ' non-zero

    Erase MyArray
    Debug.Print SafeArrayGetDim(MyArray)    ' zero

    ReDim MyArray(31, 15, 63)
    Debug.Print SafeArrayGetDim(MyArray)    ' non-zero

    Erase MyArray
    Debug.Print SafeArrayGetDim(MyArray)    ' zero

    ReDim MyArray(127)
    Debug.Print SafeArrayGetDim(MyArray)    ' non-zero

    Dim vArray As Variant
    vArray = MyArray
    ' If you uncomment the next line, the program won't compile or run.
    'Debug.Print SafeArrayGetDim(vArray)     ' <- Type mismatch
End Sub
Heikeheil answered 29/1, 2019 at 3:24 Comment(3)
I encountered the compile error Constants, fixed-length strings, arrays, user-defined types, and Declare statements not allowed as Public members of an object module. However, I changed the function declaration to Private and it worked.Counterclockwise
"Sub Main" should have given it away that the example code should be in a module, not a class. :) With the function declared as public in a module, you can call it from anywhere in the project.Heikeheil
SafeArrayGetDim will return the lower DWORD of the SAFEARRAY* pointer that's stored in MyArray variable. This lower DWORD will be 0 for NULL pointer (unallocated array) but might be 0 for a valid pointer like &H12340000 for instance which is non-NULL pointer to an allocated array and that's why this approach is not very reliable.Switchman
G
0

If the array is a string array, you can use the Join() method as a test:

Private Sub Test()

    Dim ArrayToTest() As String

    MsgBox StringArrayCheck(ArrayToTest)     ' returns "false"

    ReDim ArrayToTest(1 To 10)

    MsgBox StringArrayCheck(ArrayToTest)     ' returns "true"

    ReDim ArrayToTest(0 To 0)

    MsgBox StringArrayCheck(ArrayToTest)     ' returns "false"

End Sub


Function StringArrayCheck(o As Variant) As Boolean

    Dim x As String

    x = Join(o)

    StringArrayCheck = (Len(x) <> 0)

End Function
Gilli answered 8/10, 2008 at 16:5 Comment(1)
+1 for being by far the simplest method to detect an empty string array.Settler
P
0

My only problem with API calls is moving from 32-bit to 64-bit OS's.
This works with Objects, Strings, etc...

Public Function ArrayIsInitialized(ByRef arr As Variant) As Boolean
    On Error Resume Next
    ArrayIsInitialized = False
    If UBound(arr) >= 0 Then If Err.Number = 0 Then ArrayIsInitialized = True
End Function
Pigeonwing answered 12/8, 2012 at 4:14 Comment(1)
You should peruse the existing answers before posting one of your own. I proposed this solution four years ago.Waltner
G
0

You can solve the issue with Ubound() function, check if the array is empty by retrieving total elements count using JScript's VBArray() object (works with arrays of variant type, single or multidimensional):

Sub Test()

    Dim a() As Variant
    Dim b As Variant
    Dim c As Long

    ' Uninitialized array of variant
    ' MsgBox UBound(a) ' gives 'Subscript out of range' error
    MsgBox GetElementsCount(a) ' 0

    ' Variant containing an empty array
    b = Array()
    MsgBox GetElementsCount(b) ' 0

    ' Any other types, eg Long or not Variant type arrays
    MsgBox GetElementsCount(c) ' -1

End Sub

Function GetElementsCount(aSample) As Long

    Static oHtmlfile As Object ' instantiate once

    If oHtmlfile Is Nothing Then
        Set oHtmlfile = CreateObject("htmlfile")
        oHtmlfile.parentWindow.execScript ("function arrlength(arr) {try {return (new VBArray(arr)).toArray().length} catch(e) {return -1}}"), "jscript"
    End If
    GetElementsCount = oHtmlfile.parentWindow.arrlength(aSample)

End Function

For me it takes about 0.4 mksec for each element + 100 msec initialization, being compiled with VB 6.0.9782, so the array of 10M elements takes about 4.1 sec. The same functionality could be implemented via ScriptControl ActiveX.

Gwynethgwynne answered 13/12, 2015 at 1:36 Comment(0)
A
0
If ChkArray(MyArray)=True then
   ....
End If

Public Function ChkArray(ByRef b) As Boolean
    On Error goto 1
    If UBound(b) > 0 Then ChkArray = True
End Function
Antoinetteanton answered 12/7, 2016 at 15:55 Comment(0)
F
0

There are two slightly different scenarios to test:

  1. The array is initialised (effectively it is not a null pointer)
  2. The array is initialised and has at least one element

Case 2 is required for cases like Split(vbNullString, ",") which returns a String array with LBound=0 and UBound=-1. Here are the simplest example code snippets I can produce for each test:

Public Function IsInitialised(arr() As String) As Boolean
  On Error Resume Next
  IsInitialised = UBound(arr) <> 0.5
End Function

Public Function IsInitialisedAndHasElements(arr() As String) As Boolean
  On Error Resume Next
  IsInitialisedAndHasElements = UBound(arr) >= LBound(arr)
End Function
Floristic answered 14/9, 2016 at 10:8 Comment(0)
H
0

Either of these two ways is valid to detect an uninitialized array, but they must include the parentheses:

(Not myArray) = -1
(Not Not myArray) = 0
Hunchback answered 18/11, 2022 at 14:15 Comment(0)
H
0
' Function CountElements return counted elements of an array.
' Returns:
' [               -1]. If the argument is not an array.
' [                0]. If the argument is a not initialized array.
' [Count of elements]. If the argument is an initialized array.
Private Function CountElements(ByRef vArray As Variant) As Integer

    ' Check whether the argument is an array.
    If (VarType(vArray) And vbArray) <> vbArray Then
        
        ' Not an array.                 CountElements is set to -1.
        Let CountElements = -1
        
    Else
    
        On Error Resume Next
        
        ' Calculate number of elements in array.
        ' Scenarios:
        ' - Array is initialized.       CountElements is set to counted elements.
        ' - Array is NOT initialized.   CountElements is never set and keeps its
        '                               initial value of zero (since an error is
        '                               raised).
        Let CountElements = (UBound(vArray) - LBound(vArray)) + 1
    
    End If
    
End Function


' Test of function CountElements.

    Dim arrStr() As String
    Dim arrV As Variant
    
    Let iCount = CountElements(arrStr)                  ' arrStr is not initialized, returns 0.
    ReDim arrStr(2)
    Let iCount = CountElements(arrStr)                  ' arrStr is initialized, returns 3.
    ReDim arrStr(5 To 8)
    Let iCount = CountElements(arrStr)                  ' arrStr is initialized, returns 4.
    Let arrV = arrStr
    Let iCount = CountElements(arrV)                    ' arrV contains a boxed arrStr which is initialized, returns 4
    Erase arrStr
    Let iCount = CountElements(arrStr)                  ' arrStr size is erased, returns 0.
    
    Let iCount = CountElements(Nothing)                 ' Nothing is not an array, returns -1.
    Let iCount = CountElements(Null)                    ' Null is not an array, returns -1.
    Let iCount = CountElements(5)                       ' Figure is not an array, returns -1.
    Let iCount = CountElements("My imaginary array")    ' Text is not an array, returns -1.
    Let iCount = CountElements(Array(1, 2, 3, 4, 5))    ' Created array of Integer elements, returns 5.
    Let iCount = CountElements(Array("A", "B", "C"))    ' Created array of String elements, returns 3.
Hartsock answered 24/11, 2022 at 17:8 Comment(0)
C
-1

I see a lot of suggestions online about how to tell if an array has been initialized. Below is a function that will take any array, check what the ubound of that array is, redimension the array to ubound +1 (with or without PRESERVER) and then return what the current ubound of the array is, without errors.

Function ifuncRedimUbound(ByRef byrefArr, Optional bPreserve As Boolean)
On Error GoTo err:

1: Dim upp%:           upp% = (UBound(byrefArr) + 1)

errContinue:

If bPreserve Then
         ReDim Preserve byrefArr(upp%)
Else
         ReDim byrefArr(upp%)
End If

ifuncRedimUbound = upp%


Exit Function
err:
If err.Number = 0 Then Resume Next
    If err.Number = 9 Then ' subscript out of range (array has not been initialized yet)
             If Erl = 1 Then
                         upp% = 0
                         GoTo errContinue:
             End If
    Else
               ErrHandler.ReportError "modArray", ifuncRedimUbound, "1", err.Number, err.Description
    End If
End Function
Cesaria answered 26/9, 2018 at 1:17 Comment(0)
A
-2

This worked for me, any bug in this?

If IsEmpty(a) Then
    Exit Function
End If

MSDN

Arlettaarlette answered 25/6, 2014 at 6:52 Comment(2)
No, there's no bug. It's just useless. "IsEmpty only returns meaningful information for variants."Waltner
Thanks for clarification raven. I wonder why similar method not given for non-variants.Arlettaarlette
P
-8
Dim someArray() as Integer    

If someArray Is Nothing Then
    Debug.print "this array is not initialised"
End If
Pru answered 8/10, 2008 at 15:28 Comment(1)
Are you thinking of VB.NET? You might want to delete this answer AndrewPhonoscope

© 2022 - 2025 — McMap. All rights reserved.