OverviewCopy link to clipboard
This page lists a collection of function recipes you can use throughout the Appian application. Similar to a cookbook, it shows the individual ingredients that go into creating an expression using Appian functions, the order in which to combine them, and tips on when to use them or modify for preference.
The expressions listed below are not the only way to accomplish each desired outcome. This page is intended to teach you methods for creating expressions using Appian functions that are practical and efficient, as well as provide working expressions you can implement as is. Just as with cooking recipes, you may want to alter the values in each recipe to accommodate your specific requirements.
The function recipes are categorized by the type of output. Each recipe is titled with the question in mind, "What do you want to do?"
Note: For function recipes that require a rule as an Ingredient, create the rule as listed before implementing the function recipe.
Date/time resultsCopy link to clipboard
Retrieve next anniversary dateCopy link to clipboard
Use caseCopy link to clipboard
You want to retrieve next year's anniversary date based on a start date, such as an employee's hire date of 02/05/2011.
IngredientsCopy link to clipboard
InputsCopy link to clipboard
- start (date)
ExpressionCopy link to clipboard
1
2
3
4
5
6
7
8
if(
or(
and(month(ri!start) <= month(today()), day(ri!start) <= day(today())),
and(month(ri!start) < month(today()), day(ri!start) > day(today()))
),
date(1 + year(today()), month(ri!start), day(ri!start)),
date(year(today()), month(ri!start), day(ri!start))
)
Copy
Start a timer one minute after a process startsCopy link to clipboard
Use caseCopy link to clipboard
You want to set a timer to start exactly one minute after a process starts, as compared to automatically.
IngredientsCopy link to clipboard
ExpressionCopy link to clipboard
Configure this in the "Delay until the date and time specified by this expression" on the Setup tab for the Timer Event.
pp!start_time + minute(1)
Note: To change the time difference from 1 minute to more, modify the value in the minute()
function as desired.
Add ten minutes to a datetime valueCopy link to clipboard
Use caseCopy link to clipboard
You want to add ten minutes to a datetime value saved as pv!datetime.
IngredientsCopy link to clipboard
ExpressionCopy link to clipboard
pv!datetime + intervalds(0,10,0)
Note: To change interval added to the datetime value, modify the values in intervalds()
as desired.
Determine if a date-time value falls within working hoursCopy link to clipboard
Use caseCopy link to clipboard
Users are able to enter any date-time value, but you want to perform an extra validation after users submit the form to determine if a date-time value (saved as ri!dt) falls between your company's working hours of 6:00 AM and 5:00 PM.
The idea is to work with one consistent time scale, which is done here by the use of timestamps rather than both hours and minutes. This function constructs new timestamps for the boundaries matching the input.
IngredientsCopy link to clipboard
InputsCopy link to clipboard
- dt (DateTime)
ExpressionCopy link to clipboard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
or(
ri!dt > gmt(
datetime(
year(ri!dt),
month(ri!dt),
day(ri!dt),
17,
0,
0
)
),
ri!dt < gmt(
datetime(
year(ri!dt),
month(ri!dt),
day(ri!dt),
6,
0,
0
)
)
)
Copy
Note: To change the working hours, modify the values within the datetime()
function as desired
Display the number of days before a specific dateCopy link to clipboard
Use caseCopy link to clipboard
You want to tell users how many business days are left before a deal closes, if the deal has already closed, or if the deal is closing today.
IngredientsCopy link to clipboard
InputsCopy link to clipboard
- closeDate (Date)
ExpressionCopy link to clipboard
1
2
3
4
5
6
7
8
9
if(
networkdays(today(), ri!closeDate)<=0,
"This deal has closed.",
if(
networkdays(today(), ri!closeDate)=1,
"This deal will close at the end of today.",
"This deal will close in" & networkdays(today(), ri!closeDate) & "business days."
)
)
Copy
Note: To change the text that displays, modify the text as desired. To base the number of days on a system calendar, replace any instance of networkdays(today(), ri!closeDate)
with calworkdays(today(), ri!closeDate, "companyCalendar")
where companyCalendar
is the name of your system calendar. To include all days (including weekends), replace any instance of networkdays(today(), ri!closeDate)
with tointeger(ri!closeDate - today())
.
See also: calworkdays() and tointeger()
Convert an XML string into a value of type DatetimeCopy link to clipboard
Use caseCopy link to clipboard
You have a localized XML string representing a date and time and need to convert it to a value of type Datetime in the GMT timezone.
IngredientsCopy link to clipboard
InputsCopy link to clipboard
- dateText (Text)
ExpressionCopy link to clipboard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
=a!localVariables(
local!fullArray: split(ri!dateText, "T"),
local!dateArray: split(local!fullArray[1], "-"),
local!timeArray: split(left(local!fullArray[2], 12), ":"),
local!smsArray: split(local!timeArray[3], "."),
local!timeZone: "GMT" & right(local!fullArray[2], 6),
local!rawDate: datetime(
local!dateArray[1],
local!dateArray[2],
local!dateArray[3],
local!timeArray[1],
local!timeArray[2],
local!smsArray[1],
local!smsArray[2]
),
gmt(
local!rawDate,
local!timeZone
)
)
Copy
yields 9/25/2013 1:50 AM GMT+00:00
where ri!dateText
= 2013-09-24T19:50:24.192-06:00
Number resultsCopy link to clipboard
Return the number of active employees in your applicationCopy link to clipboard
Use caseCopy link to clipboard
You want to quickly display how many employee records exist in your application.
IngedientsCopy link to clipboard
ExpressionCopy link to clipboard
myQueryRule(topaginginfo(1,0)).totalCount
Note: When using a batchsize of 0 and attempting to only retrieve a total count based on a query, the function detailed above is better to use than count(myQueryRule())
. If you used count(myQueryRule())
, the system would run the main query; whereas using .totalcount
, the system only executes a count query against the database.
Return the total number of revisions made to a documentCopy link to clipboard
Use caseCopy link to clipboard
You want to show the number of times a document has had a new version saved.
IngedientsCopy link to clipboard
InputCopy link to clipboard
- doc (Document)
ExpressionCopy link to clipboard
document(ri!doc,"totalNumberOfVersions")-1)
Return a random integer in a rangeCopy link to clipboard
Use caseCopy link to clipboard
You want to return a random integer between two integers, inclusive.
IngredientsCopy link to clipboard
InputsCopy link to clipboard
- min (Number (Integer))
- max (Number (Integer))
ExpressionCopy link to clipboard
ri!min + tointeger(rand() * (ri!max - ri!min))
Text resultsCopy link to clipboard
Truncate text after 50 charactersCopy link to clipboard
Use caseCopy link to clipboard
You want to truncate the remaining part of a text value once it surpasses 50 characters by replacing the excess text with an ellipsis (…).
IngredientsCopy link to clipboard
InputsCopy link to clipboard
- text (Text)
ExpressionCopy link to clipboard
1
2
3
4
5
if(
len(ri!text) > 50,
left(ri!text, 50) & "...",
ri!text
)
Copy
Note: To change the amount of characters allowed before truncating, modify the numeric value as desired.
Display the full name of a userCopy link to clipboard
Use caseCopy link to clipboard
You want to display the full name of a user despite knowing only the username. Additionally, the field that is storing user information may not always contain a value.
Tip: If the User record type has data sync enabled, you can reference the firstAndLastName
record field instead of building this expression.
IngredientsCopy link to clipboard
InputsCopy link to clipboard
- user (User)
ExpressionCopy link to clipboard
1
2
3
4
5
if(
isnull(ri!user),
"",
user(ri!user, "firstName") & " " & user(ri!user, "lastName")
)
Copy
Note: To change the user information that is populated, modify the second parameter in the user()
function as desired.
Create a title from any text valueCopy link to clipboard
Use caseCopy link to clipboard
You want to convert a text value to display as a title, which will capitalize the first word, and all words not found in a "no capitalize" list.
IngredientsCopy link to clipboard
InputsCopy link to clipboard
- title (Text)
ExpressionCopy link to clipboard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
a!localVariables(
/* Breaks up the title into an array of words and removes whitespaces. */
local!titleArray: split(trim(ri!title), " "),
/* A list of words that will be ignored. Adjust this list to change what does not get capitalized. */
local!noCaps: {"a","an","the","at","by","in","of","up","as","and","but","or","for","nor","etc.","etc","on","at","to","from", "that"},
/* If the word is in local!noCaps but not the first word, don't capitalize. Otherwise capitalize the word. */
concat(
a!forEach(
items: local!titleArray,
expression: if(
and(not(fv!isFirst), contains(local!noCaps, fv!item)),
fv!item,
proper(fv!item)
) & if(fv!isLast, "", " ")
)
)
)
Copy
Note: To produce initial caps for your own text, modify the text value as desired.
Array resultsCopy link to clipboard
Remove all values in an arrayCopy link to clipboard
Use caseCopy link to clipboard
You want to remove all values in an array so it is considered empty.
IngredientsCopy link to clipboard
InputsCopy link to clipboard
- array (Any Array)
ExpressionCopy link to clipboard
ldrop(ri!array, count(ri!array))
Note: Instead of the word array, enter the name or array reference as needed.
Repeat each item in an array based on the values of a different arrayCopy link to clipboard
Use caseCopy link to clipboard
You want to repeat each item in an array (for example, local!textList
) a certain number of times as defined by the values in a different array (for example, local!frequencyList
).
- Where
local!textList = {"a", "b", "c"}
andlocal!frequencyList = {2, 3, 1}
, the output would be{"a", "a", "b", "b", "b", "c"}
.
IngredientsCopy link to clipboard
InputsCopy link to clipboard
- textList (Array)
- frequencyList (Array)
ExpressionCopy link to clipboard
1
2
3
4
5
6
7
8
9
10
11
load(
local!textList: {"a","b","c"},
local!frequencyList:{2,3,1},
a!forEach(
items:local!textList,
expression: repeat(
local!frequencyList[fv!index],
fv!item
)
)
)
Copy
Note: To change which variables to use, modify the textList value to the array variable that should determine the text to repeat and modify the frequencyList value to the array variable that should determine how many times each text value in the aforementioned array should be repeated.
Extract a list from an EntityData array of the data written to a single entityCopy link to clipboard
Use caseCopy link to clipboard
You want to extract the list of data written to an entity (for example, Opportunity) based on the output generated by using the Write to Multiple Data Store Entities Smart Service to write to three entities: Opportunity, Contact, and Line Item.
See also: Write to Multiple Data Store Entities Smart Service
The explanation of the configuration is longer than the solution. If you configure the Write to Multiple Data Store Entities Smart Service to update data for three entities (Opportunity, Contact, and Line Item), each entity may show up more than once in the EntityData input array. Consequently, the output of the smart service ("Stored Values") would contain a dynamic number of elements for each EntityData.
To get the list of all Opportunities that were updated by the smart service, you need to append every Data field where the entity is equal to Opportunity.
IngredientsCopy link to clipboard
- a!forEach().
- Write to Multiple Data Store Entity Smart Service.
- OPPORTUNITY_ENTITY Constant (Data Store Entity).
entityData
is the array to operate on andentity
is the context parameter.
ExpressionCopy link to clipboard
Within the expression editor of a new custom output:
1
2
3
4
5
6
7
8
a!forEach(
items: merge(ac!StoredValues, cons!OPPORTUNITY_ENTITY),
expression: if(
fv!item[1].entity = fv!item[2],
fv!item.Data,
{}
)
)
Copy
Note: To change the entity by which to pull the list of data from, modify the OPPORTUNITY_ENTITY value as desired.
Sort an arrayCopy link to clipboard
Use caseCopy link to clipboard
You want to sort an array of values.
IngredientsCopy link to clipboard
InputsCopy link to clipboard
- array (Any Array)
ExpressionCopy link to clipboard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
todatasubset(
a!forEach(
ri!array,
{
value: fv!item
}
),
a!pagingInfo(
startIndex: 1,
batchSize: -1,
sort: a!sortInfo(
field:"value",
ascending: true
)
)
).data.value
Copy
Boolean resultsCopy link to clipboard
Determine if items in an array are contained within another arrayCopy link to clipboard
Use caseCopy link to clipboard
You want to see if any of the items in an array are contained within another array.
IngredientsCopy link to clipboard
ExpressionCopy link to clipboard
1
2
3
4
5
6
or(
a!forEach(
items:ri!originalArray,
expression: contains(ri!compareArray, fv!item)
)
)
Copy
Matching resultsCopy link to clipboard
Return a CDT from an array that contains a field value matching another valueCopy link to clipboard
Use caseCopy link to clipboard
You have an array of department CDTs, each containing a field called Id
, and you want to retrieve the CDT with an id
value matching the value of a process variable.
IngedientsCopy link to clipboard
- displayvalue()
- rule input:
ri!departmentid
(Integer) - rule input:
ri!departments
(CDT Array) -
Custom Data Type:
1 2 3
department (Text) |- id (Integer) |- address (Text)
Copy
ExpressionCopy link to clipboard
displayvalue(ri!departmentId, ri!departments.id, ri!departments, "none")
Note: To change the value that displays if the ri!departmentId
doesn't match any ri!department.id
values, modify the "none" text value as desired.