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

vb6 check if array is empty
vb6 array
visual basic multidimensional array
vba check if array is initialized
visual basic array of objects
vb.net initialize array
visual basic byte array
visual basic function return array

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?

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://stackoverflow.com/a/32539884/11683 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 :)

Classic VB, One of the common problems when dealing with arrays is to know when the array has VB6, XHTML & CSS hobbyist Merri's Avatar Dim lngNewIndex As Long ' check whether our array is initialized: if it is, take UBound and  Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information. Learn more In vb 6.0, how can we know if a dynamic array have been initialized?

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.

Determine if An Array is Initialized, This is the snippet Determine if An Array is Initialized on FreeVBCode. The FreeVBCode site provides free Visual Basic code, examples, snippets, and articles  vb6 Declare an Array. Ask Question Asked 7 years, 5 months ago. There is no "Char" type in VB6, nor is there any initialization syntax on variable declaration.

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

How to: Initialize an Array Variable, See also. You initialize an array variable by including an array literal in Either in the New clause, or when you assign the array value, supply  Sometimes functions will return an uninitialized array (Null or "Nothing" return) or sometimes they may return an initialized array that is not allocated. My goal is to eliminate redundant code in the form of If / Else blocks before using each array, or Try / Catch blocks to handle exceptions thrown by the array being un-initialized or un-allocated.

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).

Arrays, When you use Visual Basic syntax to define the size of an array, you examples, see How to: Initialize an Array Variable in Visual Basic. To initialize an array variable by using an array literal Either in the New clause, or when you assign the array value, supply the element values inside braces ( {} ). The following example shows several ways to declare, create, and initialize a variable to contain an array that has elements of type Char .

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.

Checking if an array is initialized and allocated in VB.NET, If you have enabled Option Strict you will see a warning on the line ElseIf inArray(​0) Is Net is carrying over the VB6 error handling pattern. 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.

excel-vba, excel-vba Check if Array is Initialized (If it contains elements or not). Example#. A common problem might be trying to iterate over Array which has no values in  excel-vba Check if Array is Initialized (If it contains elements or not). Example A common problem might be trying to iterate over Array which has no values in it.

Visual Basic .NET Language, To declare a null array variable, you must declare it without a size: Dim array() As Integer. Or Dim array As Integer(). To check if an array is null, test to see if it Is  I recommend a slightly different approach because I think using language artifacts like (Not Array) = -1 to check for initialization is difficult to read and causes maintenance headaches. If you are needing to check for array allocation, most likely it's because you're trying to make your own "vector" type: an array that grows during runtime to

Testing for Empty Arrays with VBScript, Consider the following test… 1 2 3 4 5 6 7 Sub Main() Dim arr arr = Array() If IsArray(arr)  not variable must initialize initialization the class static java how arrays - How do I determine if an array is initialized in VB6? 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.

Comments
  • 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. Thanks
  • I agree with Praesageus.
  • 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.
  • 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.
  • >> 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...
  • 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. +1
  • RtlMoveMemory is slower than the native GetMem4. GetMem4 is over twice as fast: vbforums.com/archive/index.php/t-360672.html
  • +1, unlike the top-voted answer, this one does appear to work with string arrays.
  • From a discussion linked to by another comment, Karl Peterson provided a similar function that includes some additional validation.
  • 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.
  • Can be fixed by adding the last line to the function: If ArrayIsInitialized Then ArrayIsInitialized = Ubound(arr) >= Lbound(arr).
  • 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.