Each formula is composed of statements that take actions or evaluate to a result. The @Commands generally take an action, although a few return a result. Most formulas must evaluate to a main expression or a result, regardless of the side effects. For example, the following formula for a default value of the cSubject field generates an error: "No main or selection expression in formula."
jcSubject := "Formula Syntax"
This is because there is no main expression. The formula simply assigns a value to a temporary variable. You can, however, use a text constant. A text constant is always enclosed in quotes. For example, "Formula Syntax" could be placed in the default value event, which would then be assigned to the field when a document is created. You can also write the following formula, storing the value "Formula Syntax" to a variable, and use the variable as the last statement:
jcSubject := "Formula Syntax"; jcSubject
Fields on a form evaluate from left to right and top to bottom. Similarly, formulas always evaluate from left to right and from top to bottom. The only exceptions to the order of execution are @Commands and @PostedCommand s. (This was discussed earlier in this chapter in the section titled "Overview of the Formula Language.") Formulas can contain constants, fields, keywords, operators, @Functions, @Commands, and variables .
Working with Constants
A constant is a value that can be assigned during the execution of a formula. There are three types of constants: numeric, text, and time-date. Text constants are enclosed in quotes or curly braces, numeric constants are simply entered, and time-date constants are enclosed in square brackets. A list can also be a constant. (You can read more about lists in the section "Working with Lists," later in this chapter.) The following list shows how each type of constant can be assigned to a field or variable:
nNumber := 10.34 cText := "This is a text constant" cTextList := "Red" : "Yellow" : "Green" dDate := [08/09/98] dDateTime := [08/09/98 11:30 PM]
Operators typically assign or modify values of variables or fields. A full listing of operators is available in a Domino Designer Help document titled "Operator and Precedence." You can quickly locate this in the Designer Help Search view by typing in the first few letters of the first word. Domino Help then moves to the document. There are six basic types of operators: arithmetic, assignment, comparison (equality), list subscripting and concatenation, logical, and unary (positive or negative). Some of these operators are fairly easy to understand; others require more explanation.
Arithmetic operators are just what you expect ”they perform mathematical functions. These operators are the commonly used signs + , - , * , / , and so on. You can use these functions to perform permuted operations against lists. You can change the sign of a numeric variable with the + or the - sign.
Comparison operators determine how two values equate to each other. For example, = , > , < , <> , and != are all comparison operators. Note that the equal sign ( = ) does not assign a value ”it equates two values. When a comparison operator is used, the return value is a logical value. Because Notes does not have a logical variable type ( unfortunately ) in the Formula language, numeric 1 is true and is false .
The assignment operator, := , assigns values to a variable or a field. A variable is limited in scope to the currently executing formula. Even if there are several fields in a form and an event in all the fields has a formula that uses the same variable name, the value of the variable remains with the formula in which it resides ”changing it in one field does not affect the value of the variable in another. This is important to understand because in some ways it is quite different from other programming languages. You can use a variable with the same name as a field, and if the field has a value, the variable has the same value. You can then modify the value of the variable in the formula. Unless you explicitly save the value using the FIELD keyword or @SetField() , the value of the variable is discarded when the formula completes execution, even though it has the same name as a field. Because the scope of variables is so limited, you should consider developing and using a naming convention. Using j (for "junk" because it is discarded) as the first letter of a variable is one such convention. Consider Listing 12.5.
Listing 12.5 Assigning Field Values from an Action Button
REM "Look up the departments in the HR database" ; REM "The HR database replica ID is stored in the Profile" ; jcHRLookupID := @GetProfileField("GP"; "cHRLookupID"); jcDeptList := @DbColumn( ""; jcHRLookupID ; "LUDEPT";1) ; REM "should add an error trap here..." ; jcDept := @Prompt([OKCANCELLIST]; "Departments" ; "Choose a department" ; "" ; jcDeptList ) ; @If(jcDept = ""; @Return(""); @Success) ; REM "The Department code and description"; REM "are concatenated into a single view column" ; jcDepartment := @Right(jcDept; " ") ; REM "The Department code should be the first"; REM "four characters plus 00" ; jcDeptCode := @Left(jcDept; 4) + "00"; REM "By prefacing the variable name with the letter j" ; REM "it makes it very easy to use @SetField"; @SetField("cDepartment"; jcDepartment) ; @SetField("cDeptCode"; jcDeptCode);
Using j plus the name of the field ”jcDepartment, for example ”makes it very easy to read and maintain your code. Using @SetField() is very straightforward because the field name is prominent in the variable.
Lists are concatenated using the colon . In the following example, three lists are created: cTextList , nNumList , and dDateList .
cTextList := "Item One" : " Item Two" : " Item Three"; nNumList := 1 : 2 : 3 ; dDateList := [08/09/98] : @Today : [08/10/98];
New in Designer 6 is the subscript operator,  , or two square braces. You can retrieve the value stored in an element of a list by including the element number within the square braces. The following formula returns the third item in cTextList :
cTextList := "Item One" : " Item Two" : " Item Three"; cElement3 := cTextList
There are three logical operators: AND , NOT , and OR . AND is represented by the ampersand, & ; NOT is represented by the exclamation point, ! ; OR is represented by the pipe, .
Unary operators are the plus sign and the minus sign. These change the sign of a number. By default, all numbers are positive, unless otherwise specified.
All operators can be combined in the same formula under the right circumstances.
Many of the syntax rules for the Formula language are similar to those in other programming languages. They are fairly easy to learn, especially because errors are flagged by the syntax checker. Formatting formulas, using semicolons, using case, and changing the precedence through the use of parentheses are all discussed in the next several sections.
Minimal formatting rules govern formulas. In Release 3, if you added spaces and line feeds in the Formula window, when you saved the object containing the formula, all the formatting disappeared. This made reading and debugging complex formulas extremely frustrating and difficult. In Release 4, whitespace was allowed in formulas. This meant that you could add line feeds, blank lines, indented lines, and spaces. This made formulas easier to read and maintain. You can also change the font used in the Script area with no effect on the code.
A space is required only in one condition ”after a keyword such as FIELD . For example, FIELDcText is not correct, but FIELD cText is. Although this point might seem rather obvious, it needs to be mentioned because spaces aren't required elsewhere. Consider the following formula, which contains no spaces except the one after the keyword and those in the text values:
FIELD cText:="This is some text created on"+@Today+" by "+ @Name([CN];@UserName);
Despite the preceding note, by convention, operators have spaces before and after them to make the formula easier to read.
Perhaps one of the most important rules is that each statement in a formula must be separated with the line-continuation character, the semicolon. If you look at any one of the formulas in this chapter, you see that rule in effect. If you fail to use a semicolon at the end of any statement except the last, you will receive an error message and will not be able to save the formula.
All arguments within @Functions and @Commands are separated by semicolons. In the following example, @SetField("cDeptCode"; jcDeptCode) , the semicolon separates the first argument, the name of the field, from the second argument, the variable containing its value. In many other languages, LotusScript and Java included, the comma is used as an argument separator. If you are new to Domino applications development, this might take some getting used to.
For the most part, formulas are not case sensitive. Text constants are, of course, case sensitive because TEXT is not the same as text or Text . Some conventions are in widespread use also. In particular, keywords are always entered in upper case. For example, you will see REM but not Rem or rem , and FIELD but not Field . On the other hand, @Functions are usually entered in mixed case, as are variable names . You are probably aware that it is easier to read mixed case than all uppercase or all lowercase words. So, @SetField ”or, as an even better example, @DocumentUniqueID ”are much easier to read than @SETFIELD or @documentuniqueid . Particularly in the last example, all the lowercase letters seem to flow together. Arguments specified for @Commands are also entered in mixed case. In Release 4, arguments entered for @Functions, such as @Prompt([OkCancelEdit];...) , were converted to all capitals, as in [OKCANCELEDIT] , when the formula was saved. In Designer 6, the case you enter is preserved. Used judiciously, case can be an important factor in making the readability and maintenance of your applications easier.
The order of operations, as mentioned earlier in this chapter, proceeds from top to bottom and from left to right. You can, however, alter the precedence of logical and arithmetic operators through the use of parentheses. If you are not careful when using parentheses, you can get some rather surprising results. Parentheses can group statements and can be used to great effect in formulas such as those written for SELECT statements and hide when formulas. Of course, they can be used in many other formulas as well. For example, consider the following view selection formula:
SELECT Form = "AD" &! (dDate1 = "" & dDate2 = "" & dDate3 = "")
This selection criteria does not display any documents composed with the AD form where the three date fields ”dDate1, dDate2, and dDate3 ”are empty. Without the parentheses around the three date fields, a very different collection of documents would appear. With the parentheses, the &! ( AND NOT ) applies to all of the dates. Removing the parentheses causes the view to display documents composed with the AD form where dDate1 is not empty but dDate2 and dDate3 are empty.
SELECT Form = "AD" &! dDate1 = "" & dDate2 = "" & dDate3 = ""
To select documents where at least one of the three date fields is not empty, enclose the date fields in parentheses, but separate them with the OR argument, substituting the pipe symbol for the ampersand:
SELECT Form = "AD" &! (dDate1 = "" dDate2 = "" dDate3 = "")
Combining the logical operators, & and , with parentheses to change the order of precedence provides a very powerful method of limiting the documents that appear in views. However, this technique can also be applied in many other areas, such as view column formulas, default value formulas, and so forth.
Parentheses can also be used to alter the order of evaluation in arithmetic statements. As you know, arithmetic operators have a specific order of precedence. For example, multiplication and division take precedence over addition and subtraction. If you wanted to calculate the sales tax of a group of items, the following formula would not work:
1.99 + 2.89 + 15.99 * .0575
Rounded to two decimal places, this formula returns 5.80 . The multiplication of 15.99 x the sales tax of .0575 is added to 1.99 and 2.89. The real sales tax is 1.20, which can be returned properly through the use of parentheses:
(1.99 + 2.89 + 15.99) * .0575
Part I. Introduction to Release 6
Whats New in Release 6?
The Release 6 Object Store
The Integrated Development Environment
Part II. Foundations of Application Design
Advanced Form Design
Using Shared Resources in Domino Applications
Using the Page Designer
Adding Framesets to Domino Applications
Automating Your Application with Agents
Part III. Programming Domino Applications
Using the Formula Language
Real-World Examples Using the Formula Language
Writing LotusScript for Domino Applications
Real-World LotusScript Examples
Writing Java for Domino Applications
Real-World Java Examples
Enhancing Domino Applications for the Web
Part IV. Advanced Design Topics
Accessing Data with XML
Accessing Data with DECS and DCRs
Security and Domino Applications
Creating Workflow Applications
Analyzing Domino Applications
Part V. Appendices
Appendix A. HTML Reference
Appendix B. Domino URL Reference