XRM Tokens

XRM Tokens provide a generic method to substitute static texts with information from Microsoft Dataverse or Dynamics 365.

This is a XrmToolBox tool to test and learn how XRM Tokens is used. Try it!
Docs: XRM Tokens Runner for Microsoft Dataverse
Best used in the Bulk Data Updater tool.

Substitutions always start within the context of a record in the database, the source record. Based on the token, information from the source record and its relationships is used to substitute the token with dynamic information.

The source code for XRM Tokens is maintained in a C# Shared Project, which can be included in Plugins, Custom APIs, Custom Workflow Activities, XrmToolBox tools, or any other kind of SDK client.


References

Power Fx tokensPower Fx can be used mixed with data. Only imagination limits.
Attribute tokensSimple way to get readable attribute, and linked references.
Raw tokensGetting the raw values, numbers, ids, etc.
Record URL tokensFor a record, or related, or any record – you can get the URL.
Expand tokensGet a list of children records.
System tokensA number of like date and user etc.
Random tokensGet random texts, numbers, date and Guids.
Token formattingLot of feature to change values.
If-else statementsIf-Else for attribute values compare to anything.
SequencesA simple way of numbering a list of any records.

Code 🔗

XRM Tokens is maintained on GitHub repository:
https://github.com/rappen/Rappen.XTB.Helper

XRM Tokens how to use the code as share projects:
https://github.com/rappen/Rappen.XTB.Helper/wiki

XRM Tokens Runner tester is here on GitHub:
https://github.com/rappen/XRMTokensRun

XRMTokens shared project has all details:
https://github.com/rappen/Rappen.XTB.Helper/tree/main/Rappen.XRM.Tokens


Power Fx tokens 🔗

It would be best to start by reading the Microsoft Docs Power Fx formula reference for Power Apps. Just do it.

You can mix with my “normal XRM Tokens formulas”, see this example to increase the price by the percent from the pricelist:

<PowerFx|Round({price|<value>}*(1+({pricelist.yearlyincrease}/100)); 2)>
Result: 10,35   // from price = $9,95 and increase = 4%

Using the string formulas for example:

<PowerFx|Proper("COMPanY: {parentcustomerid.name}")>
Result: Company: Rapp Solutions Ab  // from contact Jonas Rapp

Using an extremely simple formula:

<PowerFx|42+9>
Result: 51

Calculate the area of the diameter of a circle:

<PowerFx| Round( Pi() * Sqrt({rapp_diameter} / 2); 1 ) )
Result: 22,2   // from diameter = 100

Get the current year:

<PowerFx|Year("<system|now>")>
Result: 2022

Compare columns:

<PowerFx|If({rapp_number1}={rapp_number2>};"Equal";"Unequal")>

Note 1: For functions in the formulas that need more than one parameter, will be separated with either a semicolon or a comma. This is because of the different local locale formats on your computer. See like Round in my first example above.
Note 2: The examples were run on a computer with a Swedish locale.
Note 3: There’s a current bug if any formulas include the character “less than” < or “more than” > , it fails. I will fix this before the end of time. I promise. See the example where this is not possible, and the issue #24 to fix it:

More is Number <PowerFx|If({rapp_number1} < {rapp_number2>}; "2 or equal"; "1")>
Error message: GetFirstEnclosedPart: Missing end tag: >

Attribute tokens 🔗

Attributes on the source record are referred to by using simple curly braces around the attribute logical name. Example:

First name is {firstname}.

Information from related parent records can be referenced with dot notation. Example:

Parent account email is {parentaccoundid.emailaddress1}.

This method can be used recursively. Example:

Parent account owner BU name is {parentaccoundid.ownerid.businessunitid.name}.

Raw tokens 🔗

Attributes can always get as “raw” values. If you only do as above it will always get a “nice” readable result. Example was to get raw value:

Credit Limit is money "{creditlimit}" and value to count {creditlimit|<value>}
Parent Contant is "{primarycontactid}" and raw id {primarycontactid|<value>}
Gadgets are: '{rapp_gadgets}' with values {rapp_gadgets|<value>}

Example result:

Credit Limit is money "200,00 kr" and value to count 200,0000
Parent Contant is "Tin Tin" and raw id c45ad2cd-4257-ea11-a811-000d3a4aa8e7
Gadgets are: 'Panorama; Sleep cabin; Loo' with values 100000000;100000001;100000004

Record URL tokens 🔗

For any attribute that is a Lookup, you can add the format to get the full link to that record. You can even use it to the primary id on “this record”.

Simple example:

{accountid|<recordurl>}
{primarycontactid|<recordurl>}

Example result:

https://xxx.crm4.dynamics.com/main.aspx?pagetype=entityrecord&etn=account&id=12345678-87a3-ec11-983f-000d3a4be01e
https://xxx.crm4.dynamics.com/main.aspx?pagetype=entityrecord&etn=contact&id=12345678-7141-ec11-8c62-6045bd8d92e1

Advanced example, creating Markdown this time:

Company: [{name}]({accountid|<recordurl>})
Boss: [{primarycontactid}]({primarycontactid|<recordurl>})
Workers:
<expand|contact|parentcustomerid|- ## [{fullname}]({contactid|<recordurl>})|fullname|
|true|true|>

Advanced example result (in Markdown format):

Advanced example result (in raw format):

Company: [Oil Drilling Company](https://xxx.crm4.dynamics.com/main.aspx?pagetype=entityrecord&etn=account&id=4ccf03b8-87a3-ec11-983f-000d3a4be01e)
Boss: [Harry S. Stamper](https://xxx.crm4.dynamics.com/main.aspx?pagetype=entityrecord&etn=contact&id=cb479557-7141-ec11-8c62-6045bd8d92e1)
Workers:
1. [A.J.](https://xxx.crm4.dynamics.com/main.aspx?pagetype=entityrecord&etn=contact&id=87a1ae69-7141-ec11-8c62-6045bd8d92e1)
2. [Bear](https://xxx.crm4.dynamics.com/main.aspx?pagetype=entityrecord&etn=contact&id=2f2e86e1-9441-ec11-8c62-6045bd8d92e1)
3. [Oscar](https://xxx.crm4.dynamics.com/main.aspx?pagetype=entityrecord&etn=contact&id=d33fa1da-9441-ec11-8c62-6045bd8d92e1)
4. [Rockhound](https://xxx.crm4.dynamics.com/main.aspx?pagetype=entityrecord&etn=contact&id=16cfc06e-9441-ec11-8c62-6045bd8d92e1)

Expand tokens 🔗

XRM Tokens can concatenate information from related child records in 1:M relationships, and even through M:M relationships.

1:M relationships are expanded using the following format:

<expand|childtable|lookup|childtoken|order|separator|distinct|activeonly|maxcount>

Definition of parameters:

  • childtable – logical name of the child table of the 1:M relationship (required)
  • lookup – logical name of the column on the child table that contains the lookup value to the parent (required)
  • childtoken – any valid XRM Token, this is applied to each child record retrieved (required)
  • order – comma separated logical names to sort the child records by, may be suffixed by /asc or /desc to specify direction (optional)
  • separator – string sequence to separate the values of each retrieved child record (optional)
  • distinct – set to true if only one unique occurrence of the child record values shall be included (optional)
  • activeonly – set to false to include inactive child records (optional)
  • maxcount – specify max number of child records to return (optional)

Examples from an account:

Active case types:
<expand|incident|customerid|{casetypecode}||\n|true>

Contact first names:
<expand|contact|parentaccountid|{firstname}|lastname,firstname|, |false|true|100>

Expanding over M:M relationship:

Marketing lists: <expand|listmember|entityid|{listid.listname}||, ||false>

Sample result of the text above:

Marketing lists: Rocket News, X-mas cards

See also examples under Record URL tokens!


System tokens 🔗

System tokens are identified by <system|content|format>.
Available system tokens:

  • Now – current date and time
    Format is any standard or custom C# DateTime format, and may be omitted.
    Example: <system|now|yyyy-MM-dd hh:mm>
  • Today – current date
    Same as Now, but excludes time portion of current DateTime.
  • User – current Dataverse user
    Format is any XRM Token.
    Example: <system|user|{fullname} of {businessunitid.name}>
  • Char – special character handling
    Format can be any of \\n, \\r and \\t, which will be replaced by \n, \r and \t for line breaks and tabs.
    Example: {fullname}<system|char|\\n\\r>{address1_line1}
    Can be used to get { } in the result like this:
    Token: <system|char|{> "status_code": "{statuscode}" <system|char|}>
    Result: { "status_code": "Active" }

Random tokens 🔗

Random tokens are identified by <random|type|param1|param2>.
Available random tokens:

  • Text – returns a numbers of characters
    Param1 is the length of the result.
    Param2 may be added to say which characters will be random from. If not added, these will be used: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.
    Example 1: <random|Text|10> gives like “RWx2CWOmRn”
    Example 2: <random|Text|6|ABCDEFGHIJ> gives a number like “GCEAAJ”
  • Number – returns any number. Both parameters below are optional.
    Param1 is the min number (max number if Param2 is not added).
    Param2 is the max number
    Example 1: <random|Number> gives any number from 0 to Int.Max (2 147 483 646)
    Example 2: <random|Number|10> gives any number from 0 to 10
    Example 3: <random|Number|-100|100> gives any number from -100 to 100
  • Date – returns any date, may add first/last dates.
    Param1 is the first date.
    Param2 is the last date.
    Example 1: <random|Date> returns any date from 0000-01-01 to 9999-12-31
    Example 2: <random|Date|1994-09-21|2003-03-20> returns any date from my children’s births
  • Guid – returns any random guide. No parameters.
    Example: <random|Guid> returns something like “39af8d6b-6ead-4209-a7b6-268ddf92aa35”

Example for random emails:

{firstname}.<random|text|8>@{parentcustomerid|<Replace| |>}<random|number|1|9>.com

Result: Jonas.pN3teoTE@RappSolutions7.com


Token formatting 🔗

Formats can be added to the returned values by adding a pipe character after the token.

Available format tokens:

  • Left – truncates populated value at the end if necessary.
    Format contains the max number of characters.
    Example: {description|<Left|50>}
  • Right – same as Left but truncates from the beginning.
  • Upper – make all letters uppercase.
    Example: {firstname|<Upper>}
    Result: JONAS
  • Lower – make all letters lowercase.
  • Trim – Remove blanks in the beginning or the end of the text.
    Can also add a text to remove, otherwise any spaces. Note this is not exactly as the C# code function, this removes the text, not each character written.
    Examples:
    {name|<Trim>} Removes spaces in the beginning and the end.
    {name|<Trim|ish>} Removes the “ish” string in the beginning and the end.
  • TrimStart – same as Trim, but only from the beginning of the text.
  • TrimEnd – same as Trim, but only from the end of the text.
  • Pad – fills a populated value to specified number of characters
    Format contains R/L defining which end to pad, number of total characters, and an optional pad character.
    The example will right align the first name and prepend it with underscore up to a total of 10 characters.
    Example: {firstname|<Pad|L|10|_>}
    Result: _____Jonas
  • SubStr – gets a section of the populated value.
    Format contains start character (zero indexed) and number of characters to return.
    Example: {accountnumber|<SubStr|3|6>}
    The example will return 6 characters of the account number, starting at the fourth character.
  • Replace – replaces occurrences of old string with the new string in the populated value.
    Example: {description|<Replace|CDS|Dataverse>}
  • Math – performs a few mathematical operations.
    Format contains operator, and a second value. Second value may be a token itself.
    Example: Total VAT: {price|<value><Math|*|{vat}>}
    This example will return the price multiplied by the VAT.
    Math operators: + – * / Div Mod Round Abs. Note that Round and Abs do not require second value.
    Increase price by 5%, with 2 decimals:
    New price: {price|<value><Math|*|105><Math|Round><Math|/|100>}

The formats can be applied to any previous token, and combined:

User last name is <system|user|{lastname|<Left|3><Pad|R|10|*>}>.

The example above would look up the current user, extract the last name, take the first three characters of that, and finally append asterisks to the right up to a total length of 10 characters.


If-else statements 🔗

XRM Tokens can include conditions.

Conditional values are defined using the following format:

<iif|value1|operator|value2|trueresult|falseresult>

Definition of parameters:

  • value1 – any token, static value, or combination for the first value of the comparison
  • operator – defines how to compare value1 and value2
    Allowed operators: eq, neq, lt, gt, le, ge
  • value2 – any token, static value, or combination for the second value of the comparison
  • trueresult – any token, static value, or combination to return if the comparison evaluates to true
  • falseresult – any token, static value, or combination to return if the comparison evaluates to false

Example:

{firstname} has <iif|{emailaddress1}|neq||email {emailaddress1}|no email|>

Sequences 🔗

When using XRM Tokens on a bulk of records, it can be beneficial to number them using an external sequence counter. To add and format this sequence number, enter sequence tokens:

[#|startno|format]

Definition of parameters:

  • startno – indicates first number of the bulk (optional)
  • format – Format is and standard or custom C# number format, and may be omitted.

Examples:

[#] {fullname}
[#|1001|0000000] {name}