How to determine if an array is initialized in VB6?

Passing an unlimited array to the UB6 Ubound function will throw an error, so I want to check if it has been measured before trying to check its upper bound. How to do it?

+52
arrays vb6
Oct 08 '08 at 15:22
source share
21 answers

That's what I went with. This is similar to the GSerg answer , but uses the best documented API CopyMemory function and is completely self-contained (you can just pass an array, not ArrPtr (array) into this function). It uses the VarPtr function, which Microsoft warns about this , but this application is only for XP, and it works, so I am not interested.

Yes, I know that this function will accept everything that you throw on it, but I will leave 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 
+14
Jan 14 '09 at 21:42
source share

I use this:

 Public Declare Function GetMem4 Lib "msvbvm60" (ByVal pSrc As Long, ByVal pDst As Long) As Long Public Declare Function ArrPtr Lib "msvbvm60" Alias "VarPtr" (arr() As Any) As Long Public Function StrArrPtr(arr() As String, Optional ByVal IgnoreMe As Long = 0) As Long GetMem4 VarPtr(IgnoreMe) - 4, VarPtr(StrArrPtr) End Function Public Function UDTArrPtr(ByRef arr As Variant) As Long If VarType(arr) Or vbArray Then GetMem4 VarPtr(arr) + 8, VarPtr(UDTArrPtr) Else Err.Raise 5, , "Variant must contain array of user defined type" End If End Function Public Function ArrayExists(ByVal ppArray As Long) As Long GetMem4 ppArray, VarPtr(ArrayExists) End Function 

Using:

 ? ArrayExists(ArrPtr(someArray)) 
 ? ArrayExists(StrArrPtr(someArrayOfStrings)) 
 ? ArrayExists(UDTArrPtr(someArrayOfUDTs)) 

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

+24
Oct 08 '08 at 16:31
source share

I just thought about it. Simple enough, no API calls are required. Any problems with this?

 Public Function IsArrayInitialized(arr) As Boolean Dim rv As Long On Error Resume Next rv = UBound(arr) IsArrayInitialized = (Err.Number = 0) End Function 

Change I found a flaw in the behavior of the Split function (in fact, I would 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? This is -1! Thus, passing this array to this IsArrayInitialized function will return true, but trying to access arr (0) will result in an index error outside the range.

+17
Oct 08 '08 at 21:02
source share

I found this:

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

Edit : RS Conley indicated in his answer that (not someArray) sometimes returns 0, so you need to use ((Not someArray) = -1).

+13
Oct 08 '08 at 15:22
source share

Both the GSerg and Raven methods are undocumented hacks, but since Visual BASIC 6 is no longer being developed, this is not a problem. However, the Raven example does not work on all machines. You have to test this.

If (Not someArray) = -1 Then

On some machines, it will return zero to another large negative number.

+8
Oct 08 '08 at 19:16
source share

VB6 has a function called "IsArray", but it does not check if the array has been initialized. You will get Error 9 - Subscript out of range if you try to use UBound for an uninitialized array. My method is very similar to SJ, except that it works with all types of variables and has error handling. If a variable without an array is marked, you will receive an error message 13 - Type of 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 
+5
Sep 24 '12 at 19:31
source share

This is a modification of the answer . Without using the API.

 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 ie 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. ie array not initialized End Function 

This should also work with split function. Constraint - you need to determine the type of array (string in this example).

+3
Jun 14 '12 at 15:53
source share
 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 

Using:

 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 
+2
Apr 08 '15 at 17:54
source share

When you initialize the array, put an integer or boolean with flag = 1. and request this flag when you need to.

+1
Jan 21 2018-12-12T00:
source share

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

It supports testing code in accordance with the use of UBOUND and does not require the use of error handling for testing.

It depends on zero arrays (which is the case in most development cases).

Do not use Erase to clear the array. use the alternative 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. 
+1
Apr 30 '15 at 20:06
source share

The easiest way to handle this is to make sure the array is initialized in front, before you need to check for Ubound. I need an array that has been declared in the (General) area of ​​the form code. i.e.

 Dim arySomeArray() As sometype 

Then in form load mode, I delete the array:

 Private Sub Form_Load() ReDim arySomeArray(1) As sometype 'insure that the array is initialized End Sub 

This will allow you to repeat the definition of the array at any time later in the program. When you find out how large the array is, you just need to redo it.

 ReDim arySomeArray(i) As sometype 'i is the size needed to hold the new data 
+1
Sep 22 '17 at 16:20
source share

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 nonzero, otherwise the function returns zero.

Note that you cannot use this function with options that contain arrays. This will result in a compilation 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 probram won't compile or run. 'Debug.Print SafeArrayGetDim(vArray) ' <- Compile error: Type mismatch End Sub 
+1
Jan 29 '19 at 3:24
source share

My only problem with API calls is moving from 32-bit to 64-bit.
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 
0
Aug 12
source share

You can solve the problem using the Ubound() function, check if the array is empty by counting the total number of elements using the JScript VBArray() object (works with variant type arrays, 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 microseconds for each element + 100 ms initialization compiled with VB 6.0.9782, so an array of 10 M elements takes about 4.1 seconds. The same functionality can be implemented using ScriptControl ActiveX.

0
Dec 13 '15 at 1:36
source share
 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 
0
Jul 12 '16 at 15:55
source share

There are two different scenarios:

  • The array is initialized (in fact, this is not a null pointer)
  • The array is initialized and has at least one element

Case 2 is necessary for cases such as Split(vbNullString, ",") , which returns an array of String with LBound=0 and UBound=-1 . Here are the simplest code examples 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 
0
Sep 14 '16 at 10:08 on
source share

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

Here is my solution (to 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 when Arr is created by an external COM dll, and the fourth when Arr not ReDim -ed (the subject of this question):

  • UBound(Arr) works, so calling UBound2(Arr) adds a bit of overhead, but it doesn't UBound2(Arr) much
  • UBound(Arr) fails in a function that defines Arr , but succeeds inside UBound2()
  • UBound(Arr) as in the function that defines Arr and in UBound2() , so error handling does its job
  • After Dim Arr() As Whatever before, before ReDim Arr(X)
0
Feb 15 '18 at 0:36
source share

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 
-one
Oct 08 '08 at 16:05
source share

I see a lot of suggestions on how to determine if an array has been initialized . Below is a function that will take any array, check what ubound of this array is, resize the array to ubound +1 (with or without PRESERVER), and then return the current ubound value of the array 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
-one
Sep 26 '18 at 1:17
source share

It worked for me, any mistake in that?

 If IsEmpty(a) Then Exit Function End If 

MSDN

-2
Jun 25 '14 at 6:52
source share
 Dim someArray() as Integer If someArray Is Nothing Then Debug.print "this array is not initialised" End If 
-8
Oct 08 '08 at 15:28
source share



All Articles