[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 492
  • Last Modified:

Subscript out of range on an Array

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
tomkent
Asked:
tomkent
1 Solution
 
mcriderCommented:
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
 
ParallelProcessorCommented:
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
 
ArtWrobleCommented:
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 does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
wsh2Commented:
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
 
mindphaserCommented:
Public Function IsBound(vArray As Variant) As Boolean
   On Error Resume Next
   IsBound = IsNumeric(UBound(vArray))
End Function
0
 
crazymanCommented:
            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
 
wsh2Commented:
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

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now