Home » excel » excel – How to round variable values down to next lowest number from an array?

excel – How to round variable values down to next lowest number from an array?

Posted by: admin April 23, 2020 Leave a comment

Questions:

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, 307 or 389 or 425. How can I round this number down to the next lowest number contained in the array without using a bunch of If statements?

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?

How to&Answers:

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)

Output:

300

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 0.

Answer:

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

Used like:

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

Output:

 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

Answer:

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