Previous Page TOC Next Page


5 — Error Trapping, Error Handling, and Error Reporting

by Richard Buhrer

Programs execute in an uncertain world. Even a completely bug-free program can encounter problems during execution. Any number of interactions between the user, the hardware (host computer and network), and other active programs in a multitasking environment can result in error conditions that stop a Visual Basic program cold.

When Visual Basic programs encounter these error conditions, they terminate immediately and unceremoniously. A user can easily lose important data. Even when the error condition is entirely caused by the user, the user's dissatisfaction and anger is directed toward the software and its author(s).

High quality software must be written with a means for intercepting errors when they occur. At best, software should provide a mechanism for remedying the error condition; at least, software should allow a graceful exit with no data loss. This process is commonly referred to as error handling.

An Introduction to Errors

The folks at Microsoft define runtime errors as "errors that occur while your code is running and that result from attempts to complete an invalid operation." These errors are reported to the program by the Visual Basic runtime engine as numerical codes. In Visual Basic 4.0, these codes are long integers. The codes (as you are probably aware) fall in the range of —2,147,483,648 to 2,147,483,647—that's approximately 4.3 billion unique errors that the system can report. There is some logic (although not a lot) to the error codes. Table 5.1 summarizes the ranges of error codes.

Ranges


Description


Comments


3 to 94

System errors

Miscellaneous errors concerning interactions with memory, disks, and various programming errors like Return without GoSub.

260 to 428

DDE and form-related messages

These errors include some important interactions between programs and with Windows, such as No timer available.

429 to 451

OLE automation messages

These return information about the external condition of OLE automation servers, whether it can be located, if it doesnt respond in a certain amount of time, and so on. Internal conditions in servers are passed to the client program by adding an internal error code to the constant, vbObjectError and returning that as the error number. These are important errors to attend to if you are interested in the OLE automation client and server functions of Visual Basic 4.0.

452 to 521

Miscellaneous

These messages cover interactions with resource messages(RES) files, the Clipboard, printers, and other truly miscellaneous messages.

2055 to 3751

Data access

A large range of database access errors that object errors return error conditions from the MS Access/Jet database engine.

20476 to

Common dialog

These messages are spread out over a wide range 28671, 31001, control messages of numerical values; not a sign of careful logic 32751 to 32766 in assigning error numbers.

30000 to 30017

Grid messages

Error messages from the Visual Basic grid control.

31003 to 31039

OLE control

Messages from the OLE control for Visual Basic 4.0.

32001 to 32015

DB grid messages

Error messages for the Visual Basic data-bound grid control.

The Basics of Error Handling

There are really three activities that make up error handling:

A common example of an error condition is addressing a floppy disk drive with no disk in it. In this case, trapping the error means intercepting the error before Visual Basic terminates the program. In this situation, the error is Error 71, Disk not ready. Handling the error simply means instructing the user to place a disk in the drive or to close the drive door and then instructing the program to resume processing. If the error is unexpected or unrecoverable, that is, something the error handler cannot process, then the next step is reporting the error. This means returning the error condition to the default error-handling routines of the compiler (which cause, in this case, an unceremonious termination of the program).

There is a set of language constructs for error processing that have been present in various dialects of Basic for a number of years. Visual Basic 4.0 supports these legacy tools with which you may already be familiar. Error trapping is enabled by using the On Error construct, as follows:

On Error Goto Label1

... Error prone actions

On Error Goto 0

On Error ... is the statement that turns error handling on and off. The On Error statement has three forms:

Most error-handling routines are variations on the following code skeleton:

Label1:

      Select Case Err

       ...Case X      ' an anticipated error

              'Fix the error

               Resume

            Case Else 'Unanticipated Errors

                Msg$ = Error$(Err)

                MsgBox Msg$

                 Error Err

         End Select

Exit Sub 'or Function

After the label, error handling code often uses some branching structure (If...Then...Else...End If or Select Case) to process the anticipated errors; it also uses a default clause (Else or Case Else). Information about the nature of the error is retrieved from the system Err object that contains a long integer.


Caution

The nature of the system Err object/value is one of the big changes in Visual Basic 4.0. In Visual Basic 3.0 and earlier, the Err value was a global system variable of type integer. In Visual Basic 4.0, it is an OLE object with a default property of Number (a long integer).

Review your error-handling code in legacy code; at the least, you should change to Long the type of the variables used to access the Err value. If you don't do this, you face the possibility of generating an error (runtime error # 6, Overflow) in your error handler. This is not a pretty thought. The good news is that Visual Basic now has room for a much richer error-handling capability; it gives programmers the ability to identify and process errors that occur in OLE objects outside Visual Basic; it also gives programmers the ability to use the error-handling system to process programmer-defined, application-specific errors.

The Error[$]() function returns what Microsoft calls a descriptive string (these strings are still rather cryptic and may not give the programmer or the user much helpful information if the programmer relies on them solely for the information returned to the user). The Error statement returns the error condition to the compiler's default error processing. The syntax of the Error statement can take one of two forms:

Error Err

Error number

This construct is useful for the handling of unanticipated errors in an error handler. Although Visual Basic 4.0 supports both the Error() function and the Error statement, new features in Visual Basic 4.0 provider richer information and finer control of the default processing of errors. These new features are described in the following section.

New Error-Handling Features in Visual Basic 4.0

Visual Basic 4.0 introduces three new tools for managing errors and retaining the legacy error management functions. The new tools include the Err object (for Visual Basic errors), the Errors collection and Error object (for data access object errors), and options that customize the development environment's error handling behavior.


Caution

Although legacy code should execute correctly because of the design of the new Err ob-ject, it's always wise to test error-handling routines in the Visual Basic 4.0 environment.

The Err Object

The new Err object, like any OLE object, exposes properties and methods for reporting and responding to error conditions. Table 5.2 lists the properties of the Err object; Table 5.3 lists the methods of the Err object.

Property


Description


Number

The number identifying the error. This the default property of the Err object.

Description

The descriptive name associated with an error.

Source

The name of the object or application in which the error originated.

HelpFile

A fully qualified path to a Windows Help file.

HelpContext

A Context ID referring to a specific topic in a help file.

LastDLLError

Passes an error value returned from a dynamic link library called using the Declare syntax. Only available in the 32-bit version of Visual Basic (because of the error reporting capabilities of the underlying operating systems).

Method


Description


Raise

Generates a runtime error.

Clear

Resets the Err object, erasing any earlier error information.


Why Raise Errors?

The Err object gives much finer control over error reporting. Some of the potential uses are:

The syntax for the Raise method is shown here:

object.Raise(Number[, Source[, Description[, HelpFile[, HelpContext]]]])

Note that only the first parameter, Number, is required. The syntax also supports named arguments. Because the default property of the Err object is the Number property, code using the Error() function and the Error statement still executes correctly.


Tip

The MsgBox[()] construct in Visual Basic 4.0 has the same capabilities as the MsgBox[()] construct in Visual Basic for Applications. The extended syntax is as follows:

MsgBox(prompt[, buttons][, title][, helpfile, context])

Note that helpfile and context parameters have been added. When a helpfile name and a helpfile construct are specified, the resulting message box responds to the F1 key by launching Windows Help and displaying the help context to the user. This is done without your having to use WinHelp API calls in your own application.

Consequently, you can use the following code to launch a message box:

Answer = MsgBox( Prompt:=Err.Description _
Buttons:=vbYesNO + vbCritical _
Title:= "Error Number " & Err.Number _
Helpfile:= Err.Helpfile _
Context:=Err.Context)
If Answer = vbYes Then ....


Note

Visual Basic 4.0 embraces the OLE 2.0 model of objects. For example, the font properties of controls in Visual Basic 3.0 and earlier (FontName, FontSize, FontBold, and so on) have been replaced by a Font object with properties (Name, Size, Bold, and so on).

Consider the following code for Visual Basic 3.0:

MyControl.FontName = "Arial"
MyControl.FontSize = 10
MyControl.FontBold = True
Code end

It is replaced by this code in Visual Basic 4.0:

With MyControl.Font
.Name = "Arial"
.Size = 10
.Bold = True
End With

See Chapter 16, "OLE for the First Time," for more information on objects and their uses.

The Error Object and Errors Collection

The Error object reports data access object errors and is very similar to the Err object in its structure. The differences are that the Error object has no LastDLLError property and no Raise or Clear methods. Table 5.4 describes the properties of the Error object.

Property


Description


Number

The number identifying the error. This the default property of the Error object.

Description

The descriptive name associated with an error.

Source

The name of the object or application in which the error originated.

HelpFile

A fully qualified path to a Windows Help file.

HelpContext

A Context ID referring to a specific topic in a help file.

The Errors collection belongs to the DBEngine object. When a data access action occurs, the collection is populated with all the occurring errors. When another data access action occurs, the collection is emptied and repopulated with any new errors. Like all collections, the Errors collection has only one property: Count. By examining the Count property of the Errors collection, you can determine whether the data access action executed without error:

If DBEngine.Errors.Count <> 0 then

... process errors....

End If

Environment Options

Environment options that customize error handling are located in the Advanced tab of the Options dialog box (see Figure 5.1). To access the Options dialog box, choose Tools | Options. The error-handling options are listed here:


Figure 5.1. The Advanced tab of the Options dialog box.

The Break on All Errors option causes the development environment to switch from Run to Break mode whenever any error occurs—whether or not an error handler is active. This setup allows the programmer to identify the occurrence of errors even when the error handler is active. Break on All Errors can be especially useful for developing and debugging the error-handling routines.

The Break on Unhandled Errors option is most useful in later debugging and testing of an application, when the programmer is more confident of the error-handling routines and is more interested in unhandled errors.

The Break in OLE Server option is most useful when debugging OLE servers created in Visual Basic. The object application here is another instance of Visual Basic, in which the OLE server is running in the development environment's Run mode while a test client is being run in the first instance of Visual Basic. If an error condition in the client application occurs, the server application breaks at its current position.


Note

Visual Basic 4.0 can be run in multiple instances (see Figure 5.2); Visual Basic 3.0 and earlier can be run only in one instance.


Figure 5.2. Windows 95 with two instances of Visual Basic running.

Design Issues in Error Handling

The tools and mechanics of error handling are, unfortunately, just the tip of the iceberg. There are basically three types of error handling: Inline, Local, and Centralized. The following sections explore the techniques of these different types of error handling and some of the design issues that make one type more appropriate than another in particular situations.


Caution

The three stages of error handling (trapping, handling, and reporting) and the three types of error handling (inline, local, and centralized) are separate concepts. Any of the three types provide all the services of the three stages.

Inline Error Handling

Inline error handling disables the default error handling of Visual Basic and checks for errors after each line of error-prone code. This emulates the behavior of languages that do not raise exceptions like the C language. C was designed to give the programmer ultimate freedom (and consequently ultimate responsibility) for the code he or she writes. Therefore, C programmers have the ability to totally ignore most if not all of the error conditions that occur in the course of execution (at his or her own risk, I hasten to add). In C you must deliberately check for errors when you expect them to occur, which is to say that you handle them inline. In Visual Basic, inline error handling always begins with the On Error Resume Next construct, which causes Visual Basic to continue with the next line of code after an error occurs. There are a variety of strategies for processing errors in this way. Microsoft mentions three in the documentation for Visual Basic to which we add a fourth:

Each of these strategies is described in the following sections.

Returning Error Numbers from Functions

In this strategy, errors occurring when processing information in functions are returned as long integers or as variants from the function itself. The initiating procedure turns off error checking. The following code fragments illustrate this approach:

Sub DoSomethingImportant(strParameter as String)

   Dim vResult as variant

   On Error Resume Next

   vResult = MessAroundWithStrings(strParameter)

   If vResult <> 0 then 'An error occurred in the function

      ...Handle Errors...

   Else

      ...Continue Processing

   End If

   'You might include this line for completeness but it isn't required

   On Error Goto 0

End Sub

Function MessAroundWithStrings(strAString as String) as Variant

   ...Do processing...

   If Err <> 0 then

      MessAroundWithStrings = Err

   Else

      MessAroundWithStrings = 0

   End If

End Function

Note

Technically, you do not have to explicitly turn off error handling when you exit a sub or procedure that is controlling error handling. However, it is good technique to do so. If you develop the habit, you won't forget it when it is required.

Another technique that can help reduce errors is to treat the On Error... to On Error Goto 0 lines as a code block like Do...Loop or For...Next. You should indent the intervening lines to make the block more visually evident (see Figure 5.3).


Figure 5.3. The Visual Basic code window with a block of error-handling code.

Raising Visual Basic Errors in Functions and Handling Them in Calling Procedures

In this strategy, the root procedure sets error handling to a local or centralized error handler; called subs and functions use the Raise method of the Err object (preferred) or the Error statement to return an error state to the root procedure for handling. In the following code, note that the function MessAroundWithStrings uses the Raise method of the Err object to return error conditions to the calling sub (DoSomethingImportant). The same action could be accomplished by using the Error statement (a legacy tool) with the Err objects default property (Number) substituting the line

Err.Raise Err.Number

with the line

Error Err.

Sub DoSomethingImportant(strParameter as String)

   Dim vResult as String

   On Error Resume Goto ErrorHandler

   vResult = MessAroundWithStrings(strParameter)

   Continue processing

   'You might include this line for completeness but it isn't required

   On Error Goto 0

   Exit Sub

ErrorHandler:

   ...Handle Error

   'If successful

   Resume 'This will resume in the sub where the error occurred

   'If not

   ...Exit gracefully...

End Sub

Function MessAroundWithStrings(strAString as String) as String

   ...Do processing on strAString...

   If Err <> 0 then

      Err.Raise Err.Number

   Else

      MessAroundWithStrings = strAString

   End If

End Function

This approach may be the preferred one when a programmer uses programmer-defined errors as a means of communication between procedures or processes in the application. In this way, both system and programmer-defined errors can be handled with the same code.

Returning Variants of Type Error

In this approach to error handling, the root procedure passes a variant as a parameter to the called functions and procedures. If an error occurs, the type of the variant is set to type Error and the value is set to Err.Number. In the following code, we pass a separate variant parameter (vResult) the function. MessAroundWithStrings function stores the error number (0 if none) in this parameter. The calling function checks the variant type of vResult. If it is of type vbError, check the Err object for the current error information and handle the error.

Sub DoSomethingImportant(strParameter as String)

   Dim vResult as Variant

   Dim strResult as String

   On Error Resume Next

   strResult = MessAroundWithStrings(strParameter, vResult)

   If VarType(vResult) = vbError then 'An error occurred in the function

      ...Handle Errors...

   Else

      ...Continue Processing

   End If

   'You might include this line for completeness but it isn't required

   On Error Goto 0

End Sub

Function MessAroundWithStrings(strAString as String, varAResult as Variant) as _String

Dim strBuffer as String

strBuffer = strAString

   ...Do processing on strBuffer...

   If Err <> 0 then

      varAResult =  CVErr(Err.Number)

   Else

      MessAroundWithStrings = strBuffer

   End If

End Function

The variant parameter is another method that is useful for user-defined errors; you can set the value of the vResult parameter to a user-defined error number and set its type to vbError. Using variants of type vbError can be combined with the first strategy (returning the error value in the return parameter). A combined approach might look like the following code. Note that the function returns a variant instead of a string. In checking the return value, check first to see if it is of type vbError. Then handle the error or deal with the string information contained in the variant .

Sub DoSomethingImportant(strParameter as String)

   Dim vResult as variant

   On Error Resume Next

   vResult = MessAroundWithStrings(strParameter)

   If VarType(vResult) = vbError then 'An error occurred in the function

      ...Handle Errors...

   Else 'You can treat the variant as a string

      ...Continue Processing

   End If

   'You might include this line for completeness but it isn't required

   On Error Goto 0

End Sub

Function MessAroundWithStrings(strAString as String) as Variant

Dim strBuffer as String

StrBuffer = strAString

   ...Do processing on strBuffer...

   If Err <> 0 then

      MessAroundWithStrings = CVError(Err.Number)

   Else

      MessAroundWithStrings = CVar(strBuffer)

   End If

End Function

This is one of the uses of variants in which the overhead in memory and the loss of speed caused by using variants is probably worth the resulting simplicity and convenience of the code.

Anticipatory Error Checking

Of course, one approach to error handling (and probably the wisest approach) is to program in such a way as to identify or eliminate errors before they occur. One approach is to use this Assert() function. It is based on ASSERT macros from the C language. Here is the code for the Assert() function that I have developed and (like the Twilight Zone) offer for your consideration:

Function Assert (Condition As Boolean, Message As String,

                           Optional HelpFile as Variant, Optional Context as _Variant) as Boolean

    If Condition = False Then

#If DebugMode Then

       Dim Style, Title

       Style =  vbStop + vbOK

       Title = "ERROR MESSAGE"

        If IsMissing(HelpFile) or IsMissing(Context) then

             MsgBox Msg, Style, Title

        Else

             MsgBox Msg, Style, Title, HelpFile, Context

       Stop

#Else

       Dim fileName As String, fileNum As Integer

       Dim buf As String

       buf = Date$ & Chr$(9) & Time$ & Chr$(9) & Message

       fileName = App.Path & "\error.log"

       fileNum = FreeFile

      Open fileName For Append As #fileNum

            Print #fileNum, Date$, Time$, Message

            Close #fileNum

      End If

#End If

    Assert = Condition

End Sub

Note

The Assert() function uses some of the new features of Visual Basic 4.0:

The new variable type Boolean

Conditional compilation directives

Optional parameters

Visual Basic 4.0 offers a number of new variable types. Much of this is in response to the 32-bit capability of Visual Basic 4.0 and support for Unicode. In Visual Basic 3.0 and earlier, binary data was manipulated by using variables of type String. This works fine in an ANSI-based system in which characters are only one byte long. When Unicode support is added (Unicode needs two bytes per character), the manipulation of binary data no longer works correctly. Consequently, Visual Basic 4.0 adds a type Byte. You should start using Byte variables for binary data manipulation so that your code can be used across platforms.

Visual Basic now supports conditional compilation directives. These directives always begin with the # (number or pound) sign. Only two directives are supported:

#Const defines a compiler constant.

#If...Then #Else identifies separate blocks of code for selective compilation.

This conditional compilation feature has at least two major uses: It allows the programmer to compile debug and production executables from the same code. It also allows the programmer to use the same code between 16-bit and 32-bit versions (particularly useful when DLL or Windows API functions are used).

Now you can define optional parameters in your own functions just as they are defined in native Visual Basic functions. Optional parameters must be of type Variant. Consider the Format($) function in native Visual Basic. It takes a numerical expression and converts it to a variant (or string) based on an optional parameter of representing the desired format. In Visual Basic 4.0, you can design your own subs and functions with optional parameters. You do this with (logically enough) the Optional keyword. You can search online help for optional and IsMissing for further information on this technique.

The Assert() function requires a condition parameter and a string parameter for a custom message; it optionally accepts help file and context references. The function returns a Boolean based on the condition parameter. The function is set up so that it goes into Break mode in the Visual Basic IDE after showing an informative message box. In the production executable, the information is written to an error log (so that, if your program bombs on a client's computer, you have the information about errors written to disk so that you can fix the problem). The following code snippet shows how the Assert() function can anticipate errors:

If Not Assert(FileName <> "", "FileObject.FileRename:  FileName not initialized!") _Then

            'Get a valid FileName or exit gracefully

End If

If any attempt to open the file follows, the runtime error 76 occurs, Path not found. By checking for this condition, the error is avoided and the program can correct the condition.

Local Error Handling

Local error handling occurs in the procedure itself. The stubs of code discussed in the first part of this chapter on the basics of error handling are examples of localized error handling. Each procedure with error-prone activities has its own error-handling code. Each procedure can raise unanticipated errors, returning them step by step up the call chain for handling by calling procedures. Notice in the following example code how some error-handling code is local to the MessAroundWithStrings function. In the previous examples, the error-handling code was located completely in the calling function DoSomethingImportant.

Sub DoSomethingImportant(strParameter as String)

   Dim vResult as variant

   On Error Goto MyHandler

   vResult = MessAroundWithStrings(strParameter)

      ...Continue Processing

   'You might include this line for completeness but it isn't required

   On Error Goto 0

Exit Sub

MyHandler:...Handle Errors from this Sub and from the function it calls

End Sub

Function MessAroundWithStrings(strAString as String) as String

   Dim strBuffer as String

   On Error Goto SecondHandler

   StrBuffer = strAString

   ...Do processing on strBuffer...

   MessAroundWithStrings = strBuffer

   Exit Function

SecondHandler:

   Select Case Err.Number

      Case X

         ...Handle some errors but pass unhandled errors back to calling procedure:

      Case Else

         Err.Raise Number:=Err.Number

   End If

End Function

The Call Tree

The call tree is an important concept for error handling. Procedures can call other procedures, which in turn can call other procedures_ and so on, to several levels deep.

When a procedure enables an error handler, that error handler is in effect for all subsequent procedures that the root procedure calls—as well as for all procedures those procedures call in their turn.

Figure 5.4 displays a rudimentary (and useless) Visual Basic program that shows a series of nested subs and functions; it also shows the Calls dialog box launched by clicking the Calls button on the toolbar, by selecting Tools | Calls, or by pressing Ctrl+L. The Calls dialog box is available only in Break mode.


Figure 5.4. The Calls dialog box.

Localized error handling can invoke multiple error handlers in the same procedure, as shown in the following example:

Sub DoSomethingImportant(strParameter as String)

   On Error Goto StringHandler

   strParameter = MessAroundWithStrings(strParameter)

      ...Continue Processing

   On Error Goto FileHandler

   Open "Myfile.txt"for Output as #1

   ...Process File

   Close #1

   'You might include this line for completeness but it isn't required

   On Error Goto 0

Exit Sub

StringHandler:

   ...Handle string Errors

   Exit Sub

FileHandler:

   ...Handle file errors

End Sub

Centralized Error Handling

The final type of error handling is centralized error handling. Centralized error handling processes all errors through a single error-handling routine. Centralized error handling is difficult to implement in Visual Basic. Theoretically, if you invoke error handling from a Sub Main, you can then redirect all error handling to a centralized routine. However, this makes for a complicated and error-prone error-handling routine.

A more effective way of doing quasi-centralized error handling is to modularize code and have central error-handling code in code (.BAS), form (.FRM), or class (.CLS) modules based on the function and data of those modules. The new class modules of Visual Basic 4.0 present a great opportunity for object-oriented programming in Visual Basic.

One of the aspects of object-oriented programming is encapsulation. Encapsulation means isolating the data and processing in one module from all others—that is, creating a black box with clearly defined inputs and outputs. This approach allows you to develop and, more importantly, reuse error-handling code for specific types of processing.

Generating Programmer-Defined Errors

One useful strategy is to establish programmer-defined errors and then use the Visual Basic Err object and error-handling routines to trap and correct these errors. The documentation for Visual Basic 4.0 suggests that programmers define errors based on the vbObjectError offset. At press time, the specific offset of the constant has not been determined. If it is important for you to know the numerical value, you can find it by typing ? vbObjectError in the Debug window. You should use the constant rather than a hard-coded number to maintain forward compatibility in your code.

The documentation also requires user-defined errors to be in the range of 1 to 65,535. Because this range also includes errors reported from OLE controls you may be using in your application, check the error code ranges of these controls. Nonetheless, you should have a large range of open error codes.


Caution

Previous versions of Visual Basic have suggested that user-defined error numbers begin at 65,535 and work downward from there. This means that legacy code with programmer-defined error values must be reviewed for compatibility.

To avoid these problems in the future, define user-defined error messages as constants. Then you only have to edit one range or set of values to update your code. But you probably already do that, right?

Suppose that an application depends on a specific data file (such as an initialization file). When the application determines that the initialization file has been deleted, the code can define and raise an error. When the error handler encounters this error, it can write a default initialization file to disk or prompt the user with a Preferences dialog box to obtain initialization information.


Note

Windows 95 and Windows NT recommend that programmers use the system registry to record initialization information rather than using initialization files (*.INI).

Example A File Class

One thing I have come to hate is adding error-handling code to individual modules that perform file I/O. I also find it difficult to keep the syntax of file I/O forever straight in my head. When Visual Basic 4.0 offered the possibility of developing classes, I thought it was one area that would be very useful to me: developing class wrappers for frequently used code that can be plugged in to any project and accessed with the familiar metaphor of properties and methods. Because file and disk I/O is an especially error-prone activity, it helps to localize error handling for this activity in a single class module.

Ordinary and class modules have their own properties in Visual Basic 4.0. Figure 5.5 shows the Properties window for the FileClass class.


Figure 5.5. The Properties window for the FileClass module.

In this case, the FileClass object has properties of Instancing = 2 (Creatable Multiuse),Public = False, and Name = FileClass. This setup means that the objects of this class can be created and accessed only from within the project using the module. These objects can be created using Dim or GetObject, and there can be multiple instances of this object in use at the same time. Table 5.5 lists the properties and Table 5.6 lists the methods of the FileClass object.

Property (Data Type)


Description


Name (String)

Read/Write. This is the fully qualified path to a particular file.

Path (String)

Read only. This is the path segment of the filename.

Title (String)

Read only. This is the filename segment of the name.

Mode (Integer)

Read/Write. This is the mode for which the file is opened. The class supports Input, Output, Append, and Binary modes of file access.

Access (Integer)

Read/Write. This is the access restriction that you can optionally include in the Open syntax. The options include Read, Write, and ReadWrite.

Length (Long)

The number of bytes in the file.

DateTime (Variant)

Returns the date and time of the last revision of the file.

FileError (Long)

The last error returned within the file object.

Method (Returns)


Description


FileOpen()

Returns an integer that is the valid file number of the open file.

FileClose

Closes the file wrapped in the FileClass object.

FileMove strNewPath

Moves the object's file and resets the object to point at the new location for the file.

FileRename strNewName

Renames the object's file and resets the object to point at the new location.

FileDelete

Deletes the object's file from disk and sets a flag to remind the programmer (if necessary) that the file has been deleted.

FileCreate strNewFile

Creates a new null file, gives an overwrite warning, and resets the file object to point to the new file.

FileCopy strNewName[, varRegisterNew]

Copies the object's file to another location; optionally points the file object to the new instance of the file if the varRegisterNew parameter equals TRUE.

FileExists(strFileName)

Returns a Boolean indicating whether the specified file exists.

Declarations

The class module begins with the declarations shown in Listing 5.1.

Option Explicit

#If Win32 Then

    Private Declare Function GetWindowsDirectory Lib "kernel32"

        Alias "GetWindowsDirectoryA" (ByVal lpBuffer As String, _

        ByVal nSize As Long) As Long

#Else

    Private Declare Function GetWindowsDirectory Lib "Kernel" _

        (ByVal lpBuffer As String, ByVal nSize As Integer) As Integer

#End If

'Mode constants

Private Const MODE_APPEND = 0

Private Const MODE_BINARY = 1

Private Const MODE_INPUT = 2

Private Const MODE_OUTPUT = 3

'Access constants

Private Const ACCESS_READ = 0

Private Const ACCESS_WRITE = 1

Private Const ACCESS_READWRITE = 2

'File Object MyError Constants

Private Const FOBJ_ERROR_RESUME = 0

Private Const FOBJ_ERROR_RESUMENEXT = 1

Private Const FOBJ_ERROR_FILENAME = 2

Private Const FOBJ_ERROR_UNRECOVERABLE = 3

Private Const FOBJ_ERROR_UNRECOGNIZABLE = 4

'Constants for trappable file I/O errors

Private Const ErrOutOfMemory = 7

Private Const ErrBadFileNameOrNumber = 52

Private Const ErrFileNotFound = 53

Private Const ErrFileAlreadyOpen = 55

Private Const ErrDeviceIO = 57

Private Const ErrFileAlreadyExists = 58

Private Const ErrDiskFull = 61

Private Const ErrBadFileName = 64

Private Const ErrTooManyFiles = 67

Private Const ErrPermissionDenied = 68

Private Const ErrDiskNotReady = 71

Private Const ErrCantRename = 74

Private Const ErrPathFileAccessError = 75

Private Const ErrPathNotFound = 76

'Internal Property Variables

Private FilePath As String

Private FileTitle As String

Private FileName As String

Private FileMode As Integer

Private FileAccess As Integer

Private FileNumber As Integer

Private LastError As Long

'Flag variables

Private AmOpen As Boolean

Private AmDeleted As Boolean

This is pretty standard stuff: constants are defined to increase the readability and maintainability of the code. Two Visual Basic 4.0-specific features are used here: The first is the conditional compilation option; declarations are included for both the 16-bit and the 32-bit APIs. This way the module can be added to any project for either platform and compile correctly.

The second feature is the use of Public (new to Visual Basic 4.0 from VBA) instead of Global, and the deliberate use of Private variables accessed through Property methods.

Utility Subs and Functions

At the heart (not at the head) of the module are private utility functions used by the public methods (see Listing 5.2).

'**********************************************************

'

'    Private Utility Functions

'

'

'

'**********************************************************

Private Sub ProcessPathTitleAndName(newName As String)

   Dim BackSlash As Integer

   If InStr(newName, "\") Then

        BackSlash = RInstr(0, newName, "\")

        FilePath = Left$(newName, BackSlash - 1)

        FileTitle = Mid$(newName, BackSlash + 1)

    ElseIf InStr(newName, ":") Then

        Dim CurDrive As String

        Dim TargetDrive As String

        TargetDrive = Left$(newName, 1)

        CurDrive = CurDir$

        If Left$(CurDrive, 1) <> TargetDrive Then

            ChDrive TargetDrive

            FilePath = CurDir$

            ChDrive CurDrive

        Else

            FilePath = CurDir$

        End If

        FileTitle = Mid$(newName, InStr(newName, ":") + 1)

    Else

        FilePath = CurDir$

        FileTitle = newName

    End If

    FileName = FilePath & "\" & FileTitle

End Sub

'=======================================================

Private Sub DoFileCopy(Source As String, Target As String, _

        Optional Overwrite As Variant)

    Dim ErrorMsg As String, SourceNum As Integer, TargetNum As Integer

    Dim buffer As String, TheLength As Long

    ErrorMsg = "FileObject.DoFileCopy: Attempting "

    ErrorMsg = ErrorMsg & "copy/move operation on non-existent file!"

    If Assert(FileExists(Source), ErrorMsg) Then

        SourceNum = FreeFile: TargetNum = FreeFile

        On Error GoTo DoFileCopyError

            Open Source For Binary Access Read As SourceNum

            TheLength = LOF(SourceNum)

            Open Source For Binary Access Read As SourceNum

            Open Target For Binary Access Write As TargetNum

        On Error GoTo 0

        If TheLength < 60000 Then

            'Take the file in bits

            Do Until TheLength < 60000

                buffer = String$(0, 60000)

                Get SourceNum, , buffer

                Put TargetNum, , buffer

                TheLength = TheLength - Len(buffer)

            Loop

            buffer = String$(0, TheLength)

            Get SourceNum, , buffer

            Put TargetNum, , buffer

        Else

            buffer = String$(0, TheLength)

            Get #SourceNum, , buffer

            Put TargetNum, , buffer

        End If

        Close #SourceNum

        Close #TargetNum

    End If

    Exit Sub

DoFileCopyError:

    Dim action As Integer, ErrNumber As Integer

    action = Errors()

    Select Case action

        Case 0

            Resume

        Case 1

            Resume Next

        Case 2, 3

            Exit Sub

        Case Else

            ErrNumber = Err.Number

            Err.Raise ErrNumber

End Select

End Sub

'============================================================

Sub DeletedMsg()

    Dim msg, style

    msg = "You have deleted the file """ & FileName & "."""

    msg = msg & "  You must reinitialize the FileObject with a "

    msg = msg & "new valid file name before proceeding!"

    style = vbCritical + vbOKOnly

    MsgBox msg, style, App.Title

End Sub

'========================================================

Private Function OverwriteWarning(FileName As String) As Integer

    Dim msg As String, style As Integer

    msg = "The file, " & FileName & ", already exists in the current "

    msg = msg & "directory.  Overwrite it?"

    style = vbQuestion Or vbYesNo

    OverwriteWarning = MsgBox(msg, style, App.Title)

End Function

'=========================================================

Private Function RInstr(Start As Integer, Source As String, _

    Goal As String) As Integer

    Dim Index As Integer, N As Integer

    If Start <> 0 Then Index = Start Else Index = Len(Source)

    For N = Index To 1 Step -1

        If Mid$(Source, N, 1) = Goal Then

            RInstr = N

            Exit Function

        End If

    Next

    RInstr = 0

End Function

Centralized Error-Handling Function

The module uses the centralized error-handling function shown in Listing 5.3.

Private Function Errors() As Integer

    Dim MsgType As Integer, msg As String, response As Integer

    Dim NewFileNameNeeded As Boolean

    Dim DoResume As Boolean

    Dim DoResumeNext As Boolean

    'Return Value     Meaning     Return Value     Meaning

    '      0          Resume            2          Filename Error

    '      1          Resume Next       3          Unrecoverable Error

    '                                   4          Unrecognized Error

    MsgType = vbExclamation

    Select Case Err.Number

        Case ErrOutOfMemory '7

            msg = "The operating system reports that there is not "

            msg = msg & "enough memory to complete this operation.  "

            msg = msg & "You can try closing some other applications and then "

            msg = msg & "click Retry to try again or you can click Cancel to exit."

            MsgType = vbExclamation + vbRetryCancel

            DoResume = True

            'Resume or Exit

        Case ErrBadFileNameOrNumber, ErrBadFileName

            msg = "That file name is illegal!"

            NewFileNameNeeded = True

            DoResume = True

            'Resume

        Case ErrFileNotFound

            msg = "That file does not exist.  Create it?"

            MsgType = vbExclamation + vbOKCancel

            DoResumeNext = True

            'Resume Next

        Case ErrFileAlreadyOpen

            msg = "That file is already in use."

            MsgType = vbExclamation + vbRetryCancel

            NewFileNameNeeded = True

            'New Name

        Case ErrDeviceIO

            msg = "Internal disk error."

            MsgType = vbExclamation + vbRetryCancel

            DoResume = True

            'Resume

        Case ErrFileAlreadyExists

            msg = "A file with that name already exists.  "

            msg = msg & "Replace it?"

            MsgType = vbExclamation + vbOKCancel

            NewFileNameNeeded = True

            'New Name

        Case ErrDiskFull

            msg = "This disk is full.  Continue?"

            MsgType = vbExclamation + vbOKCancel

            DoResume = True

            'Resume

        Case ErrTooManyFiles

            msg = "The operating system reports that too "

            msg = msg & "many files are currently open.  You "

            msg = msg & "can try closing some other applications "

            msg = msg & "and then try again."

            MsgType = vbExclamation + vbRetryCancel

            DoResume = True

            'Resume

        Case ErrPermissionDenied

            msg = "You have tried to write to a file that is in "

            msg = msg & "use or is designated as read-only."

            NewFileNameNeeded = True

            'New Name

        Case ErrDiskNotReady

            msg = "Insert a disk in the drive and close the door."

            MsgType = vbExclamation + vbOKCancel

            DoResume = True

            'Resume

        Case ErrPathFileAccessError, ErrPathNotFound

            msg = "The operating system cannot locate this file on "

            msg = msg & "this path.  Check to make sure that the file "

            msg = msg & "name and path have been entered correctly "

            msg = msg & "and then try again."

            NewFileNameNeeded = True

        Case Else

            Errors = 4

            Exit Function

    End Select

    response = MsgBox(msg, MsgType, "File Error")

    Select Case response

        Case vbRetry, vbOK

            If NewFileNameNeeded Then

                LastError = FOBJ_ERROR_FILENAME

            ElseIf DoResume Then

                LastError = FOBJ_ERROR_RESUME

            ElseIf DoResumeNext Then

                LastError = FOBJ_ERROR_RESUMENEXT

            Else

                LastError = FOBJ_ERROR_UNRECOVERABLE

            End If

        Case Else

            LastError = FOBJ_ERROR_UNRECOGNIZABLE

    End Select

    Errors = LastError

End Function

The Errors() function is adapted from the example code for centralized error handling in the Visual Basic 4.0 Programmer's Guide. It is changed in a few regards: it relies on constants and is a little more readable. The return values are revised so that the function can instruct various calling procedures to try for a new filename if that is an easy solution for the error condition. The function also stores the handler's assessment to a variable called LastError.

Properties

The properties of the FileClass object are accessed with the Property methods shown in Listing 5.4.

'*****************************************************

'

'   Property Procedures

'      Path, Name, Mode, Access,

'      Length, DateTime,

'

'

'*****************************************************

Public Property Get Path() As String

    If AmDeleted Then

        DeletedMsg

        Exit Property

    End If

    Path = FilePath

End Property

'========================================================

Public Property Let Name(newName As String)

    If Not FileExists(FileName) Then

        Dim msg, style, answer

        msg = "The file, """ & newName & """ does not exist.  "

        msg = msg & "Create it?"

        style = vbQuestion Or vbYesNo

        answer = MsgBox(msg, style, App.Title)

        If answer = vbYes Then

            FileCreate newName

        Else

            Exit Property

        End If

    Else

        ProcessPathTitleAndName newName 'Checks for Drive, Directory, etc.

    End If

End Property

'==========================================================

Public Property Get Name() As String

    If AmDeleted Then

        DeletedMsg

        Exit Property

    End If

    Name = FileName

End Property

'==========================================================

Public Property Get Title() As String

    If AmDeleted Then

        DeletedMsg

        Exit Property

    End If

    Title = FileTitle

End Property

'===========================================================

Public Property Let Mode(NewMode As Integer)

    If AmDeleted Then

        DeletedMsg

        Exit Property

    End If

    If NewMode <> FileMode Then

        FileMode = NewMode

        If AmOpen Then

            Close #FileNumber

            FileOpen

        End If

    End If

End Property

'============================================================

Public Property Get Mode() As Integer

    If AmDeleted Then

        DeletedMsg

        Exit Property

    End If

    Mode = FileMode

End Property

'==============================================================

Public Property Let Access(NewAccess As Integer)

    If AmDeleted Then

        DeletedMsg

        Exit Property

    End If

    If NewAccess <> FileAccess Then

        FileAccess = NewAccess

        If AmOpen Then

            Close #FileNumber

            FileOpen

        End If

    End If

End Property

'===============================================================

Public Property Get Access() As Integer

    If AmDeleted Then

        DeletedMsg

        Exit Property

    End If

    Access = FileAccess

End Property

'================================================================

Public Property Get FileError() As Integer

    FileError = LastError

End Property

'================================================================

Public Property Get Length() As Long

    If AmDeleted Then

        DeletedMsg

        Exit Property

    End If

    Dim FileNum As Integer

    If Assert(FileName <> "", _

            "FileObject.Length:  FileName not initialized!") Then

        FileNum = FreeFile

        Open FileName For Binary Access Read As #FileNum

        Length = LOF(FileNum)

        Close FileNum

    End If

End Property

'===============================================================

Public Property Get DateTime() As Variant

    If AmDeleted Then

        DeletedMsg

        Exit Property

    End If

    If Not Assert(FileName <> "", _

            "FileObject.FileOpen:  FileName not initialized!") Then

        Exit Property

    End If

    If Assert(FileExists(FileName), _

            "FileObject.DateTime:  FileName not initialized!") Then

        DateTime = FileDateTime(FileName)

    End If

End Property

Note

Visual Basic Applications Edition had support for the new Property procedures—and now, so does Visual Basic 4.0. Property is now a keyword and represents a new class of procedures along with Sub and Function procedures.

Methods

Finally, there are the method subs and functions. Note that subs and functions become methods in a class module simply by being declared as Public (see Listing 5.5).

'**********************************************************

'

'    Methods

'

'      FileOpen, FileClose, FileMove, FileRename,

'      FileDelete and FileError

'

'**********************************************************

Public Function FileOpen() As Integer

    If AmDeleted Then

        DeletedMsg

        Exit Function

    End If

    If Not Assert(FileName <> "", _

            "FileObject.FileOpen:  FileName not initialized!") Then

        Exit Function

    End If

    If AmOpen Then Close #FileNumber

    Dim dummy As Variant

    FileNumber = FreeFile

    Select Case FileMode

        Case MODE_APPEND

            Select Case FileAccess

                Case ACCESS_READ

                    dummy = Assert(False, _

                        "FileObject.FileOpen:  " & _

                        "ReadOnly Access specified for Append action!")

                    AmOpen = False

                Case ACCESS_WRITE

                    On Error GoTo FileOpenError

                    Open FileName For Append Access Write As #FileNumber

                    AmOpen = True

                    FileOpen = FileNumber

                    On Error GoTo 0

                    Exit Function

                Case ACCESS_READWRITE

                    dummy = Assert(False, _

                        "FileObject.FileOpen:  " & _

                        "ReadWrite Access specified for Append action!")

                    AmOpen = False

                Case Else

            End Select

        Case MODE_BINARY

            Select Case FileAccess

                 Case ACCESS_READ

                    On Error GoTo FileOpenError

                    Open FileName For Binary Access Write As #FileNumber

                    AmOpen = True

                    FileOpen = FileNumber

                    On Error GoTo 0

                    Exit Function

                 Case ACCESS_WRITE

                    On Error GoTo FileOpenError

                    Open FileName For Binary Access Write As #FileNumber

                    AmOpen = True

                    FileOpen = FileNumber

                    On Error GoTo 0

                    Exit Function

                Case ACCESS_READWRITE

                    On Error GoTo FileOpenError

                    Open FileName For Binary Access Read Write As #FileNumber

                    AmOpen = True

                    FileOpen = FileNumber

                    On Error GoTo 0

                    Exit Function

                Case Else

            End Select

        Case MODE_INPUT

            Select Case FileAccess

                 Case ACCESS_READ

                    On Error GoTo FileOpenError

                    Open FileName For Input Access Read As #FileNumber

                    AmOpen = True

                    FileOpen = FileNumber

                    On Error GoTo 0

                    Exit Function

                 Case ACCESS_WRITE

                    dummy = Assert(False, _

                        "FileObject.FileOpen:  " & _

                        "Attempting Access Write with Input mode!")

                    Exit Function

                Case ACCESS_READWRITE

                    dummy = Assert(False, _

                        "FileObject.FileOpen:  " & _

                        "Attempting Access Read Write with Input mode!")

                    Exit Function

                Case Else

            End Select

        Case MODE_OUTPUT

            Select Case FileAccess

                 Case ACCESS_READ

                    dummy = Assert(False, _

                        "FileObject.FileOpen: " & _

                        "Attempting Access Read with Output mode!")

                    Exit Function

                 Case ACCESS_WRITE

                    On Error GoTo FileOpenError

                    Open FileName For Output Access Write As #FileNumber

                    AmOpen = True

                    FileOpen = FileNumber

                    On Error GoTo 0

                    Exit Function

                Case ACCESS_READWRITE

                    dummy = Assert(False, _

                        "FileObject.FileOpen:  " & _

                        "Attempting Access Read Write with Output mode!")

                    Exit Function

                Case Else

            End Select

        Case Else

            dummy = Assert(False, _

                "FileObject.FileOpen:  " & _

                "Incorrect File Mode parameter set!")

            Exit Function

    End Select

FileOpenError:

    Dim action As Integer, ErrNumber As Integer

    action = Errors()

    Select Case action

        Case 0

            Resume

        Case 1

            Resume Next

        Case 2, 3

            Exit Function

        Case Else

            ErrNumber = Err.Number

            Err.Raise ErrNumber

            Err.Clear

    End Select

End Function

'=========================================================

Public Sub FileClose()

    If AmDeleted Then

        DeletedMsg

        Exit Sub

    End If

    If Not Assert(FileName <> "", _

        "FileObject.FileOpen:  FileName not initialized!") Then

        Exit Sub

    End If

    If AmOpen Then

        Close #FileNumber

        FileNumber = 0

        AmOpen = False

    End If

End Sub

'========================================================

Public Sub FileMove(NewPath As String)

    If Not Assert(FileName <> "", _

        "FileObject.FileMove:  FileName not initialized!") Then

        Exit Sub

    End If

    'Check Drive Spec

    Dim newName As String, SourceNum As Integer, TargetNum As Integer

    If Right$(NewPath, 1) = "\" Then   'Get the path in shape

        newName = NewPath & FileTitle

    Else

        newName = NewPath & "\" & FileTitle

    End If

    If InStr(NewPath, ":") Then   'There is a drive spec included

        If Left$(newName, 1) <> Left$(FileName, 1) Then

            'Different drive, Name command won't work

            DoFileCopy FileName, newName

            Kill FileName

            ProcessPathTitleAndName newName

        End If

    Else

        On Error GoTo FileMoveError

        Name FileName As newName

        On Error GoTo 0

        ProcessPathTitleAndName newName

    End If

    Exit Sub

FileMoveError:

    Dim action As Integer, ErrNumber As Integer

    action = Errors()

    Select Case action

        Case 0

            Resume

        Case 1

            Resume Next

        Case 2, 3

            Exit Sub

        Case Else

            ErrNumber = Err.Number

            Err.Raise ErrNumber

            Err.Clear

    End Select

End Sub

'==============================================================

Public Sub FileRename(newName As String)

    If Not Assert(FileName <> "", _

        "FileObject.FileRename:  FileName not initialized!") Then

        Exit Sub

    End If

    On Error GoTo FileRenameError

    If InStr(newName, ":") Then  'there is a drive spec

        If Left$(newName, 1) <> Left$(FileName, 1) Then

            DoFileCopy FileName, newName

            Kill FileName

        Else

            Name FileName As newName

        End If

    Else

        Name FileName As newName

    End If

    On Error GoTo 0

    ProcessPathTitleAndName newName

FileRenameError:

    Dim action As Integer, ErrNumber As Integer

    action = Errors()

    Select Case action

        Case 0

            Resume

        Case 1

            Resume Next

        Case 2, 3

            Exit Sub

        Case Else

            ErrNumber = Err.Number

            Err.Raise ErrNumber

            Err.Clear

    End Select

End Sub

'===============================================================

Public Sub FileDelete()

    If Not Assert(FileName <> "", _

        "FileObject.FileOpen:  FileName not initialized!") Then

        Exit Sub

    End If

    If AmOpen Then Close #FileNumber

    If AmDeleted Then

        DeletedMsg

        Exit Sub

    End If

    Kill FileName

    AmDeleted = True

    FileNumber = 0

End Sub

'===================================================

Public Sub FileCreate(newName As String)

    Dim FileNum As Integer

    Dim choice As Integer

    If FileExists(newName) Then

        choice = OverwriteWarning(newName)

        If choice = vbNo Then Exit Sub

    End If

    FileNum = FreeFile

    Open newName For Output As #FileNum

    Close FileNum

    ProcessPathTitleAndName newName

End Sub

'===================================================

Public Sub FileCopy(newName As String, Optional RegisterNew As Variant)

    If Not Assert(FileName <> "", _

        "FileObject.FileOpen:  FileName not initialized!") Then

        Exit Sub

    End If

    DoFileCopy FileName, newName

    If Not IsMissing(RegisterNew) And RegisterNew = True Then

        ProcessPathTitleAndName newName

    End If

End Sub

Class Initialization and Termination Code

The functions shown in Listing 5.6 are called when an instance of type FileClass is created or destroyed.

'**********************************************************

'

'    Class Initialization and Destruction

'

'

'

'**********************************************************

Private Sub Class_Initialize()

    Dim nResult As Integer

    Dim buffer As String

    'Initializes the object to an ubiquitous file

    'This works in tandem with the inifile object

    'by setting things to point to WIN.INI

    FileTitle = "WIN.INI"

    buffer = String$(200, 0)

    nResult = GetWindowsDirectory(buffer, Len(buffer))

    FilePath = Left$(buffer, nResult)

    FileName = FilePath & "\" & FileTitle

    FileMode = MODE_BINARY

    FileAccess = ACCESS_READWRITE

End Sub

Private Sub Class_Terminate()

    If FileNumber <> 0 Then

        Close #FileNumber

    End If

End Sub

When a file object is first initialized, the default filename, mode, and access values are set. When the object is terminated (that is, when the object variable is Set equal to Nothing or when the object variable goes out of scope), if a file is open, that file is closed.

How To Use the FileClass Object

To use a FileClass object in your programs, you follow these basic steps:

  1. Add the FileClass.CLS file to your project.

  2. Add the Assert() function to a module in your project.

  3. Dim an object variable of type FileClass.

  4. Use the new keyword in the dim statement or use the GetObject() function to create an instance of FileClass.

After these steps are completed, you can address the FileClass object in your code with a sequence like the following, which opens an initialization file and populates an array with all the section names in the file:

With myFile

        .Access = ACCESS_READ

        .Mode = MODE_INPUT

    End With

    FileNum = myFile.FileOpen()

    'Clear and refill the Sections array

    Erase mySections

    counter = 0

    Do

        Line Input #FileNum, buf

        If Len(buf) <> 0 Then

            If Left$(buf, 1) = "[" Then ' it's a section name

                ReDim Preserve mySections(counter + 1)

                Index = InStr(2, buf, "]") - 2

                mySections(counter) = Mid$(buf, 2, Index)

                counter = counter + 1

            End If

        End If

    Loop Until EOF(FileNum)

    myFile.FileClose

Public Constant Declarations

To take full advantage of the module, you must include the following declarations in a form or module of your program:

'Mode constants

Public Const MODE_APPEND = 0

Public Const MODE_BINARY = 1

Public Const MODE_INPUT = 2

Public Const MODE_OUTPUT = 3

'Access constants

Public Const ACCESS_READ = 0

Public Const ACCESS_WRITE = 1

Public Const ACCESS_READWRITE = 2

'File Object MyError Constants

Public Const FOBJ_ERROR_RESUME = 0

Public Const FOBJ_ERROR_RESUMENEXT = 1

Public Const FOBJ_ERROR_FILENAME = 2

Public Const FOBJ_ERROR_UNRECOVERABLE = 3

Public Const FOBJ_ERROR_UNRECOGNIZABLE = 4

This inconvenience is necessary because class modules in Visual Basic 4.0 cannot contain public constant declarations; to use constants, you have to declare them elsewhere in your application.

Summary

Error handling is an important aspect of professional-quality programming. It protects the users of your software from the mystifying disappearance of the program and from the frustrating loss of data. The basic mechanisms of error handling in Visual Basic 4.0 are similar to earlier versions and other flavors of the Basic language. Visual Basic 4.0 gives richer and finer control of error reporting through the Err object, the Error object, and Errors collection for data access and with new programming environment options. Finally, design issues like the types of errors anticipated and the modular design of the application determine which pattern of error handling (Inline, Local, or Centralized) is best for a particular situation.

Previous Page TOC Next Page