Solved

Subscript out of range on an Array

Posted on 2000-08-16
7
469 Views
Last Modified: 2008-02-01
I Have a Function that returns an Array.  When the function has return I do a UBound to get the count of array elements.  If the function doesn't fill the array (like if no records are available) I get the subscript out of range error. I can work around it with error trapping but I was wondering if there is a way to check the array size without getting the error?
0
Comment
Question by:tomkent
7 Comments
 
LVL 14

Expert Comment

by:mcrider
ID: 3957272
You can code your own function...  For example:

    Function GetUbound(ArrayObject As Variant)
        Dim iVal As Long
        On Error Resume Next
        iVal = -1
        iVal = UBound(ArrayObject)
        GetUbound = iVal
    End Function



To use this function, you can do something like this:
   
    Private Sub Command1_Click()
        Dim x() As String
        Dim y As Long
       
        y = GetUbound(x)
        If y = -1 Then
            MsgBox "No Items in array"
        Else
            MsgBox "Ubound is " + CStr(y)
        End If
    End Sub



Cheers!®©
0
 
LVL 2

Accepted Solution

by:
ParallelProcessor earned 200 total points
ID: 3958174
Tom,

I agree - error trapping is a messy way to do it. Also, error trapping is not a very fast way to do it and it is a pain if you are debugging your project with the debugger set to stop at all errors.

The trick that I use is to read the SAFEARRAY descriptor in memory (Matt Curland's book is a great resource for these kinds of tricks). This particular bit of code can also be found on www.vb2themax.com

Good Luck!

Jon





To use, one would write the following code:

if ArrayDims(TestArray)=0 then
  msgbox "TestArray is empty"
end if


Add the following function to a module:

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Dest As _
    Any, Source As Any, ByVal bytes As Long)


Function ArrayDims(arr As Variant) As Integer
    Dim ptr As Long
    Dim VType As Integer
   
    Const VT_BYREF = &H4000&
   
    ' exit if not an array
    If (VType And vbArray) = 0 Then Exit Function
   
    CopyMemory ptr, ByVal VarPtr(arr) + 8, 4
    If (VType And VT_BYREF) Then
        CopyMemory ptr, ByVal ptr, 4
    End If
   
    If ptr Then
        CopyMemory ArrayDims, ByVal ptr, 2
    End If
End Function
0
 

Expert Comment

by:ArtWroble
ID: 3958292
Back in the early days of BASIC, it seems to me that there was some ambiguity about the i'th element of a vector, in some cases the first element's subscript was 0 or 1.  But I don't remember what was the default.  I vaguely remember you had to define it near where you Dim'd the array.  I wonder if it carried over into VB.  You might try looking at that aspect.  
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 14

Expert Comment

by:wsh2
ID: 3961200
If you Redim the array immediately after you create it then your UBound WILL work.

<---- Code Begin ----->

Private Sub Form_Load()

   If UBound(xMyArray) = 0 _
   Then
      MsgBox "Empty Table"
   End If

End Sub

Private Function xMyArray() As Variant

   Dim x() As String
   ReDim x(0)
   '
   ' Your Processing Here
   '
   xMyArray = x()
   
End Function

<----- Code End ----->

If you store your data in elements 1 on up this works very simply. If you want to use element 0, then you have to initialize it with a Unique value.. and test for it to find out if the array is empty.

<---- Code Begin ----->

Private Sub Form_Load()

   If xMyArray(0) = -32768 _
   Then
      MsgBox "Empty Table"
   End If

End Sub

Private Function xMyArray() As Variant

   Dim x() As Integer
   ReDim x(0)
   x(0) = -32768
   xMyArray = x()
   
End Function

<----- Code End ----->


0
 
LVL 1

Expert Comment

by:mindphaser
ID: 3966806
Public Function IsBound(vArray As Variant) As Boolean
   On Error Resume Next
   IsBound = IsNumeric(UBound(vArray))
End Function
0
 
LVL 13

Expert Comment

by:crazyman
ID: 3967252
            Private Declare Sub Copymemory Lib "kernel32" Alias "rtlmovememory" _
        (pdest As Any, Psrc As Any, Byval Bytelen As Long)


Private Function Getarraydimensions(byval Arrptr As Long) As Integer
    Dim Address As Long
    Copymemory Address, Byval Arrptr, Byval 4
    If Address <0 Then
        Copymemory Getarraydimensions, Byval Address, 2
    End If
End Function

Private Function Varptrarray(arr As Variant) As Long
    Copymemory Varptrarray, Byval Varptr(arr) + 8, Byval 4
End Function


Private Sub Form_load()
    Dim Myarr() As Long
    Dim Ndims As Integer

   Ndims = Getarraydimensions(varptrarray(myarr))
    If Ndims > 1 Then
        Msgbox "the Array Has " & Ndims & " Dimension(s)."
    Else
        Msgbox "the Array Has Not Been Initialized."
    End If
End Sub



           
0
 
LVL 14

Expert Comment

by:wsh2
ID: 3967398
Unless a dynamic array is ReDim'd.. there is NO WAY to test for its existence in VB (or the API for that matter). The best thing to do is always ReDim the array right after it's (Dim)creation.. after that UBound and other tests will always work.. <smile>.
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Introduction I needed to skip over some file processing within a For...Next loop in some old production code and wished that VB (classic) had a statement that would drop down to the end of the current iteration, bypassing the statements that were c…
Enums (shorthand for ‘enumerations’) are not often used by programmers but they can be quite valuable when they are.  What are they? An Enum is just a type of variable like a string or an Integer, but in this case one that you create that contains…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now