Reputation: 6463
I have a two-dimensional array:
(1, 1) = X (1, 2) = [Empty] (1, 3) = [Empty]
(2, 1) = Y (2, 2) = [Empty] (2, 3) = [Empty]
(3, 1) = Z (3, 2) = [Empty] (3, 3) = [Empty]
I want to store data in 2nd and 3rd column, where the row number is determined by matching values in the first column against some specific value provided. Is there a way to find the row number of the array where Z
is present, without having to loop through the whole column? I'm looking for an equivalent of using WorksheetFunction.Match
on a one-dimensional array.
To solve my problem, I can create two arrays, where the first one will have one dimension and will store values to look in, and the second one will store the rest of columns. I'd rather have just one, though.
Upvotes: 0
Views: 9238
Reputation: 21
'To determine if a multi-dimension array is allocated (or empty)
'Works for any-dimension arrays, even one-dimension arrays
Public Function isArrayAllocated(ByVal aArray As Variant) As Boolean
On Error Resume Next
isArrayAllocated = IsArray(aArray) And Not IsError(LBound(aArray, 1)) And LBound(aArray, 1) <= UBound(aArray, 1)
Err.Clear: On Error GoTo 0
End Function
'To determine the number of dimensions of an array
'Returns -1 if there is an error
Public Function nbrDimensions(ByVal aArray As Variant) As Long
Dim x As Long, tmpVal As Long
If Not IsArray(aArray) Then
nbrDimensions = -1
Exit Function
End If
On Error GoTo finalDimension
For x = 1 To 65536 'Maximum number of dimensions (size limit) for an array that will work with worksheets under Excel VBA
tmpVal = LBound(aArray, x)
Next x
finalDimension:
nbrDimensions = x - 1
Err.Clear: On Error GoTo 0
End Function
'*****************************************************************************************************************************
'To return an array containing al the coordinates from a specified two-dimension array that have the searched item as value
'Returns an empty array if there is an error or no data
'Returns coordinates in the form of x,y
'*****************************************************************************************************************************
Public Function makeArrayFoundXYIn2DimArray(ByVal itemSearched As Variant, ByVal aArray As Variant) As Variant
Dim tmpArr As Variant, x As Long, y As Long, z As Long
tmpArr = Array()
If IsArray(aArray) Then
If isArrayAllocated(aArray) And nbrDimensions(aArray) = 2 Then
z = 0
For x = LBound(aArray, 1) To UBound(aArray, 1)
For y = LBound(aArray, 2) To UBound(aArray, 2)
If itemSearched = aArray(x, y) Then
If z = 0 Then
ReDim tmpArr(0 To 0)
Else
ReDim Preserve tmpArr(0 To UBound(tmpArr) + 1)
End If
tmpArr(z) = CStr(x) + "," + CStr(y)
z = z + 1
End If
Next y
Next x
End If
End If
makeArrayFoundXYIn2DimArray = tmpArr
Erase tmpArr
End Function
shareeditflag
Upvotes: 0
Reputation: 21
Try this function
Public Function posInArray(ByVal itemSearched As Variant,ByVal aArray As Variant) As Long
Dim pos As Long, item As Variant
posInArray = 0
If IsArray(aArray) Then
If Not isEmpty(aArray) Then
pos = 1
For Each item In aArray
If itemSearched = item Then
posInArray = pos
Exit Function
End If
pos = pos + 1
Next item
posInArray = 0
End If
End If
End Function
Upvotes: 2
Reputation: 4363
You can use Index()
for working with areas in arrays which then allows you to use match. However, I've always found Excel functions to be extremely slow when used on VBA arrays, especially on larger ones.
I'd hazard a guess and and say that actually looping through would be your best bet here. Alternatively, depending on your use case use a different storage mechanism, something with a Key/Value lookup like a collection or Scripting.Dictionary would probably give you the best performance
EDIT
For the record, I again state that I wouldn't do it like this, it's slow on large arrays, but you can do:
Sub test()
Dim arr(1 To 3, 1 To 3)
arr(1, 1) = "X"
arr(2, 1) = "Y"
arr(3, 1) = "Z"
With Application
MsgBox .Match("Z", .Index(arr, 0, 1), 0)
End With
End Sub
Upvotes: 1