Program 2 Help:
Mortgage Problem w/ Error Checking


The whole point of error checking is to filter what the user types on the screen BEFORE you attempt to read the data into local variables and perform calculations.  Why?  Because the user may enter unusable data, like text, that cannot be stored in a numeric variable.  So the approach is to test the data.  If it is incorrect the program displays an error message and stops prior to attempting to perform input and calculations with invalid or missing data.  If the data is entered correctly, on the other hand, then the input and calculations proceed normally.

What types of unusable data can the user enter? 

  1. The user can enter nothing, in which case it can result in an error by attempting to convert nothing to an integer.

  2. The user can enter text, which again cannot be converted to an integer.

  3. The user can enter a number outside the acceptable range.  This doesn't cause an error when the data is read in, but may cause an error or ridiculous results when calculations are performed.  For example, borrowing a negative amount of money is clearly not possible, so the program should check for that condition.

  4. The user can enter a floating point value in a field in which only integer numbers are acceptable.

How can checking for these potential problems be accomplished?  Let's look at each potential error individually.

  1. Nothing entered.  You can check to see if nothing has been entered by testing for a blank field, or "".  For example, if the condition (txtLoan.Text = "") evaluates to True, then nothing has been entered in the field.  That should trigger an error message.

  2. Text instead of numeric values.  You can check to see if a field has a numeric value by using the IsNumeric function.  This function will return True if there is a numeric value, or False if there is not. 

    Testing the condition IsNumeric(txtLoan.Text) doesn't quite accomplish what we want though.  If the fields has a numeric value it will return True, but we want to be warned (and an error message triggered) if there is NOT a numeric value.  How is this achieved?  The Not operator can be used to reverse or negate the test, so an error is generated if there is NOT a numeric value.  Therefore the condition Not (IsNumeric(txtLoan.Text)) can be used for this test.

  3. Number out of range.  This can be implemented fairly easily using the relational operators.  For example, if you want to test to be sure a number is not negative you can use the condition (myNum < 0) to trigger an error message.  There is a slight glitch in this type of test though.  You first have to extract the numeric value from a field or you will be comparing a text value to a numeric value.  You can use the Val function to extract numeric data from a field.  For example, the condition Val(txtLoan.Text) < 0) can be used to extract the value from the txtLoan control and then compare it to 0. If this evaluates to True it should trigger an error message.

    You can also test both ends of a range of values.  For example, if we want to trigger a warning if the interest percentage is between 0 and 1 (in case the user entered 0.075 instead of 7.5) then we can use the condition (Val(txtInterest.Text) >= 0) AND Val(txtInterest.Text) < 1)).  If this evaluates to True it should trigger a warning message.

  4.  Positive numbers only.  This test requires a little ingenuity on your part.  Or at least it did prior to reading this.  There are several ways in which you can test to see if a number is an integer.  Integer division is useful for this test.  Recall that integer division truncates any remainder from the division operation, as opposed to real division which keeps the remainder.  Can we use this to our advantage?  Sure.  If you divide a number by 1 and the result is not equal to the original number, then it cannot be an integer.  So we can simply take the number, perform integer division by 1, and if the result is not equal to the original number then it is not an integer.  Again we have to use the Val function since we need to extract the value from the text control.  The condition (Val(txtYears.Text) <> (Val(txtYears.Text) \ 1)) should trigger an error message if it evaluates to True.

That sums up the tests that have to be performed prior to reading data into the program.  Does the order in which the tests are performed matter.  Yes it does, because we do not want to try to extract a value from a field with the Val function prior to determining that there is a value to extract.  You want to check them in the order presented above--first check for an empty field, then for non numeric data, then for range violations and non integers.


As explained in class, you can perform all the tests for input field 1, and then all for field 2, etc., or you can perform them individually.  The individual test allows you to provide more specific error messages.  The all-at-once test requires that you use the OrElse to combine the test conditions.

For example, you can use the following all-at-once structure:

If (txtLoan.Text is blank) orelse (txtLoan.Text is non numeric) orelse (txtLoan.Text is negative)  then
   write ("Plenty big problems with
txtLoan")
ElseIf (txtInterest.Text is blank) orelse (txtInterest.Text is non numeric) orelse (txtInterest.Text is outside of acceptable range) then
   write ("Plenty big problems with txtInterest")
ElseIf (txtYears.Text is blank) orelse (txtYears.Text is non numeric) orelse (txtYears.Text is negative) orelse (txtYears.Text is non Integer) then
   write ("Plenty big problems with txtYears")
Else ' all must be okay
   If (txtInterest.Text is between 0 and 1) then
       display warning
   End If
   read values from screen into local variables
   do calcs with checks for divide by zero
   write output to screen
EndIf

You can also use the individual test approach:

If (txtLoan.Text is blank) then
   write ("Blank
txtLoan")
ElseIf
(txtLoan.Text is non numeric) then
   write ("Non numeric
txtLoan")
ElseIf
(txtLoan.Text is negative)  then
   write ("Negative
txtLoan")

ElseIf (txtInterest.Text is blank) then
   write ("Blank txtInterest")
ElseIf (txtInterest.Text is non numeric) then
   write ("Non numeric txtInterest")
ElseIf (txtInterest.Text is outside of acceptable range) then
   write ("Out of range txtInterest")
ElseIf (txtYears.Text is blank) then
   write ("Blank  txtYears")
ElseIf (txtYears.Text is non numeric)  then
   write ("Non numeric txtYears")
ElseIf (txtYears.Text is negative) then
   write ("Negative  txtYears")
ElseIf (txtYears.Text is non Integer) then
   write ("Non Integer txtYears")
Else ' all must be okay
   If (txtInterest.Text is between 0 and 1) then
       display warning
   End If
   read values from screen into local variables
   do calcs with checks for divide by zero
   write output to screen
EndIf

Regardless of the structure that you select, you replace the pseudocode test with the correct condition as explained above.