Home

Microsoft Visual Basic Exception Handling

 

Exception Handling Fundamentals

 

Introduction

As opposed to the traditional techniques used to deal with errors, Visual Basic now supports a technique referred to as exception handling. This technique was mostly used by other languages such as C/C++, Object Pascal, C#, etc. This technique is also referred to as structured exception handling (SEH).

The On Error GoTo system of dealing with errors is referred to as unstructured exception handling (we will abbreviate is unSEH). There were many concerns with unSEH (mostly lastly used in Microsoft Visual Basic 6):

  • In unSEH, you have to remember to include On Error GoTo sometimes in a random area inside the function. Besides On Error GoTo, you have to remember to create a label section. The name of the label has to be faithfully included in the On Error GoTo line
  • When using the On Error GoTo technique, you have to make sure you get out of the function at the right time, which is done using an Exit Sub line. If you create this Exit Sub line in the wrong area in your function, either the whole code would not be considered or an desired section of the function would still execute, possibly producing an unpredictable result. In the same way, a bizarre way of creating a Resume or a Resume Next line would prevent the compiler from reaching or considering some sections of a function
  • As mentioned previously, the On Error GoTo system provides a global variable named Err. As flexible as good intentioned as it may appear, to effectively use Err, you have to proceed by trial and error because Err identifies errors by a number but its documentation does not possibly provide a list of error numbers. This is because Err not only depends on the application (Visual Basic, VBA, etc) but also it depends on the circumstance in which it is invoked. The only possible solution is to cause an error in your code in order to cause Err to show the numeric error that occurred. Then you have to use that error number and create a custom error message

Because of these uncertainties, you should abandon the On Error GoTo traditional error handling and use SEH in all of your new code. Because SEH and unSEH techniques are inherently different, you cannot use both in the same function.

Practical LearningPractical Learning: Introducing Exception Handling

  1. Start Microsoft Visual Basic if necessary.
    Create a new Windows Application named GeorgetownCleaningServices1
  2. Design the form as follows:
     
    Control Name Text
    Form    
    Label   Customer Name:
    TextBox TxtCustomerName1  
    Label   mm
    Label   dd
    Label   yyyy
    Label   Order Date:
    TextBox TxtMM 1
    TextBox TxtDD 1
    TextBox TxtYYYY 2000
    Label   Item Types
    Label   Qty
    Label   Unit Price
    Label   Sub-Total
    Label   Shirts
    TextBox TxtQtyShirts 0
    TextBox TxtUnitPriceShirts 1.15
    TextBox TxtSubTotalShirts 0.00
    Label   Pants
    TextBox TxtQtyPants 0
    TextBox TxtUnitPricePants 1.95
    TextBox TxtSubTotalPants 0.00
    Label   Other
    TextBox TxtQtyOther 0
    TextBox TxtUnitPriceOther 3.50
    TextBox TxtSubTotalOther 0.00
    Button BtnProcess Process
    Label   Customer Name:
    TextBox TxtCustomerName2  
    Label   Order date:
    TextBox TxtOrderDate  
    Label   Tax Rate:
    TextBox TxtTaxRate 5.75
    Label   %
    Button BtnTax Tax
    Label   Total Order:
    TextBox TxtTotalOrder 0.00
    Label   Tax Amount:
    TextBox TxtTaxAmount 0.00
    Label   Net Price:
    TextBox TxtNetPrice 0.00
    Label   Amount Tended:
    TextBox TxtAmountTended 0.00
    Button BtnDifference Diff
    Label   Difference:
    TextBox TxtDifference 0.00
  3. To arrange the tab sequence, on the main menu, click View -> Tab Order
  4. On the form, click only the following controls whose squares have a white background, in the indicated order:
     
    Georgetown Cleaning Services - Tab Order
  5. Press Esc
  6. Right-click the form and click View Code
  7. Declare a few variables as follows:
    Public Class Form1
    
        ' Order Information
        Dim CustomerName As String
        Dim mm As String
        Dim dd As String
        Dim yyyy As String
    
        ' Quantities of items
        Dim NumberOfShirts As Integer
        Dim NumberOfPants As Integer
        Dim NumberOfOther As Integer
    
        ' Price of items
        Dim PriceOneShirt As Double
        Dim PriceAPairOfPants As Double
        Dim PriceOther As Double
    
        ' Each of these sub totals will be used for cleaning items
        Dim SubTotalShirts As Double
        Dim SubTotalPants As Double
        Dim SubTotalOther As Double
    
        ' Values used to process an order
        Dim TaxRate As Double
        Dim TotalOrder As Double
        Dim TaxAmount As Double
        Dim SalesTotal As Double
    
    End Class
  8. In the Class Name combo box, select BtnProcess
  9. In the Method Name, select Click and implement its event as follows:
    Private Sub BtnProcessClick(ByVal sender As Object,
                                ByVal e As System.EventArgs)
                                Handles BtnProcess.Click
            If BtnProcess.Text = "Process" Then
                Height = 408
                BtnProcess.Text = "Reset"
            Else
                Height = 232
                TxtCustomerName1.Text = ""
                TxtMM.Text = "1"
                TxtDD.Text = "1"
                TxtYYYY.Text = "2000"
                TxtQtyShirts.Text = "0"
                TxtQtyPants.Text = "0"
                TxtQtyOther.Text = "0"
                TxtSubTotalShirts.Text = "0.00"
                TxtSubTotalPants.Text = "0.00"
                TxtSubTotalOther.Text = "0.00"
    
                BtnProcess.Text = "Process"
            End If
    
            ' Request order information from the user
            CustomerName = TxtCustomerName1.Text
            mm = TxtMM.Text
            dd = TxtDD.Text
            yyyy = TxtYYYY.Text
    
            ' Request the quantity of each category of items
            ' Number of Shirts
            NumberOfShirts = CInt(TxtQtyShirts.Text)
            ' Number of Pants
            NumberOfPants = CInt(TxtQtyPants.Text)
            ' Number of Dresses
            NumberOfOther = CInt(TxtQtyOther.Text)
    
            ' Unit Prices of items
            PriceOneShirt = CDbl(TxtUnitPriceShirts.Text)
            PriceAPairOfPants = CDbl(TxtUnitPricePants.Text)
            PriceOther = CDbl(TxtUnitPriceOther.Text)
    
            ' Perform the necessary calculations
            SubTotalShirts = NumberOfShirts * PriceOneShirt
            SubTotalPants = NumberOfPants * PriceAPairOfPants
            SubTotalOther = NumberOfOther * PriceOther
    
            TxtSubTotalShirts.Text = CStr(SubTotalShirts)
            TxtSubTotalPants.Text = CStr(SubTotalPants)
            TxtSubTotalOther.Text = CStr(SubTotalOther)
    
            ' Calculate the "temporary" total of the order
            TotalOrder = SubTotalShirts + SubTotalPants + SubTotalOther
    
            ' Display the receipt
            TxtCustomerName2.Text = CustomerName
            TxtOrderDate.Text = mm + "/" & dd + "/" & yyyy
            TxtTotalOrder.Text = CStr(TotalOrder)
    End Sub
  10. In the Class Name combo box, select BtnTax
  11. In the Method Name, select Click and implement its event as follows:
    Private Sub BtnTaxClick(ByVal sender As Object, 
                            ByVal e As System.EventArgs) 
                            Handles BtnTax.Click
            ' Get the tax rate
                TaxRate = CDbl(TxtTaxRate.Text) / 100
    
            ' Calculate the tax amount using a constant rate
                TaxAmount = TotalOrder * TaxRate
            ' Add the tax amount to the total order
                SalesTotal = TotalOrder + TaxAmount
    
            TxtTaxAmount.Text = TaxAmount.ToString()
            TxtNetPrice.Text = CStr(SalesTotal)
    End Sub
  12. In the Class Name combo box, select BtnDifference
  13. In the Method Name, select Click and implement its event as follows:
    Private Sub BtnDifferenceClick(ByVal sender As Object, 
                                   ByVal e As System.EventArgs) 
                                   Handles BtnDifference.Click
            Dim AmountTended As Double = 0.0
            Dim Difference As Double = 0.0
    
            ' Request money for the order
            AmountTended = CDbl(TxtAmountTended.Text)
    
            ' Calculate the difference owed to the customer
            ' or that the customer still owes to the store
            Difference = AmountTended - SalesTotal
    
            TxtDifference.Text = CStr(Difference)
    End Sub
  14. Return to the form and resize it form to appear as follows:
     
  15. To execute the application, on the Standard toolbar, click the Start Without Debugging button
     
      
  16. Close the form and return to your programming environment
  17. Execute the application again. This time, type a letter such as d for the quantity of shirts and click Process
     
  18. Click Quit to close the form and return to your programming environment

Try to Catch the Error

As mentioned already, errors are likely going to occur in your program. The more you anticipate them and take action, the better your application can be. We have already seen that syntax errors are usually human mistakes such as misspelling, bad formulation of expressions, etc. The compiler will usually help you fix the problem by pointing it out.

SEH is based on two main keywords: Try and Catch. An exception handling section starts with the Try keyword and stops with the End Try statement. Between Try and End Try, there must by at least one Catch section. Therefore, exception handling uses the following formula:

Try
    ' Code to execute in case everything is alright
Catch
    ' If something bad happened, deal with it here
End Try

Exception handling always starts with the Try keyword. Under the Try line, Write the normal code that the compiler must execute. Here is an example:

Private Sub CalculateClicked(ByVal sender As Object, 
                             ByVal e As EventArgs) 
                             Handles BtnCalculate.Click
            Dim Number As Double
            Dim Result As Double

            Try
                Number = CDbl(InputBox("Enter a number:"))
            
            End Try
End Sub

As the compiler is treating code in the Try section, if it encounters a problem, it "gets out" of the Try section and starts looking for a Catch section. Therefore, you MUST always have a Catch section. If you do not, the program will not compile. A Catch section must be written before the End Try line:

Private Sub CalculateClicked(ByVal sender As Object, 
                             ByVal e As EventArgs) 
                             Handles BtnCalculate.Click
            Dim Number As Double
            Dim Result As Double

            Try
                Number = CDbl(InputBox("Enter a number:"))
            Catch
                
            End Try
End Sub

When the Catch keyword is simply written as above, it would be asked to treat any error that occurs. For example, if you execute the above code with a number such as 35$.75 instead of 35$.75, nothing would appear to happen. This would indicate that the error was found and vaguely dealt with. One problem in this case is that the compiler would not bother to let the user know why there is no result displayed. Because there can be various types of errors in a program, you also should make your program more intuitive and friendlier so that, when an error occurs, the user would know the type of problem. This is also useful if somebody calls you and says that your program is not functioning right. If there is a way the user can tell you what exact type of error is displaying, maybe you would find the solution faster.

 
 
 

Practical LearningPractical Learning: Catching Exceptions

  1. To introduce exceptions, access the form's code and change the events of the buttons as follows:
    Public Class Form1
    
       . . . No Change
    
        Private Sub BtnProcessClick(ByVal sender As Object, 
                                     ByVal e As System.EventArgs) 
                                     Handles BtnProcess.Click
            . . . No Change
    
            ' Request the quantity of each category of items
            ' Number of Shirts
            Try
                NumberOfShirts = CInt(TxtQtyShirts.Text)
            Catch
    
            End Try
    
            ' Number of Pants
            Try
                NumberOfPants = CInt(TxtQtyPants.Text)
            Catch
    
            End Try
    
            ' Number of Dresses
            Try
                NumberOfOther = CInt(TxtQtyOther.Text)
            Catch
    
            End Try
    
            ' Unit Prices of items
            Try
                PriceOneShirt = CDbl(TxtUnitPriceShirts.Text)
            Catch
    
            End Try
    
            Try
                PriceAPairOfPants = CDbl(TxtUnitPricePants.Text)
            Catch
    
            End Try
    
            Try
                PriceOther = CDbl(TxtUnitPriceOther.Text)
            Catch
    
            End Try
    
            . . . No Change
        End Sub
    
        Private Sub BtnTaxClick(ByVal sender As Object, 
                                 ByVal e As System.EventArgs) 
                                 Handles BtnTax.Click
            ' Get the tax rate
            Try
                TaxRate = CDbl(TxtTaxRate.Text) / 100
            Catch
    
            End Try
            ' Calculate the tax amount using a constant rate
            TaxAmount = TotalOrder * TaxRate
            ' Add the tax amount to the total order
            SalesTotal = TotalOrder + TaxAmount
    
            TxtTaxAmount.Text = TaxAmount.ToString()
            TxtNetPrice.Text = SalesTotal.ToString()
        End Sub
    
        Private Sub BtnDifferenceClick(ByVal sender As Object, 
                                        ByVal e As System.EventArgs) 
                                        Handles BtnDifference.Click
            Dim AmountTended As Double = 0.0
            Dim Difference As Double = 0.0
    
            ' Request money for the order
            Try
                AmountTended = CDbl(TxtAmountTended.Text)
            Catch
    
            End Try
    
            ' Calculate the difference owed to the customer
            ' or that the customer still owes to the store
            Difference = AmountTended - SalesTotal
    
            TxtDifference.Text = CStr(Difference)
        End Sub
    End Class
  2. Execute the application. This time, type invalid values in the quantity text boxes and other text boxes where the user is supposed to enter some values
     
  3. Click Process
     
  4. Return to your programming environment

The Error Message

As mentioned already, if an error occurs when processing the program in the Try section, the compiler transfers the processing to the next Catch section. You can then use the catch section to deal with the error. At a minimum, you can display a message to inform the user. To do this, you can create a message box in the Catch section. Here is an example:

Imports System.Drawing
Imports System.Windows.Forms

Module Exercise

    Public Class Starter
        Inherits Form

        Private LblNumber As Label
        Private TxtNumber As TextBox
        Friend WithEvents BtnCalculate As Button
        Private LblResult As Label
        Private TxtResult As TextBox

        Dim components As System.ComponentModel.Container

        Public Sub New()
            InitializeComponent()
        End Sub

        Public Sub InitializeComponent()
            Text = "Exception Behavior"

            LblNumber = New Label
            LblNumber.Location = New Point(17, 23)
            LblNumber.Text = "Number:"
            LblNumber.AutoSize = True

            TxtNumber = New TextBox
            TxtNumber.Location = New Point(78, 20)
            TxtNumber.Size = New Size(83, 20)

            BtnCalculate = New Button
            BtnCalculate.Location = New Point(78, 45)
            BtnCalculate.Text = "Calculate"
            BtnCalculate.Size = New Size(83, 23)

            LblResult = New Label
            LblResult.Location = New Point(17, 75)
            LblResult.Text = "Result:"
            LblResult.AutoSize = True

            TxtResult = New TextBox
            TxtResult.Location = New Point(76, 72)
            TxtResult.Size = New Size(83, 20)

            Controls.Add(LblNumber)
            Controls.Add(TxtNumber)
            Controls.Add(BtnCalculate)
            Controls.Add(LblResult)
            Controls.Add(TxtResult)

        End Sub

        Private Sub CalculateClicked(ByVal sender As Object, 
                                     	      ByVal e As EventArgs) 
                                     	      Handles BtnCalculate.Click
            Dim Number As Double
            Dim Result As Double

            Try
                Number = CDbl(TxtNumber.Text)
                Result = Number * 12.48
                TxtResult.Text = CStr(Result)
            Catch
                MsgBox("Something bad happened")
            End Try
        End Sub
    End Class

    Function Main() As Integer

        Dim frmStart As Starter = New Starter

        Application.Run(frmStart)

        Return 0
    End Function

End Module

Custom Message

Of course, your message may not be particularly clear but this time, the program will not crash.

Practical LearningPractical Learning: Displaying Custom Messages

  1. To display custom messages to the user, change the code as follows:
    Public Class Form1
    
        . . . No Change
    
        Private Sub BtnProcessClick(ByVal sender As Object, 
                                     ByVal e As System.EventArgs) 
                                     Handles BtnProcess.Click
            . . . No Change
    
            ' Request the quantity of each category of items
            ' Number of Shirts
            Try
                NumberOfShirts = CInt(TxtQtyShirts.Text)
            Catch
                MsgBox("The value you typed for the number of " & 
                       "shirts is not a valid number." & 
                       vbCrLf & "Please enter a natural number such " & 
                       "as 2 or 24 or even 248")
            End Try
    
            ' Number of Pants
            Try
                NumberOfPants = CInt(TxtQtyPants.Text)
            Catch
                MsgBox("The value you typed for the number of " & 
                       "pair or pants is not a valid number." & 
                       vbCrLf & "Please enter a natural number such " & 
                       "as 2 or 24 or even 248")
            End Try
    
            ' Number of other items
            Try
                NumberOfOther = CInt(TxtQtyOther.Text)
            Catch
                MsgBox("The value you typed for the number of " & 
                       "other items is not a valid number." & 
                       vbCrLf & "Please enter a natural number such " & 
                       "as 2 or 24 or even 248")
            End Try
    
            ' Unit Prices of items
            Try
                PriceOneShirt = CDbl(TxtUnitPriceShirts.Text)
            Catch
                MsgBox("The value you entered for the unit price " & 
                       "of a shirt is not a recognizable currency " & 
                       "amount." & vbCrLf & 
                       "Only natural or decimal numbers " & 
                       "are allowed. Please consult the management " & 
                       "to know the valid prices.")
            End Try
    
            Try
                PriceAPairOfPants = CDbl(TxtUnitPricePants.Text)
            Catch
                MsgBox("The value you entered for the unit price of " & 
                       "a pair of pants is not a recognizable " & 
                       "currency amount." & vbCrLf & 
                       "Only natural or decimal " & 
                       "numbers are allowed. You can consult the " & 
                       "management to find out about " & 
                       "the allowable prices.")
            End Try
    
            Try
                PriceOther = CDbl(TxtUnitPriceOther.Text)
            Catch
                MsgBox("The value you entered for the unit " & 
                       "price of other items is not a valid amount." & 
                       vbCrLf & "You must enter only a natural or a " & 
                       "decimal number. For more information, " & 
                       "please consult the management to get " & 
                       "the right prices.")
            End Try
    
            . . . No Change
        End Sub
    
        Private Sub BtnTaxClick(ByVal sender As Object, 
                                 ByVal e As System.EventArgs) 
                                 Handles BtnTax.Click
            ' Get the tax rate
            Try
                TaxRate = CDbl(TxtTaxRate.Text) / 100
            Catch
                MsgBox("The value you entered is not " & 
                       "recognized as a valid tax rate." & 
                       vbCrLf & "A valid tax rate is a value " & 
                       "between 0 and 100.00" & 
                       vbCrLf & "Please try again.")
            End Try
            ' Calculate the tax amount using a constant rate
            TaxAmount = TotalOrder * TaxRate
            ' Add the tax amount to the total order
            SalesTotal = TotalOrder + TaxAmount
    
            TxtTaxAmount.Text = TaxAmount.ToString()
            TxtNetPrice.Text = SalesTotal.ToString()
        End Sub
    
        Private Sub BtnDifferenceClick(ByVal sender As Object, 
                                        ByVal e As System.EventArgs) 
                                        Handles BtnDifference.Click
            Dim AmountTended As Double = 0.0
            Dim Difference As Double = 0.0
    
            ' Request money for the order
            Try
                AmountTended = CDbl(TxtAmountTended.Text)
            Catch
                MsgBox("The value you entered for the amount " & 
                       "tended is not valid. Only natural or " & 
                       "decimal numbers are allowed." & 
                       "Please try again.")
            End Try
    
            ' Calculate the difference owed to the customer
            ' or that the customer still owes to the store
            Difference = AmountTended - SalesTotal
    
            TxtDifference.Text = CStr(Difference)
        End Sub
    End Class
  2. Test the application with valid and invalid values. Here is an example:
     

    Georgetown Cleaning Services

  3. Close the form and return to your programming environment

Exceptions in the .NET Framework

 

The Exception Class

Most libraries such as Borland's VCL and Microsoft's MFC ship with their own classes to handle exceptions. Even the Win32 library provides its type of mechanism to face errors. To support exception handling, the .NET Framework provides a special class called Exception. Once the compiler encounters an error, the Exception class allows you to identify the type of error and take an appropriate action.

Normally, Exception mostly serves as the general class of exceptions. It is used like a Catch that is not followed by any parameter. Anticipating various types of problems that can occur in a program, Microsoft derived various classes from Exception to make this issue friendlier. As a result, almost any type of exception you may encounter already has a class created to deal with it. Therefore, when your program faces an exception, you can easily identify the type of error.

There are so many exception classes that we cannot study or review them all. The solution we will use is to introduce or review a class when we meet its type of error.

In exception handling, errors are dealt with in the Catch clause. To use it, on the right side of Catch, type a parameter name, followed by the As operator, and followed by the the type of exception you want to deal with. By default, an exception is first of type Exception. Based on this, a typical formula to implement exception handling is:

Private Sub CalculateClicked(ByVal sender As Object, 
                                     	      ByVal e As EventArgs) 
                                     	      Handles BtnCalculate.Click
            Dim Number As Double
            Dim Result As Double

            Try

                ' Process the normal flow of the program here

            Catch ex As Exception

                ' Deal with the exception here

            End Try

End Sub

As reviewed already, when an exception occurs in the Try section, code compilation is transferred to the Catch section. If you declare the exception as an Exception type, this class will identify the error.

The Exception's Message

One of the properties of the Exception class is called Message. This property contains a string that describes the type of error that occurred. You can then use this Exception.Message property to display an error message if you want. Here is an example:

Private Sub CalculateClicked(ByVal sender As Object, 
                                     ByVal e As EventArgs) 
                                     Handles BtnCalculate.Click
            Dim Number As Double
            Dim Result As Double

            Try
                Number = CDbl(TxtNumber.Text)
                Result = Number * 12.48
                TxtResult.Text = CStr(Result)
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
End Sub

An exception using the Exception.Message message

Custom Error Messages

As you can see, one of the strengths of the Message property is that it gives you a good indication of the type of problem that occurred. Sometimes, the message provided by the Exception class may not appear explicit enough. In fact, you may not want to show it to the user since, as in this case, the user may not understand what the message means and why it is being used. As an alternative, you can create your own message and display it to the user. As seen previously, to display your own message, in the Catch section, use the MsgBox() function to create and display a message. Here is an example:

Private Sub CalculateClicked(ByVal sender As Object, 
                                     ByVal e As EventArgs) 
                                     Handles BtnCalculate.Click
            Dim Number As Double
            Dim Result As Double

            Try
                Number = CDbl(TxtNumber.Text)
                Result = Number * 12.48
                TxtResult.Text = CStr(Result)
            Catch ex As Exception
                MsgBox("The operation could not be carried because " & 
                             "the number you typed is not valid")
            End Try
End Sub

An exception with a custom message

You can also combine the Exception.Message message and your own message:

Private Sub CalculateClicked(ByVal sender As Object, 
                                     ByVal e As EventArgs) 
                                     Handles BtnCalculate.Click
            Dim Number As Double
            Dim Result As Double

            Try
                Number = CDbl(TxtNumber.Text)
                Result = Number * 12.48
                TxtResult.Text = CStr(Result)
            Catch ex As Exception
                MsgBox(ex.Message & 
                       vbCrLf & "The operation could not be carried because " & 
                       "the number you typed is not valid")
            End Try
End Sub

Exception Handling

 
 
   
 

Home Copyright © 2004-2010 FunctionX, Inc.