I’m working on a macro in Excel using VBA. I have an array of numbers like:
180, 190, 300, 390, 400, 430, ...
I then have a variable with a value of, say,
425. How can I round this number down to the next lowest number contained in the array without using a bunch of
For example, I would need to change:
307 -> 300 389 -> 300 425 -> 400
What would be a faster way to do this than using a long list of logic statements?
If your array is sorted, you can just use
HLOOKUP(). If you specify
True for the last parameter, it will match the closest previous value. For example:
Debug.Print WorksheetFunction.HLookup(307, Array(180, 190, 300, 390, 400, 430), 1, True)
You would just need to guard against numbers less than the lowest number (180, in this case). So you may want to start your array with a value of
Assuming that the array is sorted, you could use:
Function RoundTo(A As Variant, num As Long) As Variant 'returns greatest number in A which is <= num 'returns False if no such number exists 'assumes A is a sorted array of numbers Dim i As Long On Error Resume Next i = Application.WorksheetFunction.Match(num, A, 1) If Err.Number > 0 Then RoundTo = False Exit Function End If On Error GoTo 0 RoundTo = A(LBound(A) + i - 1) End Function
Sub test() Dim A As Variant, i As Long A = Array(12, 15, 19, 25, 39) Debug.Print RoundTo(A, 45) Debug.Print RoundTo(A, 18) Debug.Print RoundTo(A, 12) Debug.Print RoundTo(A, 11) End Sub
39 15 12 False
You could of course tweak it to return something other than
False when the number is too small to be rounded to any number in your list of numbers
You can do something like this.
Private Sub CommandButton20_Click() Dim aValues(1 To 5) As Integer Dim i As Integer aValues(1) = 180 aValues(2) = 190 aValues(3) = 300 aValues(4) = 390 aValues(5) = 400 Dim iFindValue As Integer iFindValue = 310 'First make sure we have a valid value to check for. If aValues(1) > iFindValue Then MsgBox ("Lowest value in the array is greater than variable.") Exit Sub End If 'Loop through the array For i = 1 To UBound(aValues) 'If we are at the end of the array, we haven't found it so set the value to the highest slot in the array. If i = UBound(aValues) Then iFindValue = aValues(i) Exit Sub End If 'If it is in between the current slot value and the next one, set it to the current. Effectively rounding it down. If aValues(i) < iFindValue And aValues(i + 1) > iFindValue Then iFindValue = aValues(i) Exit Sub End If Next i End Sub
You said your array could be sorted, but if for some reason it wasn’t, you could do something like this.
Private Sub CommandButton20_Click() Dim aValues(1 To 5) As Integer Dim i As Integer aValues(1) = 180 aValues(2) = 190 aValues(3) = 300 aValues(4) = 390 aValues(5) = 400 Dim iFindValue As Integer iFindValue = 310 Dim iTemp As Integer Dim iDifference As Integer iDifference = 32000 For i = 1 To UBound(aValues) 'Find the difference iTemp = iFindValue - aValues(i) 'If it is the smallest difference found so far, record it If iTemp > 0 And iTemp < iDifference Then iDifference = iTemp End If Next i 'Make the adjustment iFindValue = iFindValue - iDifference End Sub