In last month's tip I complained about poor error checking in LotusScript code. I also promised to provide some...
details about how to write proper error handling routines. So I'll start this tip with an overview of the theory and then present an example that puts the theory into practice.
There are two kinds of errors in LotusScript: compile-time errors and run-time errors. Compile-time errors are easy to deal with, because the LotusScript programming interface does most of the work for you. You cannot successfully compile a script routine that contains compile-time errors. The programming interface flags some errors in red before you even try to compile them, and then moves your cursor to other errors after compilation.
Run-time errors are harder to find and fix, because there are no built-in tools to take you to them. You have to do the work of writing good code that finds and reports the errors in a meaningful way.
The basic idea with run-time errors is that, when an error occurs, the script interpreter looks for an error handler that applies to this type of error. If no such error handler is found, the interpreter looks for an applicable error handler in the calling routine, then the calling routine above that, and so on. If no error handler at all is found, LotusScript stops processing and exits completely, printing the relevant error message (if any) for the user.
Within the error handlers that you write, LotusScript provides some helpful functions so you can track error messages, error codes and the locations of errors within your script. All of these concepts are illustrated in the following example:
1. Const NAME_VIEW = "AllByName" 2. Const SUMMARY_FIELD = "Summary" 3. Const SEARCH_STRING = "Tim Lewis" 4. Const SECRET_CODE = "The string we are looking for." 5. Const GENERAL_ERROR = 1001 6. Const SPECIAL_ERROR = 1002 7. 8. Dim Sess As NotesSession 9. Dim ThisDb As NotesDatabase 10. Dim NameView As NotesView 11. Dim Doc As NotesDocument 12. Dim Summary As String 13. 14. On Error Goto ErrorReturn 15. On Error SPECIAL_ERROR Goto SpecialErrorHandler 16. 17. Set Sess = New NotesSession 18. Set ThisDb = Sess.CurrentDatabase 19. 20. Set NameView = ThisDb.GetView (NAME_VIEW) 21. If NameView Is Nothing Then Error GENERAL_ERROR, "Cannot open view named " + NAME_VIEW 22. 23. Set Doc = NameView.GetDocumentByKey (SEARCH_STRING) 24. If Doc Is Nothing Then Error GENERAL_ERROR, "Cannot find the name " + SEARCH_STRING 25. 26. Summary = Doc.GetItemValue (SUMMARY_FIELD)(0) 27. Summary = Trim$(Summary) 28. If Summary = "" Then Error GENERAL_ERROR, "Summary empty for " + SEARCH_STRING 29. 30. If Summary = SECRET_CODE Then Error SPECIAL_ERROR 'error text is optional 31. 32. Msgbox Summary 33. 34. NormalReturn: 35. Exit Sub 36. 37. ErrorReturn: 38. Msgbox "Problem while running this code." 39. Msgbox "Error number is " + Cstr(Err) + ".", MB_OK + MB_ICONSTOP, "ERROR" 40. Msgbox "Error message is: " + Error$, MB_OK + MB_ICONSTOP, "ERROR" 41. Msgbox "Near line number " + Cstr(Erl) + ".", MB_OK + MB_ICONSTOP, "ERROR" 42. Resume ErrorReturn2 43. ErrorReturn2: 44. Exit Sub 45. 46. SpecialErrorHandler: 47. Msgbox "Found the secret code.", MB_OK + MB_ICONEXCLAMATION, "FOUND IT" 48. Resume Next
Line 14 sets up a general error handler (defined at line 37), which will be used for all run-time errors in this script, with one exception. Line 15 creates a more narrow error handler (defined at line 46), which will be used only for error code 1002. It is important that the specific error handler is defined after the general error handler, or the general handler will take precedence.
Error handlers can be invoked in two ways -- either automatically by LotusScript when it encounters a run-time error, or manually by the programmer at any time. An example of an automatic error is when LotusScript tries to open a file that does not exist. That is a hard run-time error and LotusScript will invoke the currently defined error handler to deal with the problem.
A manual invocation of an error handler is shown at line 21. LotusScript does not consider a missing view to be an automatic error. But the programmer has decided that it is unacceptable for this view to be missing from this database. So line 21 raises a run-time error manually, even though LotusScript would be happy to continue processing (at least for a while.)
Now let's look at the error handling routines at lines 37 and 46.
Line 39 reports the current error number, which is returned by the built-in function Err. Line 40 reports the error message associated with the current error code, using the built-in function Error$. And line 41 reports the location where the error occurred, using the function Erl. Lines 42 and 43 seem superfluous, but they perform an important operation. When LotusScript is handling an error, the error is not considered "handled" until a Resume statement is executed. So line 42 tells LotusScript to continue normal processing at line 43.
The block of code between lines 46 and 48 is used only for error code 1002. This is a user-defined error code so it will never occur automatically. (Error numbers 1000 to 1999 are reserved for user-defined codes.) Notice that this error handler differs in a key way from the previous one. After reporting some information to the user (line 47), the error handler returns processing back into the body of the code. The Resume Next statement (line 48) tells LotusScript that the error is "handled" and to continue program execution at the statement following the statement that caused the error.
The use of general-purpose and special error handlers, such as those shown here, will make an enormous difference in the quality of your LotusScript programming. Instead of mysterious run-time crashes for unknown reasons, you will have accurate reporting of what is going on in your program. Error handlers also prevent destructive bugs, when LotusScript vainly tries to continue processing after an unacceptable condition has occurred, such as a missing database, view, or document.
For further information see Domino R6 Designer Help / Contents / Lotuscript Language / Error Processing.
About the author: Chuck Connell is president of CHC-3 Consulting, which helps organizations with all aspects of Domino and Notes.
Do you have comments on this tip? Let us know.
Please let others know how useful it is via the rating scale below. Do you have a useful Notes/Domino tip or code to share? Submit it to our monthly tip contest and you could win a prize and a spot in our Hall of Fame.