As the name implies, the Formula language constructs formulas. Formulas can range from the extremely simple to the extraordinarily complex (for example, a formula using nested @If() and @Do() commands). Although a formula may appear to consist of multiple lines, a formula in Domino equates to a single line of code in a program. While the addition of @DoWhile , @For , and @While have given designers access to iterative functionality within the Formula language, the looping capability is still not equivalent to that built into procedural languages. Similarly, you can't call one formula from another ”there is no branching except within the same formula. This can be a severe limitation. If you need more power and flexibility than that offered by formulas, you can always turn to LotusScript or Java. Remember that, in general, a process written in the Formula language executes more quickly than an equivalent process written in LotusScript. Also, it is generally much easier to write a formula than to write an equivalent program in LotusScript or Java.
Understanding @Functions and @Commands
The two principal components of the Formula language, @Functions and @Commands, are used to construct formulas that return a result or perform an action. @Functions always return a result. For example, the formula @Name([CN]; @UserName) returns the common name component of the user's name. @Commands work only in the user interface and are based on menu commands. For example, @Command([FileCloseWindow]) closes the current window and @Command([EditDocument]) opens a document in edit mode. The menu equivalents are File, Close and Actions, Edit. Unlike @Functions, @Commands do not necessarily return a value.
Working with @Functions
@Functions have a general syntax as follows :
@Function( arguments )
All return a result, and some have side effects (see the section "Understanding Side Effects," later in this chapter). Not all @Functions require arguments; some, such as @All , merely return a result. For example, in a view selection formula, SELECT @All returns all documents in the database. The command @SetField("cStatus"; "New") has two arguments: the name of the document field cStatus and the value. This formula sets the value of the cStatus field to "New" .
Not all @Functions work in all contexts. For example, @All works only in view selection, agent selection, and replication formulas. There are many different types of @Functions, including the following listed in Table 12.1.
Table 12.1. Formula Types
Type | Examples |
---|---|
Arithmetic | @Abs , @Integer , @Round , @Modulo |
Client information | @BrowserInfo , @ClientType |
Data retrieval | @DbColumn , @DbLookup , @DbCommand |
Database information | @DbTitle , @DbName , @DbManager |
Date and time | @Date , @TextToTime , @Time , @Hour , @Year , @Day , @BusinessDays |
Document information | @DocLength , @Attachments , @DocumentUniqueID |
Document status | @IsDocBeingSaved , @IsNewDoc , @IsDocBeingEdited , @DocLock |
Field values | @GetDocField , @SetField , @GetProfileField , @GetField, @ThisName , @ThisValue |
Iterative | @DoWhile , @For , @While |
List | @Count , @Member , @Elements , @Subset , @Contains , @Trim , @Implode , @Explode , @Sort , @DBColumn , @DbLookup |
Logical | @True , @False , @Success , @IsTime , @IsNumber |
@MailSend , @MailDbName , @MailSavePreference | |
String | @Right , @LeftBack , @MiddleBack |
User information | @UserName , @UserRoles , @NameLookup , @UserAccess |
User input | @Prompt , @DialogBox , @PickList |
Working with @Commands
@Commands have a syntax that is similar to the syntax for @Functions:
@Command([ keyword ]; arguments )
These commands work only in the user interface, and they don't return a value. You can use @Commands in actions, SmartIcons, buttons , and hotspots. You can also use them in agents that run against the current document. @Commands cannot be used in scheduled agents , field formulas, or any object that doesn't interact with the user.
Most menu commands have a corresponding @command. For example, the corresponding @Command for the menu command File, Close is @Command([FileCloseWindow]) . Some @Commands, such as @Command ([NavigateNext]) and @Command([NavigatePrev]) , have no corresponding counterpart in the menu. Still others, such as @Command([ToolsRefreshSelectedDocs]) , are a holdover from previous releases of Notes.
The Tools menu was a Release 3 feature that was replaced in part by the Actions menu in later releases of Notes and Domino.
Because @Commands are based on the UI, they will work in foreground agents, agents that are initiated by the user. @Commands are based on the Notes client menu structure (the user interface), so many do not work for Web clients because they are Notes and Domino “specific, with no counterpart available to a browser. Some do work on the Web, however, and are very useful. For example, you can use @Command([NavigateNext]) in a form action to enable the user to move to the next document. Table 12.2 lists the @Commands that can be used on the Web.
Table 12.2. @Commands Supported on the Web
@Command | Function |
---|---|
CalendarFormat | Switches the calendar display specified |
CalendarGoTo | Navigates to the specified date |
Clear | Deletes the current document |
Close Window | Closes the current document window |
Compose | Creates a new document based on the form specified |
EditClear | Deletes a document |
EditDocument | Edits a document |
EmptyTrash | Removes deleted documents from the Trash folder |
FileCloseWindow | Closes the current document |
FileOpenDatabase | Opens a database |
FileSave | Saves a document |
Folder , FolderDocuments | Places or moves documents from a view or folder into a folder |
MoveToTrash | Moves selected documents from a view or folder into the Trash folder |
NavigateNext , NavNext | Navigates to the next document in the view |
NavigateNextMain , NavNextMain | Navigates to the next main document in the view |
NaviagtePrev , NavPrev | Navigates to the previous document in the view |
NavigatePrevMain , NavPrevMain | Navigates to the previous main document in the view |
OpenDocument | Opens a document specified by a UNID, in either read or edit mode |
OpenFrameset | Opens a specific frameset |
OpenNavigator | Opens a specific navigator |
OpenPage | Opens a specific page |
OpenView | Opens a specific view |
RefreshFrame | Refreshes the content of a specific frame in a frameset |
RemoveFromFolder | Removes a document from a folder, but not from the database |
RunAgent | Runs an agent |
SwitchView | Opens a specific view |
ToolsRunMacro | Runs an agent |
ViewChange | Switches to another view |
ViewCollapse | Collapses the current category in a categorized view |
ViewCollapseAll | Collapses all twisties in a categorized view |
ViewExpand | Expands the current category in a categorized view |
ViewExpandAll | Expands all categories in a categorized view |
ViewRefreshFields | Refreshes all fields in the current document |
ViewShowSearchBar | Shows the search bar (on the Web, the search form) |
Understanding Side Effects
Certain @Commands and @Functions have what are called side effects. A side effect is an event that occurs outside the scope of the currently executing formula. An example is opening a different database using @DBLookup() or @DBColumn and retrieving a list of values, or displaying a dialog box with @DialogBox() or @Prompt() . Side effects are useful in formulas when you need user input or to create a keyword based on values stored in a field.
Working with Formula Keywords
Keywords are the third component of the Formula language. Keywords are special functions used in formulas. There are five keywords (by convention, they are capitalized), as shown in Table 12.3.
Table 12.3. The Formula Language Keywords
Keyword | Function |
---|---|
DEFAULT | If a field does not exist, DEFAULT creates a temporary instance and assigns a value. If the field does exist, the formula uses the current value of the field. |
ENVIRONMENT | Assigns a value to an environmental variable stored in the preferences file on the Macintosh or in the windows configuration file, Notes.ini. |
FIELD | Assigns a value to a field, creating the field if it doesn't exist. |
REM | Sets any text following as nonexecuting documentation. The text must be in quotes or curly braces. |
SELECT | Used in view selection formulas, replication formulas, and agents to determine whether the current document is included in the document collection. |
Keywords are useful in many situations. By far, the most frequently used are REM and SELECT , followed by FIELD . Less frequently used are DEFAULT and ENVIRONMENT . Keywords must be listed first on a line, unlike @Functions.
Commenting Formulas with REM
REM is used to comment your formula. Its syntax is pretty simple: REM [" text"] or REM [{text}] . If the comment has either a double or a single quote in it, in previous releases, you prefaced the quote with the slash character; with the addition of curly braces as delimiting characters , you can include the quoted text inside curly braces. The following code fragment illustrates the use of REM with an embedded quoted string:
REM {Include the text "New Chapter" or "Chapter" plus the chapter number.}; @If(@IsNewDoc; "New Chapter"; "Chapter " + cChNumber)
You can see more examples of the REM keyword in Listing 12.1.
NOTE
You might have noticed by now that a semicolon is used frequently in formulas. The semicolon separates arguments within a function and also separates statements in the formula. The semicolon at the end of the previous REM statement separates it from the following @If() statement. Inside the @If() statement, semicolons separate the arguments.
Selecting Documents
The SELECT keyword has one argument: a formula that selects documents. As the name implies, SELECT is used to select documents based on the conditions supplied in the argument. The syntax is SELECT argument . @All is a frequently used argument and is the default for a new views and agents. If the result of the argument returns a true value for the document, it will be selected. Other examples include the following:
SELECT Form = "Main Topic" @Alldescendants SELECT (Form = "Main Topic" & Categories = "Applications Development") @AllDescendants SELECT Form = "CHP" Form = "TTL"
If used as a view selection formula, the first formula displays all documents composed with the Main Topic form and all response and response-to-response documents. The next formula does the same, except that it restricts the view to Main Topic documents with the Categories field set to Applications Development. The last example selects documents created using two forms with aliases of CHP or TTL. Although this is a fairly straightforward formula, in practice, you can create arguments that are much more complex. For example, consider the following complex SELECT statement:
REM {Normally, notify 2 days in advance. On Friday, notify 3 days in advance.}; REM {On Thursday, notify third shift 4 days in advance}; REM {Restrict "Offer Withdrawn" from the view}; SELECT (Form = "NH" & cWithdrawn != "Offer Withdrawn") & ( @If(@Weekday(@Today) = 6; dStart <= @Adjust(@Today; 0; 0; 3; 0; 0; 0); dStart <= @Adjust(@Today; 0; 0; 2; 0; 0; 0)) @If(@Weekday(@Today) > 5 & cShift = "Third" ; dStart <= @Adjust(@Today; 0; 0; 4; 0; 0; 0); dStart <= @Adjust(@Today; 0; 0; 2; 0; 0; 0)) ) & dStart >= @Adjust(@Today; 0; 0; -2; 0; 0; 0)
This view selection formula displays documents created with the NH form in which the offer is not withdrawn and applies a fairly complex series of date restrictions based on the day of the week and the shift.
Setting Field Values with FIELD and DEFAULT
FIELD and DEFAULT are both similar keywords. DEFAULT takes a bit of getting used to because at first glance, it doesn't make that much sense. The syntax is DEFAULT variablename := value . You use it in a formula when you want to make sure that variablename has a value even if the corresponding field doesn't exist. If the field doesn't exist, variablename is assigned value for the duration of the formula. Remember that the scope of a formula is limited to the execution of the formula itself. If you want to save the variable to a field, you must use FIELD or @SetField() . The syntax for FIELD is similar: FIELD fieldname := value . However, if the field exists, its value is overwritten by value . This is an important distinction. Many developers use the following formula to ensure that if the field does not exist, it is initialized for later use in a formula: FIELD fieldname := fieldname . For example, consider the following code:
FIELD cStatus := cStatus
This formula ensures that the field cSubject exists and that its value is not altered . You might use DEFAULT if you want to make sure that if the field cStatus did not exist, it was initialized to New . The FIELD keyword could not accomplish that without using a conditional statement. Compare Listings 12.1, 12.2 and 12.3, which evaluate to the same result.
Listing 12.1 Using the DEFAULT Keyword to Assign a Value
REM "Here is how you would use the DEFAULT Keyword:"; REM "If the field cStatus does not exist, create an instance"; REM "of it and assign New to it. If cStatus does exist,"; REM "use the value of the field."; DEFAULT cStatus := "New"
Listing 12.2 Using FIELD to Assign a Value
REM "Here is how you would use the FIELD keyword to accomplish REM "the same result:"; REM "The first line initializes the field. If it does not exist, "; REM "it creates it; if it does exist, it sets the value to itself."; FIELD cStatus := cStatus;
Listing 12.3 Using FIELD and @If() to Conditionally Assign a Value
REM "This line checks the value of the field, and if it is empty"; REM "it sets the value to New. Note that if we used "; REM {FIELD cStatus = "New"; the field would be changed}; REM "regardless of the current value. The third argument for"; REM "@If() sets the value of the cStatus field to itself."; FIELD cStatus := @If(cStatus = ""; "New"; cStatus)
Designer 6 introduced nested assignment of values. With the exception of the FIELD keyword, all keywords must be at the beginning of a line within the formula. Only the FIELD keyword can be nested within an expression.
@If(@IsAvailable(cStatus); @SetField("cStatus"; "In Progress"); FIELD cStatus := "New")
Using the ENVIRONMENT Keyword
The keyword ENVIRONMENT sets an environment variable in Notes.ini (or in the preferences file, for the Macintosh). ENVIRONMENT is specific to the server or client machine on which it is used. For example, if you want to keep the last navigator used, you can store it to the environment using a formula such as ENVIRONMENT LastNav := navigatorname , where navigatorname is a text value representing the name or alias of the navigator. The value of the variable can be retrieved using @Environment .
NOTE
@SetEnvironment is the @Function equivalent of ENVIRONMENT . It is an @Function and can be embedded anywhere inside a formula, unlike a keyword, which must appear first on a line. @SetEnvironment is perhaps more useful than ENVIRONMENT for this reason.
CAUTION
ENVIRONMENT does not work on the Web, nor do the related @Environment or @SetEnvironment commands.
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
Forms Design
Advanced Form Design
Designing Views
Using Shared Resources in Domino Applications
Using the Page Designer
Creating Outlines
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 JavaScript for Domino Applications
Real-World JavaScript 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