Minimal error handling – UI time

Field validation formulas can quickly become very annoying for the user, because they pop up a new messagebox at each document refresh. To overcome this, you can prefix them with a line like: @If( @IsDocBeingSaved; "Continue"; @Return( @Success ) );.

A problem arises if you need a QuerySave event script for full blown validation. In fact Notes executes field validation formulas after the QuerySave event script has completed. If the QuerySave validation fails, usually you notify the user with a messagebox [1st]. After the user presses OK, Notes resumes from the field validation formulas. If one of them fails, a new messagebox [2nd] for the error will be displayed.

To overcome this redundancy, you can prefix the validation code in the QuerySave event script with a line like this: Call Source.Refresh. This will force Notes to execute field validation formulas before any other validation code. But the execution of the field validation formulas is prevented by the @IsDocBeingSaved test. So you remove it and try.

Now, if a field validation fails, Notes displays a messagebox [1st] with the message in the @Failure clause of the validation formula. After the user presses OK, Notes displays a messagebox [2nd] for the error lsERR_LSXUI_NOTES_ERROR. After the user presses OK, maybe your code displays a messagebox [3rd] with any other error. After the user presses OK, Notes executes the field validation formulas again, and the same one of them fails for the second time in a row, so a new messagebox [4th] for that error will be displayed.

To overcome this squared redundancy, you can catch the error 4412 thrown by Notes and end the execution there, by setting Continue = False and calling End afterwards. This will cause only the first messagebox to pop up and it certainly works, but having removed the @IsDocBeingSaved test, field validation formulas still pop up a new messagebox at each document refresh.

To overcome this, you can use a special item for tracking the current event down. You set the $_CurrentEvent item in the current underlying document upon entering the QuerySave event and remove it upon exiting. Finally you replace the @IsDocBeingSaved test with the following one: $_CurrentEvent = "QUERYSAVE".

This works pretty well!

Usage

Sub Querysave(Source As Notesuidocument, Continue As Variant)
%INCLUDE "error_handling_ui"

    ' 1st: execute field validation formulas
    Call Source.Refresh

    ' 2nd: validate whatever else
    Call Validate( Source ) 

    ' 3rd: do whatever else
    Call Process( Source )

    ' 4th: maybe you also need to save and reload
    Call Source.Document.Save( True, True, True )
    Call Source.Reload
End Sub

Sub Validate( Source As NotesUIDocument )
%INCLUDE "error_handling"

    'just throw any needed Error
End Sub

Sub Process( Source As NotesUIDocument )
%INCLUDE "error_handling"

    'do something here
End Sub

Call this file error_handling_ui.lss and store it in the notes folder

' $_CurrentEvent can be used for executing validation formulas only on QuerySave
    ' NOTE: there's no need for having an explicit $_CurrentEvent field on the form
    ' Field validation formulas can be prepended with something like
    '   @If( $_CurrentEvent = "QUERYSAVE"; "Continue"; @Return( @Success ) );

    Call Source.Document.ReplaceItemValue( "$_CurrentEvent", Getthreadinfo( 1 ) )
    Source.Document.GetFirstItem( "$_CurrentEvent" ).SaveToDisk = False
    On Error Goto HandleError
    Goto EnterProc

HandleError:
    If Err <> 4412 Then ' any other error than "field didn't pass validation formula"
        Msgbox Getthreadinfo( 1 ) & " : " & Erl & Chr$( 10 ) & Error$, 16, "Error " & Err
    End If
    Continue = False
    End

EnterProc:

Minimal error handling

This minimal error handling suite does very little, but it’s also very useful: any error is caught, context info is appended and the error is thrown again. To simplify and clarify all the code, the suite must be included in a LotusScript file at the very top of each Sub or Function.

Usage

Sub Initialize
%INCLUDE "error_handling"

    Dim args As Variant

    args = "RAPUTA"

    Call Outer( args )

End Sub

Call this file error_handling.lss and store it in the notes folder

'catch any error & throws it again, decorated
	On Error Goto HandleError
	Goto EnterProc  
HandleError:     
	Error Err, Getthreadinfo( 1 ) & " : " & Erl & Chr$( 10 ) & Error$ 
EnterProc: