Validating a Notes formula from LotusScript
This code can be used to validate a Notes formula before using it in an Evaluate() statement or in a call to db.Search(). It will also tell you the offset of any error.
View member feedback to this tip.
This code can be used to validate a Notes formula before using it in an Evaluate() statement or in a call to db.Search(). It will also tell you the offset of any error. I use it in a Web interface to create customized reports to mimic Domino Designer's "Check formula" functionality. It uses functions in the Notes DLL, as documented in the Lotus C API, example code support Win32 (look here for help on using the same code on another platform).
Here's an example:
Dim sFormula as String sFormula = {SELECT FORM = "MyForm" & @IsAvailable(Status_T)} iRC = CheckSelectionFormulaValid (sFormula) if iRC(0) = NO_ERROR Then Print "Formula is valid!" Else Print "Formula error: " & GetAPIError(iRC(0)) Print "Error starts at character: " & Cstr(iRC(1)) & " and ends at character: " & Cstr(iRC(2)) End If
Removing the "@" from the @IsAvailable keyword should give you those results:
Formula error: @Function or operator expected, or @Function does not require an argument. Error starts at character 47 and ends at character 47, which is the last parentheses.
Const NULLHANDLE = 0 Const NO_ERROR = 0 Const ERR_FORMULA_COMPILATION = &h500 + 1 Declare Function NSFFormulaCompile Lib "nnotes.dll" ( _ Byval FormulaName As Long, _ Byval FormulaNameLength As Integer, _ Byval FormulaText As Lmbcs String, _ Byval FormulaTextLength As Integer, _ rethFormula As Long, _ retFormulaLength As Integer, _ retCompileError As Integer, _ retCompileErrorLine As Integer, _ retCompileErrorColumn As Integer, _ retCompileErrorOffset As Integer, _ retCompileErrorLength As Integer _ ) As Integer Declare Sub OSMemFree Lib "nnotes.dll" (Byval hHandle As Long) Declare Function OSLoadString Lib "nnotes.dll" ( _ Byval hmodule As Long, _ Byval status As Integer, _ Byval s As String, _ Byval slen As Integer _ ) As Integer ' ============================= =============================== ==================== ' CheckSelectionFormulaValid - This function uses the Lotus C API to check the syntax of a Notes formula. ' ' Return Value: Variant - A 3 elements array containing: ' Index 0 - The compilation error code or NO_ERROR (0) if valid ' Index 1 - The compilation error offset in formula or NO_ERROR if valid ' Index 2 - The compilation error length or NO_ERROR if valid ' ' Note: The compilation error code at Index 0 can then be passed to GetAPIError () to get more info about the error. ' ============================= ============================== ===================== Function CheckSelectionFormulaValid (sFormula) As Variant Dim iError As Integer Dim hFormula As Long Dim wFormulaLen As Integer Dim iCompileError As Integer Dim iCompileErrorLine As Integer Dim iCompileErrorColumn As Integer Dim iCompileErrorOffset As Integer Dim iCompileErrorLength As Integer Dim iArray(2) As Integer iError = NSFFormulaCompile(0, 0, _ sFormula, _ Len(sFormula), _ hFormula, _ wFormulaLen, _ iCompileError, _ iCompileErrorLine, _ iCompileErrorColumn, _ iCompileErrorOffset, _ iCompileErrorLength) If hFormula <> NULLHANDLE Then Call OSMemFree(hFormula) End If If iError = ERR_FORMULA_COMPILATION Then iArray(0) = iCompileError iArray(1) = iCompileErrorOffset iArray(2) = iCompileErrorLength CheckSelectionFormulaValid = iArray Else iArray(0) = NO_ERROR iArray(1) = NO_ERROR iArray(2) = NO_ERROR CheckSelectionFormulaValid = iArray End If End Function ' =============================== ================================ ================= ' GetAPIError - This function uses the Lotus C API to return a Notes error's text message. ' ' Return Value: String - The text associated with the Notes API error code. ' ================================ ================================= =============== Function GetAPIError(iErrorCode As Integer) As String Dim iRetVal As Integer Dim sError As String * 1024 sError = String(1024, 0) iRetVal = OSLoadString(0&, iErrorCode, sError, 1023) If iRetval <> 0 Then GetApiError = Left$(sError, iRetVal) End If End Function
I think this is a great tip! The writer suggested using it prior to any Evaluate() call. I suggest using it to debug any @Formulas you are working with during routine development.
I created a simple form that I put in my utilities database and will use it all the time. The form has one field and one action button. Put something like this in the button:
Sub Click( Source As Button ) Dim ws As New NotesUIWorkspace Dim uiDoc As NotesUIDocument Set uiDoc = ws.CurrentDocument iRC = CheckSelectionFormulaValid ( uiDoc.FieldGetText("testFormula" ) ) If iRC(0) = NO_ERROR Then Msgbox "Formula is valid!" Else Print "Formula error: " & GetAPIError(iRC(0)) Print "Error starts at character: " & Cstr(iRC(1)) & " and ends at character: " & Cstr(iRC(2)) Msgbox "Error starts at character: " & Cstr(iRC(1)) & " and ends at character: " & Cstr(iRC(2)), , _ "Formula error: " & GetAPIError(iRC(0)) End If End Sub
You may also want to check out another tip, called Formula debugger. It's very similar to the tip listed above.
—Doug J.
Do you have comments on this tip? Let us know.
This tip was submitted to the SearchDomino.com tip exchange by member Christian Cloutier. 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.