ReDim Names(100) As String, var As Variant
' Initialize the Names array (omitted).
var = Names() ' Copy the array into the Variant.
Print var(1) ' Access array items through the Variant.
You can even create an array of Variant elements on the fly using the Array function and store it in a Variant variable: ' Initialize the Names array (omitted).
var = Names() ' Copy the array into the Variant.
Print var(1) ' Access array items through the Variant.
' Arrays returned by the Array() function are zero-based.
Factorials = Array(1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800)
Likewise, you can pass an array to a procedure that expects a Variant parameter and then access the elements of the array through that parameter:Factorials = Array(1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800)
' A polymorphic function that sums the values in any array
Function ArraySum(arr As Variant) As Variant
Dim i As Long, result As Variant
For i = LBound(arr) To UBound(arr)
result = result + arr(i)
Next
ArraySum = result
End Function
The most interesting feature of the preceding routine is that it works correctly with any type of numeric one-dimensional array. It even works with String arrays, but in that case you get the concatenation of all items, not their sum. This procedure is extremely powerful and reduces the amount of code you have to write to deal with different kinds of arrays. But you should be aware that accessing array items through a Variant parameter noticeably slows down the execution. If you need the best performance, write specific routines that process specific types of arrays. Function ArraySum(arr As Variant) As Variant
Dim i As Long, result As Variant
For i = LBound(arr) To UBound(arr)
result = result + arr(i)
Next
ArraySum = result
End Function
You can also pass a multidimensional array to a routine that expects a Variant parameter. In this case, you can still access the array elements through the Variants, but if you don't know at compile time how many dimensions the array has, your routine has to determine that number before proceeding. You can get this value using a trial-and-error approach:
' This routine returns the number of dimensions of the array
' passed as an argument, or 0 if it isn't an array.
Function NumberOfDims(arr As Variant) As Integer
Dim dummy as Long
On Error Resume Next
Do
dummy = UBound(arr, NumberOfDims + 1)
If Err Then Exit Do
NumberOfDims = NumberOfDims + 1
Loop
End Function
It's perfectly legal to use the function name inside a function's code as if it were a local variable, as the previous code snippet does. Often this technique lets you save a local variable and a final assignment before exiting the routine, which indirectly makes your code run slightly faster.' passed as an argument, or 0 if it isn't an array.
Function NumberOfDims(arr As Variant) As Integer
Dim dummy as Long
On Error Resume Next
Do
dummy = UBound(arr, NumberOfDims + 1)
If Err Then Exit Do
NumberOfDims = NumberOfDims + 1
Loop
End Function
Here's a modified ArraySum routine that uses NumberOfDims and works with both one- and two-dimensional arrays:
Function ArraySum2(arr As Variant) As Variant
Dim i As Long, j As Long, result As Variant
' First check whether we can really work with this array.
Select Case NumberOfDims(arr)
Case 1 ' One-dimensional array
For i = LBound(arr) To UBound(arr)
result = result + arr(i)
Next
Case 2 ' Two-dimensional array
For i = LBound(arr) To UBound(arr)
For j = LBound(arr, 2) To UBound(arr, 2)
result = result + arr(i, j)
Next
Next
Case Else ' Not an array, or too many dimensions
Err.Raise 1001, , "Not an array or more than two dimensions"
End Select
ArraySum2 = result
End Function
Often, if a Variant contains an array, you don't know the basic type of that array in advance. The VarType function returns the sum of the vbArray constant (decimal 8192), plus the VarType of the data included in the array. This lets you test that the array passed to a routine is of a given type:Dim i As Long, j As Long, result As Variant
' First check whether we can really work with this array.
Select Case NumberOfDims(arr)
Case 1 ' One-dimensional array
For i = LBound(arr) To UBound(arr)
result = result + arr(i)
Next
Case 2 ' Two-dimensional array
For i = LBound(arr) To UBound(arr)
For j = LBound(arr, 2) To UBound(arr, 2)
result = result + arr(i, j)
Next
Next
Case Else ' Not an array, or too many dimensions
Err.Raise 1001, , "Not an array or more than two dimensions"
End Select
ArraySum2 = result
End Function
If VarType(arr) = (vbArray + vbInteger) Then
' Array of integers
ElseIf VarType(arr) = (vbArray + vbLong) Then
' Array of Longs
ElseIf VarType(arr) And vbArray Then
' An array of another type (just tests a bit)
End If
You can also test whether a Variant holds an array using the IsArray function. When a Variant variable holds an array, the TypeName function appends a pair of empty parentheses to its result:' Array of integers
ElseIf VarType(arr) = (vbArray + vbLong) Then
' Array of Longs
ElseIf VarType(arr) And vbArray Then
' An array of another type (just tests a bit)
End If
Print TypeName(arr) ' Displays "Integer()"
As I've explained, you can either assign an array to a Variant variable or you can pass an array as a Variant parameter of a procedure. While the two operations look very similar, they're substantially different. To execute an assignment, Visual Basic makes a physical copy of the array. As a result, the Variant variable doesn't point to the original data but to the copy; from this point on, all the manipulations you do through the Variant variable don't affect the original array. Conversely, if you call a procedure and pass an array as a Variant parameter, no data is physically copied and the Variant simply works as an alias of the array. You can reorder array items or modify their values, and your changes are immediately reflected in the original array
No comments:
Post a Comment
Comment will be published after moderation only. Do not advertise here.