2

I'm working on a VBA problem to find the maximum and minimum values in a sequence while skipping invalid inputs.

The issue I'm facing is that when the first value in the sequence is invalid, the variable minnum automatically gets assigned a value of 0 (for example: entering 3, a, 1, 2 gives min = 0, max = 2).

However, this error doesn't occur if the first input is valid (for example: entering 3, 1, a, 2 gives min = 1, max = 2).

Sub minmaxnum()
    Dim maxnum As Long
    Dim minnum As Double
    Dim n As Integer
    Dim num As Double
    Dim i As Integer

    n = InputBox("How many numbers do you want to enter?")
    maxnum = 0
    minnum = 1E+39

    On Error Resume Next
    For i = 1 To n
        num = InputBox("Enter those numbers: ")
        If num > maxnum Then
            maxnum = num
        End If
        If num < minnum Then
            minnum = num
        End If
    Next i

    MsgBox "Maxnum is: " & maxnum & vbCrLf & "Minnum is: " & minnum
End Sub

3 Answers 3

3

The reason your code "works" if the first input is numeric but fails if the first input is not numeric is easy:

You declare num as a number (of type double), and in VBA, numbers are initiallized with the value 0, so at the beginning of your code, you have a 0 in num. Now you ask VBA to implicitly convert the result of the InputBox (which is a string) into a number. VBA tries its best to do so, but an input of a simply cannot be converted into a number. A runtime error is generated (Runtime error 13, "Type mismatch"). But with the statement On Error Resume Next you tell VBA to ignore this error. num keeps it's value (0) and the code continues, writing this 0 into minval.

When you first enter a number, eg 3, and after that a, num keeps the value 3 and your code continues (but you handled the value 3 already, so min and max stays the same).

My advice is to get rid of the On Error Resume Next and check the input by yourself. You can do this by declaring the input variable as String and use the function IsNumeric to check if the input was a number.

What I also did is to change the type of your min and max variable to Variant. With that you can rid of assigning dummy values to them. Plus the code works also with negative values. A Variant is not initialized with 0, but is set to an internal value known as Empty.

Sub minmaxnum()
    Dim minnum As Variant, maxnum As Variant
    Dim n As Long, i As Long
    Dim inputVal As String

    Do While n = 0
        inputVal = InputBox("How many numbers do you want to enter?")
        If inputVal = "" Then Exit Sub
        If IsNumeric(inputVal) Then n = inputVal
    Loop

    For i = 1 To n
        inputVal = InputBox("Enter " & i & ". number")
        If IsNumeric(inputVal) Then
            If IsEmpty(maxnum) Or maxnum < inputVal Then
                maxnum = inputVal
            End If
            If IsEmpty(minnum) Or minnum > inputVal Then
                minnum = inputVal
            End If
        End If
    Next i

    MsgBox "Maxnum is: " & maxnum & vbCrLf & "Minnum is: " & minnum
End Sub
Sign up to request clarification or add additional context in comments.

Comments

3

Use the Application class instead

num = Application.InputBox("Enter those numbers: ", , , , , , , 1)

this variant checks the input type, in the above method it is set to number. If the input is not a number an error message is displayed and wait for the correct input.

Comments

0

Determine Min and Max from Entered Values

Sub MinMaxNum()
    
    ' Define constants.
    Const PROC_TITLE As String = "Minimum and Maximum"
    Const MIN_NUMBERS_COUNT As Long = 1
    Const MAX_NUMBERS_COUNT As Long = 20
    
    ' Declare variables.
    Dim InputString As String, InputNumber As Double
    
    ' Require user input...
    InputString = InputBox("How many numbers do you want to enter?", PROC_TITLE)
    
    ' Exit if no number.
    If Not IsNumeric(InputString) Then
        MsgBox """" & InputString & """ is no number!", _
            vbExclamation, PROC_TITLE
        Exit Sub
    End If
    
    ' Exit if no integer.
    InputNumber = CDbl(InputString)
    If InputNumber <> Int(InputNumber) Then
        MsgBox "The number " & CStr(InputNumber) & " is no integer!", _
            vbExclamation, PROC_TITLE
        Exit Sub
    End If
    
    ' Exit if out of bounds.
    If InputNumber < MIN_NUMBERS_COUNT Or InputNumber > MAX_NUMBERS_COUNT Then
        MsgBox "The number " & InputNumber & " is not between " _
            & MIN_NUMBERS_COUNT & " and " & MAX_NUMBERS_COUNT & "!", _
            vbExclamation, PROC_TITLE
        Exit Sub
    End If
    
    ' Declare additional variables.
    Dim i As Long, MinNumber As Double, MaxNumber As Double
    Dim WasNumberEntered As Boolean
    
    ' Determine the minimum and maximum from the user input.
    For i = 1 To InputNumber
        InputString = InputBox("Enter number " & i & ":", PROC_TITLE)
        If IsNumeric(InputString) Then
            If WasNumberEntered Then ' each time after the first time ...
                InputNumber = CDbl(InputString)
                Select Case InputNumber
                    Case Is < MinNumber
                        MinNumber = InputNumber
                    Case Is > MaxNumber
                        MaxNumber = InputNumber
                End Select
            Else ' the first time a number was entered
                MinNumber = CDbl(InputString)
                MaxNumber = MinNumber
                WasNumberEntered = True ' never reset
            End If
        End If
    Next i
    
    ' Display result (if applicable).
    If WasNumberEntered Then
        MsgBox "The minimum is " & MinNumber & vbLf _
            & "The maximum is " & MaxNumber, vbInformation, PROC_TITLE
    Else
        MsgBox "No number entered!", vbExclamation, PROC_TITLE
    End If

End Sub

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.