1. Computing

Getting Input and Validating It

A comparison of the VB6 Holdover InputBox and the Validating event of a TextBox

From , former About.com Guide

A reader asked for help coding a loop to use the InputBox to add data to a ListBox control. There were some specific requirements that had to be met as well:

  • Only five values could be added to the ListBox
  • The input data had to be validated for numeric values between 1 and 100
  • Blank input had to be disallowed

After pointing out a few logic errors in the program, it became clear that the real problem was the choice of technology to solve the problem.

  • The "holdover" InputBox from VB6 days.
  • Using a loop to input data.

There are just better ways to do it now. But if, for some reason, you have to use the InputBox, here's a followup article that explains how to solve one main problem.

I haven't actually tried to write a loop like this since VB.NET came onto the scene, so I gave it a shot just for fun. The first block of code below is what I came up with first.

--------
Click Here to display the illustration
--------


Private Sub AcceptGrades_Click(
    ByVal sender As System.Object,
    ByVal e As System.EventArgs
    ) Handles AcceptGrades.Click
    Dim dec_grade As Decimal
    Dim str_inputGrade As String = ""
    Dim int_counter As Integer = 1
    AcceptGrades.Enabled = False
    Do
        str_inputGrade =
            InputBox("Enter grade number " &
            int_counter.ToString,
            "Grade Calculator", "Enter Grade")
        If str_inputGrade = String.Empty Then
            MessageBox.Show("Nothing entered" &
            vbNewLine & "Please enter a grade",
            "Error",
            MessageBoxButtons.OK,
            MessageBoxIcon.Information)
        ElseIf Not IsNumeric(str_inputGrade) Then
            MessageBox.Show(
                "Input is not a numeric grade" &
            vbNewLine & "Please enter a numeric grade",
            "Error", MessageBoxButtons.OK,
            MessageBoxIcon.Information)
        Else
            dec_grade = CDec(str_inputGrade)
            If dec_grade >= 0 And dec_grade <= 100 Then
                GradeOutput.Items.Add(dec_grade)
                int_counter += 1
            Else
                MessageBox.Show(
                    "Enter a grade between 0-100",
                    "Error", MessageBoxButtons.OK,
                    MessageBoxIcon.Information)
            End If
        End If
    Loop Until int_counter > 5
End Sub

It works, but the code is "brittle". That's a term used for code that breaks easily whan anything is changed. And there are worse problems. For example, once you get into the loop, the only way to get out again is to cancel the program - not a very satisfactory user experience. Adding Cancel capability to the error boxes adds a lot of code and even more complexity. And the InputBox itself has a fatal flaw. The Cancel button in the InputBox returns a "zero length string". But a zero length string is also returned if the user simply forgets to enter anything. There's a way to tell the difference, but it requires using unmanaged code. This article explains how to do it.

Without getting into WPF or ASP.NET where there are even more sophisticated ideas, the best way to improve this program is to simply get rid of the InputBox and loop. Use a simple TextBox to enter the data and use a Label to display messages. And for data validation, code a Validating event for the TextBox control. This puts validation into one self-contained block and data entry into a different one. The global ValidGradeEntry variable guarantees that all the validating checks have been passed. New features (like a "Start Over" button or a button to delete ListBox entries, for example) could be added easily without disturbing any of the existing logic. And you can end the program without completing the loop!

--------
Click Here to display the illustration
--------


Dim ValidGradeEntry As Boolean
Private Sub inputGrade_Validating(
    ByVal sender As Object,
    ByVal e As System.ComponentModel.CancelEventArgs
    )
    ValidGradeEntry = False
    ErrorMsg.Text = ""
    If inputGrade.Text = "" Then
        ErrorMsg.Text = "Nothing entered" &
        vbNewLine & "Please enter a grade"
    ElseIf Not IsNumeric(inputGrade.Text) Then
        ErrorMsg.Text = "Input is not a numeric grade" &
            vbNewLine & "Please enter a numeric grade"
    ElseIf CDec(inputGrade.Text) < 0 Or
        CDec(inputGrade.Text) > 100 Then
        ErrorMsg.Text = "Enter a grade between 0-100"
    Else
        ValidGradeEntry = True
    End If
End Sub

Private Sub btnAcceptGrades_Click(
    ByVal sender As System.Object,
    ByVal e As System.EventArgs
    ) Handles AcceptGrades.Click
    If ValidGradeEntry = True Then
        GradeOutput.Items.Add(CDec(inputGrade.Text))
        inputGrade.Text = ""
        If GradeOutput.Items.Count = 5 Then
            AcceptGrades.Enabled = False
            ErrorMsg.Text = "5 grades entered" &
            vbNewLine & "No more input allowed"
        End If
    End If
    inputGrade.Focus()
End Sub

It's a minor point, but you might also keep in mind that the VB.NET AndAlso and OrElse operators are "short circuit" operators. That means that if you have a whole list of validating conditions, you can code them as a whole series connected with these operators (with the most frequent hits first) and nothing below a validation test that fails will use any processing.


If <validation test one succeeds> AndAlso
   <validation test two succeeds> AndAlso
   ...
Then Return <validation successful>

No doubt, there are still better ways. If you can improve on this, send it in!

  1. About.com
  2. Computing
  3. Visual Basic
  4. Quick Tips
  5. Getting Input and Validating it Using InputBox and the Validating Event

©2013 About.com. All rights reserved.