Given an array and a string and bounds within which to search, I need to find the position of the string within those bounds.
What I want to optimise:
If possible, I want to re-design the function so that it doesn't have 10 optional arguments, some of which are not actually optional depending on the size of the array being passed.
Having bounds for each dimension of the array is important because I might be after, for example, a string in the headings which could also appear elsewhere in the array.
I also don't like passing the arguments as variants but I needed a non-integer value to correspond to "L/U bound of the array".
The function itself also feels rather inelegant. It feels like there should be a much simpler way to implement what I'm trying to do.
Any suggestions on how to improve the above, including splitting it into a combination of subs/functions would be much appreciated. General suggestions about good coding practice also much appreciated.
Brief description of macro flow:
select casefor number of dimensions in the array- Check that all the required variables for that size have values
- Iterate through every element within the bounds supplied
- If/when the string is found, output the value of the dimension that was requested.
Public Function Array_Position(ByVal varSearch As Variant, ByRef arrSearchArray() As Variant, ByVal lngNumberOfDimensions As Long, ByVal lngDimensionToSearch As Long, _
Optional ByVal lngFirstDimensionLbound As Variant, Optional ByVal lngFirstDimensionUbound As Variant, _
Optional ByVal lngSecondDimensionLbound As Variant, Optional ByVal lngSecondDimensionUbound As Variant, _
Optional ByVal lngThirdDimensionLbound As Variant, Optional ByVal lngThirdDimensionUbound As Variant, _
Optional ByVal lngFourthDimensionLbound As Variant, Optional ByVal lngFourthDimensionUbound As Variant, _
Optional ByVal lngFifthDimensionLbound As Variant, Optional ByVal lngFifthDimensionUbound As Variant)
'/======================================================================================================================================================
'/ Author: Zak Armstrong
'/ Email: -
'/ Date: 14/August/2015
'/
'/ Is Called By: -
'/
'/ Calls: None
'/
'/ Description: General "Find position of string in dimension of Array" Sub
'/
'/ N.B. only accepts arrays up to 5 dimensions
'/
'/ Returns null if no match found
'/======================================================================================================================================================
Dim I As Long
Dim J As Long
Dim K As Long
Dim L As Long
Dim M As Long
Dim bMatchFound As Boolean
Dim varPosition As Variant
'/======================================================================================================================================================
On Error Resume Next
If lngFirstDimensionLbound = "all" Then lngFirstDimensionLbound = LBound(arrSearchArray, 1)
If lngSecondDimensionLbound = "all" Then lngSecondDimensionLbound = LBound(arrSearchArray, 2)
If lngThirdDimensionLbound = "all" Then lngThirdDimensionLbound = LBound(arrSearchArray, 3)
If lngFourthDimensionLbound = "all" Then lngFourthDimensionLbound = LBound(arrSearchArray, 4)
If lngFifthDimensionLbound = "all" Then lngFifthDimensionLbound = LBound(arrSearchArray, 5)
If lngFirstDimensionUbound = "all" Then lngFirstDimensionUbound = UBound(arrSearchArray, 1)
If lngSecondDimensionUbound = "all" Then lngSecondDimensionUbound = UBound(arrSearchArray, 2)
If lngThirdDimensionUbound = "all" Then lngThirdDimensionUbound = UBound(arrSearchArray, 3)
If lngFourthDimensionUbound = "all" Then lngFourthDimensionUbound = UBound(arrSearchArray, 4)
If lngFifthDimensionUbound = "all" Then lngFifthDimensionUbound = UBound(arrSearchArray, 5)
On Error GoTo 0
bMatchFound = False
varPosition = Null
Select Case lngNumberOfDimensions
Case Is = 1
If IsMissing(lngFirstDimensionLbound) Or IsMissing(lngFirstDimensionUbound) Then Call Array_Position_Error
For I = lngFirstDimensionLbound To lngFirstDimensionUbound
If arrSearchArray(I) = varSearch _
Then
varPosition = I
bMatchFound = True
End If
Next I
Case Is = 2
If IsMissing(lngFirstDimensionLbound) Or IsMissing(lngFirstDimensionUbound) Then Call Array_Position_Error
If IsMissing(lngSecondDimensionLbound) Or IsMissing(lngSecondDimensionUbound) Then Call Array_Position_Error
For I = lngFirstDimensionLbound To lngFirstDimensionUbound
For J = lngSecondDimensionLbound To lngSecondDimensionUbound
If arrSearchArray(I, J) = varSearch _
Then
Select Case lngDimensionToSearch
Case Is = 1
varPosition = I
bMatchFound = True
Case Is = 2
varPosition = J
bMatchFound = True
End Select
End If
Next J
Next I
Case Is = 3
If IsMissing(lngFirstDimensionLbound) Or IsMissing(lngFirstDimensionUbound) Then Call Array_Position_Error
If IsMissing(lngSecondDimensionLbound) Or IsMissing(lngSecondDimensionUbound) Then Call Array_Position_Error
If IsMissing(lngThirdDimensionLbound) Or IsMissing(lngThirdDimensionUbound) Then Call Array_Position_Error
For I = lngFirstDimensionLbound To lngFirstDimensionUbound
For J = lngSecondDimensionLbound To lngSecondDimensionUbound
For K = lngThirdDimensionLbound To lngThirdDimensionUbound
If arrSearchArray(I, J, K) = varSearch _
Then
Select Case lngDimensionToSearch
Case Is = 1
varPosition = I
bMatchFound = True
Case Is = 2
varPosition = J
bMatchFound = True
Case Is = 3
varPosition = K
bMatchFound = True
End Select
End If
Next K
Next J
Next I
Case Is = 4
If IsMissing(lngFirstDimensionLbound) Or IsMissing(lngFirstDimensionUbound) Then Call Array_Position_Error
If IsMissing(lngSecondDimensionLbound) Or IsMissing(lngSecondDimensionUbound) Then Call Array_Position_Error
If IsMissing(lngThirdDimensionLbound) Or IsMissing(lngThirdDimensionUbound) Then Call Array_Position_Error
If IsMissing(lngFourthDimensionLbound) Or IsMissing(lngFourthDimensionUbound) Then Call Array_Position_Error
For I = lngFirstDimensionLbound To lngFirstDimensionUbound
For J = lngSecondDimensionLbound To lngSecondDimensionUbound
For K = lngThirdDimensionLbound To lngThirdDimensionUbound
For L = lngFourthDimensionLbound To lngFourthDimensionUbound
If arrSearchArray(I, J, K, L) = varSearch _
Then
Select Case lngDimensionToSearch
Case Is = 1
varPosition = I
bMatchFound = True
Case Is = 2
varPosition = J
bMatchFound = True
Case Is = 3
varPosition = K
bMatchFound = True
Case Is = 4
varPosition = L
bMatchFound = True
End Select
End If
Next L
Next K
Next J
Next I
Case Is = 5
If IsMissing(lngFirstDimensionLbound) Or IsMissing(lngFirstDimensionUbound) Then Call Array_Position_Error
If IsMissing(lngSecondDimensionLbound) Or IsMissing(lngSecondDimensionUbound) Then Call Array_Position_Error
If IsMissing(lngThirdDimensionLbound) Or IsMissing(lngThirdDimensionUbound) Then Call Array_Position_Error
If IsMissing(lngFourthDimensionLbound) Or IsMissing(lngFourthDimensionUbound) Then Call Array_Position_Error
If IsMissing(lngFifthDimensionLbound) Or IsMissing(lngFifthDimensionUbound) Then Call Array_Position_Error
For I = lngFirstDimensionLbound To lngFirstDimensionUbound
For J = lngSecondDimensionLbound To lngSecondDimensionUbound
For K = lngThirdDimensionLbound To lngThirdDimensionUbound
For L = lngFourthDimensionLbound To lngFourthDimensionUbound
For M = lngFifthDimensionLbound To lngFifthDimensionUbound
If arrSearchArray(I, J, K, L, M) = varSearch _
Then
Select Case lngDimensionToSearch
Case Is = 1
varPosition = I
bMatchFound = True
Case Is = 2
varPosition = J
bMatchFound = True
Case Is = 3
varPosition = K
bMatchFound = True
Case Is = 4
varPosition = L
bMatchFound = True
Case Is = 5
varPosition = M
bMatchFound = True
End Select
End If
Next M
Next L
Next K
Next J
Next I
Case Else
MsgBox ("varPosition only accepts arrays up to 5 dimensions")
End
End Select
Array_Position = varPosition
End Function