There are literally hundreds of different errors that can occur while a procedure is running. Of course you’ll want to eliminate all of the errors in the procedure itself, but many errors are the result of circumstances beyond the programmer’s control. A file can fail to open because it was placed into the wrong folder, the user can enter the wrong data type into a formula, the list is endless. When such an error occurs, Panorama’s normal response is to display an error message and stop the procedure immediately. (In addition, if the procedure window is open, Panorama will attempt to highlight the statement which triggered the error.)

If you want to create a database that operates professionally, simply stopping the procedure half finished if there is an error may not be acceptable. Instead, you may want your procedure itself to trap the error and try to correct it, if possible. At a minimum, you may be able to display an error message that is more relevant to an untrained operator than Panorama’s general purpose error messages.

Panorama has several technique for trapping errors, allowing you to “channel” the error in the direction you want it to go. The sections below describe each of these techniques. When you use these techniques to trap errors Panorama has several functions that can be used to get information about the error that just occurred. To learn more about these functions see info(“error”), info(“errorstatement”), info(“errorparameter”), info(“errorstack”), and info(“executeerrorsource”).

IF ERROR

To trap errors in a particular statement, use the if error statement (two words - there must be a space). This statement must be placed immediately after the statement that you are worried might cause an error. For example, suppose you have a procedure that appends a file with the openfile statement. If the file is missing or has been moved an error will occur. This example checks for that error, and if the error occurs, asks the user to enter a new file name. The procedure will keep trying until the file is opened successfully or the user gives up and enters an empty name.

local txFileName
txFileName="New Transactions"
loop
    openfile "+"+txFileName
    if error
        gettext "Enter the file name",txFileName
        repeatloopif txFileName<>""
    endif
endloop
if txFileName="" stop endif
/* further processing of the new transactions, below */

If error must be used by itself, you cannot combine error with other conditions. For example, the statement:

if error and info("modifiers") contains "shift" /* WILL NOT WORK !! */

will NOT work. To get this effect you must nest a second if statement inside the if error, like this.

if error
    if info("modifiers") contains "shift"
        ...
    endif
endif

TRY / CATCH

To trap errors in a sequence of statements use the try, catch and endcatch statements. These statements are used together like this:

try
    ...
    ...
    ... one or more statements that may contain errors
    ...
    ...
catch
    ...
    ... statements to handle error
    ...
endcatch
...
... rest of program
...

After encountering the try statement, Panorama starts executing the statements that follow. If no errors occur in any of the statements, Panorama will jump from the catch to the first statement after the endcatch statement. But if there is an error in any of these statements, Panorama will jump immediately to the code just after catch statement. It will execute all of those statements, then continue with the statements after the endcatch statement. (Of course you can put a return or stop statement in between the catch and endcatch statements if you don’t want to continue.) This code can use the info(“error”) function if it needs to know what the error was that was trapped.

If the statements between try and catch include a call or execute statement (or any of the variations of these statements) then errors that occur within the subroutine (or even more deeply nested subroutines) will also trapped to the catch statement. If an error occurs within a subroutine Panorama will unwind any nested subroutines until it gets back to the procedure with the catch statement, then it will execute the statements after the catch statement.

Here is an example.

try
    execute {Name="Jon"}
catch
    growlmessage "Could not set Name"
endcatch

If there is a field or global variable named Name, all is well. But if there isn’t, a growl notification will appear, then the program will continue. This is a bit contrived because there is really no reason for the execute statement here, but it illustrates that try/catch will catch errors within subroutines.

If you need to, you can nest try/catch statements inside each other. If an error occurs, the closest catch statement will handle it. Remember, however, that that catch statement could be in a subroutine that you cannot see at the moment (this would mean that you also cannot see the code that generated the error).

Note: You can use endtry instead of endcatch at the end of a try/catch block – both have exactly the same meaning.

ON ERROR

The onerror statement can be used to catch all errors that are not trapped by if error statements. This has two benefits: 1) It allows the programmer to easily eliminate all error alert dialogs. This is very important for server applications because an alert dialog requires human intervention to get the server going again. 2) It makes it easy to build a log of errors. To learn more about this see the onerror statement.

THROWERROR

Sometimes you may want to generate an error yourself that can then be handled by catch or onerror. This can be done with the throwerror statement. In this example, any errors that happen between the try and catch statements will automatically be logged (assuming that you have a procedure called logtheerror that does this). But this will also happen if the account balance is negative.

try
    ...
    ...
    if accountBalance<0
        throwerror "Error -- negative account balance"
    endif
    ...
    ...
catch
    call logtheerror,info("error")
endcatch
...
... continue here even if there is an error
...

You can also use this to give an error condition a more descriptive message, without having to write duplicate error handling code for every error you want to customize.

try
    ...
    ...
    data = fileload("logfile"+datepattern(today(),"YYYYMMDD")+".log"
    if error
        throwerror "Today's log file is missing."
    endif
    ...
    ...
catch
    call logtheerror,info("error")
endcatch
...
... continue here even if there is an error
...

Note: In a formula, you can generate an error with the error( function.


See Also


History

VersionStatusNotes
10.0UpdatedCarried over from Panorama 6.0 but now includes the try/catch method for handling procedure errors.