1. Kathy Brown | Running Notes
BP208
Fabulous Feats with @Formula:
IBM Lotus Notes Client, Xpages
and Beyond
2. Agenda
Where to use @Formula
Using @Formula to work with lists
@Formula in XPages
Comparing @Formula to LotusScript
What’s new with @Formula
Some Old, but Cool Tricks
3. Where to Use @Formula
Actions, buttons, hotspots, etc. Input validation
Computed values Input translation
Hide/when formula View selection formula
Window titles XPages!
Default field values
Column formula
Section editor
Not all @functions can be used in all contexts!
4. Input Validation
Use @Success to validate the entered data and @Failure to reject the data and
provide a message to the user
@Success will allow the refresh or save of the document to continue
@Failure will cause the refresh or save to fail, and return the cursor to the failed
field (if not hidden)
Use @Formula to disallow a single blank entry, or blank entries across several
fields
@If (@ThisValue != “”; @Success; @Failure (“Please enter a value.”))
5. More Input Validation
You can enter @Formula in the input validation event for each field,
Or combine the @Formula in one field to eliminate multiple notifications to the
user
@If (( field1 = “” | field2 = “” | field3 = “”); @Failure (“Please enter all of the
required fields.”); @Success)
6. Even More Input Validation
Remember that unless you code to prevent it, (@IsDocBeingSaved), every refresh
of the document will trigger the input validation event
Irritating if the user refreshes the document before completing the form and every
field on the form disallows blank entries
7. Still More Input Validation
Requiring a particular value is quite simple
@If (@ThisValue > 100; @Failure (“This field cannot contain a value larger
than 100”); @Success)
@Matches or @Length (among other @functions) can be used to check format or
particular characters
@If (@Matches (@ThisValue; “{0-9} {0-9} {0-9} {-} {0-9} {0-9} {0-9} {-} {0-9}
{0-9} {0-9} {0-9}); @Success; @Failure (“Phone numbers must be in xxx-
xxx-xxxx format.”)
8. Input Translation
Trim and replace data to make user-entered data more consistent
Translate the data entered into data that is usable by the application
When possible, it is more user-friendly to translate the data rather than fail
validation and require the user to re-enter data
9. @Trim
@Trim does just what it says, it trims any extra white spaces from text or a text list
It does not remove tabs or new lines
10. @ProperCase and @LowerCase
@ProperCase and @LowerCase convert text or text lists to either proper case or
lower case, respectively
@LowerCase is particularly useful for making user-entered data consistent before
checking for a specific value
Three different users may enter “San Antonio,” “SAN ANTONIO,” and “san
antonio”
Lower case text is preferred for internationalization
11. @ReplaceSubstring
@ReplaceSubstring and @Replace are very powerful @functions
Essentially they provide find and replace functionality on strings or lists of strings
symbols := “!” : “@” : “#” : “$” : “%” : “^” : “&” : “*” : “+” : “=”;
result := @Trim (@ReplaceSubstring (field1; symbols; “”))
@ReplaceSubstring (@ThisValue; “” ; “/”)
@ReplaceSubstring (@ThisValue; @NewLine; “ ”)
12. @Round
Numbers can be tricky in Domino development, particularly during multiplication
and division
3.3*3.3 = 10.89
3.33333*3.33333 = 11.11
Use @Round to make decimal placing consistent
Note that @Round works differently than the Round function in
LotusScript
@Round(10.555; 0.1) = 10.6
Round(10.555, 1) = 10.6
13. @Random
@Random generates a random number between 0 and 1
Use the following formula to create a randomly generated number between x and
y
(y – x) * @Random + x
Help file!
14. @ThisValue and @ThisName
@ThisValue can be used in field formula to get the value of
that field
@ThisName provides the name of the current field
No Hard Coding!
Re-use code!
Can’t be used outside of field formula
Can’t be used in a hide formula
15. @SetEnvironment and @Environment
@SetEnvironment can set or create a variable in the user’s notes.ini file (or Notes
Preferences on a Mac)
Use @Environment to get the variable value from the notes.ini file
@SetEnvironment and @Environment cannot be used in column or selection
formula, or on the Web
Oddly, a text list can be provided for the variableName parameter, and the same
value will be assigned to all the listed variableNames, but …
If a text list is provided for the value parameter, only the first value is used, the
rest are ignored
@SetEnvironment and @Environment can be useful for setting user preferences
For example, a user location can be set and then provided as a default value
to make entry easier for the user
16. Fantastic Feat #1
Include the following formula in the Target Frame (single click) event in the
embedded view:
@SetEnvironment( "eViewSelection"; @Text(@DocumentUniqueID))
Include the following LotusScript in a button on the form where the embedded
view resides:
…
selectedDocIDString = session.GetEnvironmentString("$eViewSelection", False)
…
Set selectedDocID = db.GetDocumentByUNID(selectedDocIDString)
17. @Adjust
@Adjust allows you to adjust a given date value by second, minute, hour, day,
month, and/or year
If more than one segment of the date value needs to be adjusted, @Adjust is
easier than the LotusScript equivalent, as each value needs to be adjusted
individually in LotusScript
Adjust by more than just a number
@Adjust (aDate; 0; 0; - (@Weekday(aDate) – 1; 0; 0; 0) evaluates to the
Sunday before the given date
18. @Text
@Text isn’t just for converting values to a string
The power of @Text comes in the second parameter, the format string
@Text (someDate; “D0S0”) provides a date with the month, day, and year, and
no time
Many of the LotusScript functions associated with date are reliant on the
system format
Several number formats are also available including currency and percentage
19. View Selection Formula
Two problems with the view selection formula are the inability to use @DbLookups
and the best practice of avoiding @Today
@DbLookups just won’t work in view selection formula
@Today is a poor practice due to the drag on performance
Hard coding values is a poor practice workaround!
LotusScript (and formula) to the rescue!
20. View Selection Formula (cont.)
@AllDescendents versus @IsResponseDoc
Use @AllDescendents in view selection formula
@AllDescendents retrieves only those documents that are responses to
the documents included in the view
@IsResponseDoc retrieves all response documents in the application and
checks them against the docs in the view
See Andrew Pollack’s blog for more information, including view index size
comparisons
21. Agenda
Where to use @Formula
Using @Formula to work with lists
@Formula in XPages
Comparing @Formula to LotusScript
What’s new with @Formula
Some Old, but Cool Tricks
22. Working with Lists
Note that many of the previous @functions also work on lists of values, not just
individual values
Now we’ll cover a few more @functions that are particularly useful when working
with lists
23. @Unique
@Unique has two very different, very useful functions depending on the
parameters
@Unique with no parameters provides a random, unique
text value
@Unique when given a text list as a parameter, will return the list with
duplicate values removed
24. @Transform
@Transform takes three parameters
The list to transform
A variable name
The formula for transforming the list
@Transform (@ThisValue; “x”; @If (x>0; x*60; 0) )
This example takes a list of values, checks to see if each item in the
list is greater than 0. If it is the value is multiplied by 60, if not, then
0 is returned.
The return value is a list that has been transformed by
the formula
25. @Transform (cont.)
@Transform can utilize @Nothing
@Nothing is only available in @Transform
@Transform (@ThisValue; “x”; @If (x>0; x*60; @Nothing) )
A great use of @Transform is changing the decimal place on a list of values
For example, a list of values meant to be percentages shown as 50, needs to
be transformed to 0.50
@Transform (@ThisValue; “x”; @If (x>1; x/100; @ThisValue) )
26. @Sort
@Sort is an incredibly powerful @function
Particularly if you use the [CUSTOMSORT] keyword
Take a multi-value field with a list of names:
“John Smith” : “Jane Doe” : “Kathy Brown”
How can you sort by last name?
@sort (list; [CUSTOMSORT]; @If (@Word ($A; “ ”; 2) < @Word ($B; “ ”; 2);
@False; (@Word ($A; “ ”; 2) > @Word ($B; “ ”; 2); @True; @False))
Essentially, a custom sort formula, using $A and $B as temporary
variables
Use any formula you can imagine for the custom sort function!
27. @Max and @Min
@Max will provide the maximum value in a list of values
Likewise @Min provides the minimum value in a list of values
Additionally, each will provide the maximum of a pair-wise list
of values
List1 := 1 : 2 : 3 : 4
List2 := 5 : 6 : 0 : 1
@Max (List1; List2) will return 5 : 6 : 3 : 4
29. @Matches
An earlier example showed @Matches as a way of validating format for a field
entry
Several wildcard characters are available for @Matches
Lists can be passed in as both the parameter to be checked, and the parameter
containing the pattern for which to check
30. @Matches (cont.)
Symbol /Pattern Use /Matches
C Where C is any character. Matches any single, non-special character C (or c)
? Matches any single character
* Matches any string (any number of characters)
{ABC} Matches any character in set ABC
{A-FL-R} Matches any character in the sets A...F and L..R
+C Matches any number of occurrences of C (or c)
ABC The three-character string [a|A][b|B][c|C]
{ABC}{ABC} Any two-character string composed of capital letters A, B, or C
A?C Any three-character string that starts with a|A and ends with c|C
??? Any three-character string
+? Any string, including the null string
+?{A-Z} Any string that ends in a capital letter
+{!A-Z} Any string that does not contain a capital letter
31. @Contains
@Contains is similar to @Matches in that either parameter passed in can be a
string or a string list
@Contains can return a true value if the first parameter contains the second
parameter, but is not an exact match
Use the “=” operator or @IsMember for exact matches
32. Agenda
Where to use @Formula
Using @Formula to work with lists
@Formula in XPages
Comparing @Formula to LotusScript
What’s new with @Formula
Some Old, but Cool Tricks
33. @Formula in XPages
XPages are now available in Domino 8.5.x
@Formula is available to use in Server Side JavaScript (SSJS)
Not all @Formula are supported in XPages
34. @Formula in XPages (cont.)
Three syntactic changes to use @Formula in XPages:
Use commas rather than semicolons
Use exact case
Example:
var uname = @Name(“[CN]”, @UserName())
“null” should be used in place of 0 for formulas such as @Adjust
Example:
var adate = @Adjust (@Created(), null, null, 5, null, null, null)
35. @Formula in XPages (cont.)
Help file is not very helpful!
@Name(“[CN]”, name) – needs those quotes! But there is no example in the help
file to demonstrate that!
@UserName() – needs those parentheses! Again, no example in the help file to
show that!
39. Agenda
Where to use @Formula
Using @Formula to work with lists
@Formula in XPages
Comparing @Formula to LotusScript
What’s new with @Formula
Some Old, but Cool Tricks
40. @Formula vs. LotusScript
Many @functions have LotusScript equivalents
Check the Help file for language cross-reference
Especially check Help file for each language for additional examples
Check the Help file for differences in parameters, syntax, and where the
function can be used
Some @Formula do not have LotusScript equivalents
Some @Formula require less code and/or perform faster than LotusScript
equivalents
41. Evaluate using @Formula in LotusScript
Use the Evaluate method in LotusScript to have access to @Formula
Only use it when it makes sense, like for @DbLookup or other @Formula that
don’t have equivalent LotusScript methods
Dim results as variant
results = Evaluate ( { @Trim (@Unique (tempList))})
Most frequent problem is choosing the right delimiters and keeping them
organized within the formula
results = Evaluate {“@IsMember (‘Joe’; ‘Joe’ : ‘Jane’ : ‘Jen’)”}
42. @MailSend
@MailSend is a great example of @Formula having more functionality over
LotusScript equivalents
@MailSend acts like Send method of NotesUIDocument
However, @MailSend has more parameters, including flags!
43. @Sort vs LotusScript
val := @Sort (TextList);
@SetField (“textListOutput”; val)
vs.
Calls a script library!
44. Agenda
Where to use @Formula
Using @Formula to work with lists
@Formula in XPages
Comparing @Formula to LotusScript
What’s new-ish with @Formula
Some Old, but Cool Tricks
45. @WhichFolders
Shows in which folders a particular document resides
Currently not that useful, only available in view column formula
From the IBM help file: “The function is effective only when the view is open in the
UI and the outline pane on the left is visible”
But, someday ... ?
46. @AbstractSimple
Creates an abstract of a text or rich text field
Must save the document before using
Returns the first 100 characters or first two paragraphs, whichever is smaller
Useful for searching rich text fields for certain strings of text
Less complex than @Abstract, no keywords, size, or beginning text required
Consequently @AbstractSimple is more efficient than @Abstract
47. New @Commands
@Command [CopySelectedAsTable]
Functions the same as Edit--> Copy As… --> Table
Useful for creating a button to streamline user experience in views where
users would typically copy the data
@Command [OpenInNewWindow]
Causes a document selected within a view, folder, or calendar to be opened in
a new window
Valuable when a new window would aid the user, such as comparing one
document to another
@Command [CalendarFormat]
Added two new formats
Two work-week display
One work-month display
48. Agenda
Where to use @Formula
Using @Formula to work with lists
@Formula in XPages
Comparing @Formula to LotusScript
What’s new with @Formula
Some Old, but Cool Tricks
49. Fantastic Feat #3!
Data := [some field with a text string];
src := @Explode(Data; " ");
digits := (0:1:2:3:4:5:6:7:8:9);
digitsRev := (9:8:7:6:5:4:3:2:1:0);
numList := @Subset(((digits*+digits)*+digits); @Elements(src));
numListRev := @Subset(((digitsRev*10)*+digitsRev); -@Elements(src));
targList := @Text(numList) + @Char(250) + src;
@Word(@Replace(@Text(numListRev); @Text(numList); targList); @Char(250);
2)
50. Complicated Functionality, Uncomplicated
@Functions
Prior code uses seven @functions
@Explode
@Subset
@Elements
@Text
@Char
@Word
@Replace
All seven are backwards compatible to Version 3!
Most important, using the building blocks of @Formula, you can create incredibly
complex code
51. Everything Old Is New Again
Formula debugger?
No, not really, but …
You can place @Prompts throughout your code to see values as you go
You can write values to other fields to see @Formula values as you go
For simple @Formula, you can use the subject line of a memo and press
SHIFT+F9
52. Resources
Andrew Pollack’s entry on @AllDescendents vs. @IsResponseDoc
www.thenorth.com/apblog4.nsf/0/6DF6AAD2521ADF9185257647005E9539
Andrew’s session, IBM Lotus Domino Server & Application Performance in the
Real World,
White paper on using Evaluate
www.ibm.com/developerworks/lotus/library/ls-The_Evaluate_
statement/index.html
Niklas Waller’s entry on @SetEnvironment to access a doc in an embedded view
www.wohill.com/design/266/Get-selected-document-from-embedded-view.html
IBM Lotus Notes Documentation Lotus Domino Designer 8.5 Lotus Domino
Designer XPages Reference Guide JavaScript language elements @Functions
http://bit.ly/FormulaMap
Lotus Domino Application Development wiki - www-10.lotus.com/ldd/ddwiki.nsf
53. Bonus Feat
REM {Get a Date};
dateString := @Prompt([OkCancelEdit]; "Enter a Date"; "Please enter a date
below:"; "mm/dd/yyyy");
REM {Convert the date to a Julian Day.};
m := @TextToNumber(@Word(dateString; "/"; 1));
d := @TextToNumber(@Word(dateString; "/"; 2));
y := @TextToNumber(@Word(dateString; "/"; 3));
y := @If(m <= 2; y - 1; y);
m := @If(m <= 2; m + 12; m);
c := 2 - @Integer(y / 100) + @Integer(y / 400);
jd := @Integer(1461 * (y + 4716) / 4) + @Integer(153 * (m + 1) / 5) + d + c -
1524.5;
54. REM {Determine which synodic month we're in, using an average length of 29.53
days per synodic month.};
k := (jd - 2451550.09765) / 29.530588853;
REM {The fractional value of k is how far along in the synodic month this day is. The
full moon should come exactly halfway through the synodic month, so if the
fractional value is 0.5 then today should be a full moon.};
moonPhase := "Nothing special";
fraction := @Round(k - @Integer(k); 0.01);
moonPhase := @If(fraction >= 0.99 | fraction <= 0.01; "New Moon"; moonPhase);
moonPhase := @If(fraction >= 0.24 & fraction <= 0.26; "First Quarter"; moonPhase);
moonPhase := @If(fraction >= 0.49 & fraction <= 0.51; "Full Moon"; moonPhase);
moonPhase := @If(fraction >= 0.74 & fraction <= 0.76; "Last Quarter"; moonPhase);
@Prompt([Ok]; "Moon Phase"; "date = " + dateString + @NewLine +
"jd = " + @Text(jd) + @NewLine +
"k = " + @Text(k) + @NewLine +
"fraction = " + @Text(fraction) + @NewLine +
"Moon Phase = " + moonPhase)
55. Your Turn!
Kathy Brown
@kjbrown13 on Twitter
kathy@runningnotes.net
www.runningnotes.net
@NotesDevTips on Twitter
Don’t Forget Your Evaluations!