Reputation: 553
I don't understand why for each loop in vba doesn't return the good number of element when i use dynamic array.
For exemple, my array size is 4, and i have 5 iteration in for each loop ...
Public Sub test()
Dim t_direction() As String
Dim t_nextDirection() As String
Dim myDirection As Variant
Dim test As Integer
Var = 0
ReDim t_direction(4)
t_direction(0) = "N"
t_direction(1) = "S"
t_direction(2) = "E"
t_direction(3) = "W"
t_nextDirection = randomizeArray(t_direction)
For Each myDirection In t_nextDirection
Var = Var + 1
Next myDirection
MsgBox (UBound(t_nextDirection))
MsgBox (Var)
End Sub
Public Function randomizeArray(ByVal t_array As Variant) As String()
Dim i As Integer
Dim j As Integer
Dim tmp As String
Dim numItems As Integer
numItems = UBound(t_array) - 1
' Randomize the array.
For i = 0 To numItems
' Pick a random entry.
j = Rand(0, numItems)
' Swap the numbers.
tmp = t_array(i)
t_array(i) = t_array(j)
t_array(j) = tmp
Next i
'MsgBox (UBound(t_array))
randomizeArray = t_array
End Function
Public Function Rand(ByVal Low As Long, _
ByVal High As Long) As Integer
Rand = Int((High - Low + 1) * Rnd) + Low
End Function
Upvotes: 1
Views: 272
Reputation: 53135
ReDim t_direction(4)
actually declares t_direction
as 0 To 4
Its better to be explicit:
ReDim t_direction(0 To 3)
In the absence of a specified lower bound (using the To
clause), then the default lower bound is used.
This default can be set to 0
or 1
by using Option Base {0|1}
at module level.
In the absence of Option Base
then the default default is 0
Notes:
In VBA you are not limited to 0
or 1
as the lower bound, you can use any value you want.
To iterate over an array use
For i = LBound(arr) To UBound(arr)
To calculate the number of items in an array use
numItems = UBound(arr) - LBound(arr) + 1
This way you are not making any assumptions on what the lower bound is
Upvotes: 2
Reputation: 55672
At the moment you are creating a 5 element array with
ReDim t_direction(4)
as the first element occurs as t_direction(0)
You should either
ReDim t_direction(3)
(ie 0 to 3) and then use numItems
consistent with that, orReDim t_direction
with a base of 1 (ie 1 to 4) and then use numItems
consistent with that (ie numItems = UBound(t_array)
). The Option Base 1
below forces the first element to be 1 (which is then ensured anyow by using ReDim t_direction(1 To 4)
The code below uses the later approach. It returns 4 and 4 rather than your current 4 and 5
Option Base 1
Public Sub test()
Dim t_direction() As String
Dim t_nextDirection() As String
Dim myDirection As Variant
Dim test As Integer
Var = 0
ReDim t_direction(1 To 4)
t_direction(1) = "N"
t_direction(2) = "S"
t_direction(3) = "E"
t_direction(4) = "W"
t_nextDirection = randomizeArray(t_direction)
For Each myDirection In t_nextDirection
Var = Var + 1
Next myDirection
MsgBox (UBound(t_nextDirection))
MsgBox (Var)
End Sub
Public Function randomizeArray(ByVal t_array As Variant) As String()
Dim i As Integer
Dim j As Integer
Dim tmp As String
Dim numItems As Integer
numItems = UBound(t_array)
' Randomize the array.
For i = 1 To numItems
' Pick a random entry.
j = Rand(1, numItems)
' Swap the numbers.
tmp = t_array(i)
t_array(i) = t_array(j)
t_array(j) = tmp
Next i
'MsgBox (UBound(t_array))
randomizeArray = t_array
End Function
Public Function Rand(ByVal Low As Long, _
ByVal High As Long) As Integer
Rand = Int((High - Low + 1) * Rnd) + Low
End Function
Upvotes: 4