** It is not recommended to read Manual on phones and smaller screen tablets, since you may not enjoy full user experience.
Welcome to the Alchemy Script User Manual!
This document will be your personal guide through the Alchemy Script language, a tool that enables you to harness the power of Alchemy Script in order to automate parts of processes and data entry, data visibility, or data calculations reflected in the Alchemy User Portal.
As a System Administrator, you have the possibility to add Alchemy Script Expressions to the process and record templates to fit the needs of your organization using the Configuration Portal. In the User Portal, configured templates will allow members of your organization to capture their work in a structured and predetermined way.
This manual will guide you on best practices as you learn where and how to write Alchemy Script Expressions.
Throughout the Configuration Portal manual, you had the chance to see different alchemy script expressions in examples and explanations.
Alchemy Script Expressions can be used throughout record templates:
Alchemy Script Expressions can be used throughout process templates:
Before we see how to write expressions, we need to define the types of data to be used in expressions:
Elements of alchemy script expressions can be
These elements are represented in Figures 2.1 and 2.2.
Constants are values that are entered directly into a formula expression and do not change when the context is changed. They can be:
Additional data types cannot be used as constants since the data will always depend on context from the user portal.
Variables can be system fields or different fields inside record templates. Field identifiers are used to identify variables in formulas and the system evaluates variables every time a calculation is triggered.
Defined data types correspond to specific field types in the system:
Variables used to reference a field within the same record can be defined using only the field identifier, such as:
VariableFieldIdentifier
In the record, Request, a user fills in the number of samples needed. This is configured in the record template using a field named Number of Samples:
Each sample needs to be tested three times. Another field needs to be added to the record template called Number of Tests:
In the Formula Expression of this field, write:
NumberOfSamples * 3
This expression will pull the value entered by the user in the field Number of Samples and multiply it by 3. The resulting value of the Number of Tests field will be automatically calculated.
Variables from different records can be accessed and used in expressions by using the record reference field when configuring a record template. The expression field would be defined using:
RecordReferenceField.VariableFieldIdentifier
Note: This is a continuation of the previous scenario and should be referenced for additional information.
After a Request record has been submitted, a Chemist will perform the applicable tests and enter the results in a different record called Test Results. In order to pull data from the Request record into the Test Results record, a gateway must be established between the two.
The Test Results record template will need to be configured with a field named Related to Request:
The data value pulled from the Request record will be placed in a field named Number of Samples:
In the Formula Expression of this field, write:
RelatedToRequest.NumberOfSamples
RelatedToRequest.NumberOfSamples
The expression can also be used in calculation formulas, referenced in the previous scenario.
All records created in the scope of a single current process template can be accessed using the expression:
Record[RecordTemplateIdentifier].VariableFieldIdentifier
To better understand what this expression means, we can break down the first element:
Record: The keyword representing which record should be accessed.
[RecordTemplateIdentifier]: Records are sorted by the time of their creation. By using this component in the expression Alchemy will look for, and take the value of, the last created record within the process.
If the field referenced is part of a record template that is used in more than one stage of the process, you need to specify within the expression which stage you want to pull the data by adding Stage[StageName].
The full expression would be then be:
Stage[StageName].Record[RecordTemplateIdentifier ].VariableFieldIdentifier
In the Characterization stage you made a field for the number of samples that are needed.
The number of samples will determine how many rows will be available in the characterization table.
To do this, make a repeatable row group and put it on top of the input fields as already explained in the Configuration Portal manual - How to make a table in Alchemy. In the Repeatable Option field of the group’s advanced settings, select Determined by Formula. In the Formula Expression write the expression:
NumberOfSamples
Another possible solution is that you defined the number of samples in the stage Request within the record, Request Form. In this case write in the Formula Expression for the repeatable row group that is set to Determined by Formula:
Stage[Request].Record[RequestForm].NumberOfSamples
To access and perform calculations with fields located in a record from another process you will need to configure a field in the record template where users can select either the:
If the record template is configured using the Record field, its identifier will be used as the record reference in your expressions:
RecordFieldIdentifier.VariableFieldIdentifier
A user is trying to access the pH of a product from a record, QC Profile, which is part of the Register Product process. This data needs to be pulled into a record, QC Results, in the Quality Control process.
In the record template of QC Results, there need to be two configured fields:
In the calculation field of Target pH, write:
FromQCProfile.ProductpH
In this expression, FromQCProfile is the identifier of the first field while ProductpH is the identifier of the field in which the original value was entered during product testing.
To access the value of the pH field(identifier ProductpH) entered in the record QC Profile in the process Register Product (marked with a star in the image below) you need to configure the following two fields in the record, QC Results, from the process, Quality Control:
1 - Record field type with identifier: FromQCProfile
2 - Number field type with calculation: FromQCProfile.ProductpH
In case you use a process field in your configuration, you must add its identifier in the expression:
ProcessField.Record[RecordTemplateIdentifier].VariableFieldIdentifier
This expression behaves the same as explained earlier, with the difference that the records will be pulled from the process selected in the ProcessField field. See the examples below.
In the Alchemy Lab, Chemists are using the process template, Register Product, to input all details about lab products they get from their formulation outcomes.
The Lab Manager is using the process template, Sample, to prepare samples of products, finish the administration work and send them out to customers.
Inside a Sample process, the Lab Manager needs to pull some data from a Register Product process. Schemes of both process templates are shown in the figure below. In the process template, Register Product, there are multiple stages and records but the field the Lab Manager needs to pull data from is called pH (Identifier: pH). This field is located in the stage, Product Information, in the record, Chemical Characteristics.
Both the process template and record template need to be referenced in the Lab Manager's Sample process in order for the system to recognize where to pull the data, since the record template, Chemical Characteristics, is used across the organization in multiple process templates (NPD, ARM).
Fields that are needed in the Sample process template are:
*In the User Portal, the user will select the exact process from the dropdown list.
*The field must be the same type as the source field we are pulling data from.
This field needs to have a Formula Expression:
ChooseProduct.Record[ChemicalCharacteristics].pH
These fields are in the Sample process template, stage: Request, record template: Request Form as seen in the figure below.
In case there may be multiple records of the same template in the process you are referencing, it is advisable to create a new record field where the user can choose which record to pull the data from.
Similar to the previous example, when there may be multiple Chemical Characterization records in the Register Product process, it is advisable to have an intermediate field where the user can select which of the Chemical Characterization records to pull the data from.
Fields that are needed in the Sample process template are:
*In the User Portal, the user will select the exact process from the dropdown list.
*In the User Portal, the user will select the exact record from the dropdown list.
Below we break down what the Filter Criteria expression means:
Result is the keyword used for filtering.
Process is the system field used for matching the chosen process.
ChooseProduct is the identifier of the first field where you have chosen a process.
*The field must be the same type as the source field we are pulling data from.
As you have seen already, it is possible to "connect" multiple record and process references in one expression. For example, it is possible to access the system information about the process where the record was created using the expression:
RecordVariable.Process
Where RecordVariable is the identifier of your record field. This can be expanded further to access the process system fields. For example:
RecordVariable.Process.Status
will return the string representing the status of the process in which this record is created. This could be useful filter criteria, such as when we only want to be able to select formulation records in ongoing lab work processes.
While the multiple "dot expressions" are useful, they should be used sparingly, as more complex expressions may impact performance. Using intermediate, or hidden, fields is recommended when possible.
ThisField makes it possible to reference a field in its own calculation by enabling calculations to check the state of the field before any recalculation is done, giving the user the possibility to calculate values only for newly created rows in tables.
Data generated by the system operation is available to be used in expressions. System data can provide more information about a process, record, stage run or a user. They can be accessed by using specific keywords listed in the following sections.
Process data, from the same or different process, can be accessed through the system fields listed below using the keyword Process or the process template identifier. To access this data you need to create a field in the record template with the appropriate formula expression. The field type must be: alphanumeric, number, datetime, or user.
If data is pulled from the current process, the formula expression should be:
Process.SystemFieldIdentifier
In this example, Process is the keyword for the current process instance while SystemFieldIdentifier is the variable field identifier that is housing the data being pulled.
In the record template, an alphanumeric field type is created with the formula expression:
Process.Status
This will provide an output as a string of one of the four available statuses of the current process: In Progress, On Hold, Completed, Voided.
If data is pulled from a different process, the record template needs to include an additional field. Prior to the variable field, a process field type needs to be added, allowing the user to select the exact process the data will be pulled from.
The calculation formula in the variable field should then be:
ProcessFieldIdentifier.SystemFieldIdentifier
In this example, ProcessFieldIdentifier is the identifier of the process field type while SystemFieldIdentifier is the variable field identifier that is housing the data being pulled.
In the record template, a field is configured with the field name Choose Product:
An alphanumeric field is then created with the formula expression:
ChooseProduct.Status
This will provide an output as a string of one of the four available statuses of the user selected process: In Progress, On Hold, Completed, Voided.
System field identifiers that can be used in the Formula Expression of an alphanumeric field to return a string output include:
System fields identifiers that can be used in the Formula Expression of a number field to return a number output include:
System field identifiers that can be used in the Formula Expression of a datetime field to return a date and time output include:
System field identifiers that can be used in the Formula Expression of a user field to return an output of the user's first and last name include:
Stage run data can be accessed through the system fields listed below using the stage identifier. To access this data you need to create a field in the record template with the appropriate formula expression. The field type must be: alphanumeric, number, datatime, or user.
If data is pulled from the stages of the current process, the formula expression should be:
Stage[StageIdentifier].SystemFieldIdentifier
In this example, no stage run is added after StageIdentifier in the expression so the system will pull back information from the latest run.
To pull data from a specific run, add a numerical value to the expression:
Stage[StageIdentifier,1].SystemFieldIdentifier
In this example, the expression will access the data from the first stage run.
If data is pulled from a different process, the record template needs to include an additional field. Prior to the variable field, a process field type needs to be added, allowing the user to select the exact process the data will be pulled from.
The calculation formula in the variable field should then be:
ProcessFieldIdentifier.Stage[StageIdentifier].SystemFieldIdentifier
In this example, ProcessFieldIdentifier is the identifier of the process field type, Stage[StageIdentifier] is the identifier of the latest stage run, and SystemFieldIdentifier is the variable field identifier that is housing the data being pulled.
System field identifiers that can be used in the Formula Expression of an alphanumeric field to return a string output include:
System field identifiers that can be used in the Formula Expression of a yes/no or checkbox field to return a boolean output include:
System field identifiers that can be used in the Formula Expression of a number field to return a number output include:
System field identifiers that can be used in the Formula Expression of a datetime field to return a date and time output include:
System field identifiers that can be used in the Formula Expression of a user field to return an output of the user's first and last name include:
Once the Application Testing stage is complete, the process moves to the Lab Work Review stage. In Lab Work Review a user wants to know the effort spent on the previous stage.
The Lab Work Review record template will need to be configured with a field:
In the Formula Expression of this field, write:
Stage[ApplicationTesting].TotalEffortSpent
In this expression, [ApplicationTesting] is the identifier of the Application Testing stage while TotalEffortSpent is the system field identifier that will output the hours logged by users to complete the stage.
Record data can be accessed through the system fields listed below using the record field or record template identifier. To access this data a field needs to be created in the record template with the appropriate formula expression. The field type must be: alphanumeric, number, datatime, or user.
If the data is pulled from the current process, the formula expression should be:
Record[RecordTemplateIdentifier].SystemFieldIdentifier
This expression will pull back data from the last record created in the system.
If data is pulled from a different process, the record template needs to include an additional field. Prior to the variable field, a record field type needs to be added, allowing the user to select the exact process the data will be pulled from.
The formula expression in the variable field should then be:
RecordTypeFieldIdentifier.SystemFieldIdentifier
System field identifiers that can be used in the Formula Expression of an alphanumeric field to return a string output include:
System fields identifiers that can be used in the Formula Expression of a number field to return a number output include:
System field identifiers that can be used in the Formula Expression of a datetime field to return a date and time output include:
System field identifiers that can be used in the Formula Expression of a user field to return an output of the user's first and last name include:
System field identifiers that can be used in the Formula Expression of a process field to return a process reference output include:
Id: unique identification number of the record (visible in the URL also)
In the Formulation stage, three Formulation records (Formulation 1, 2, and 3) have been created using the same record template using the identifier, FormulationRecord.
In a subsequent stage, Lab Work Review, a user may want to access system data for the second Formulation record, Formulation 2.
The Lab Work Review record template will need to be configured with a field:
In the Formula Expression of this field, write:
Stage[Formulation].Record[FormulationTemplate,2].CompletedOn
This expression will give the user the date and time of when Formulation 2 was created.
User data can be accessed through the system fields listed below using the user field type identifier. To access this data an alphanumeric field needs to be created in the record template with the appropriate formula expression:
UserFieldTypeIdentifier.SystemFieldIdentifier
System field identifiers that can be used in the Formula Expression of an alphanumeric field to return a string output include:
In a stage, Request Review, a field can be added to the record template to provide user information for the person listed as completing a prior stage, Technical Call.
The Approve record template within the Request Review stage will need to be configured with a field:
In the Formula Expression of this field, write:
Stage[TechnicalCall].CompletedBy
This will return information about who completed the Technical Call stage.
An alphanumeric field then needs to be added, with a Formulation Expression:
TechnicalCallResponsible.Email
Accessing system data can be achieved at the Process, Stage, or Record level using the expressions listed below:
Any process data can be accessed using:
Stage run data can be accessed using:
Specific stage run data can be accessed using:
Record data can be accessed using:
Tips and Tricks:
When you are trying to access data from a record that is in the current process you are in, make sure that the record template of that record is added to the process template of the process you are currently in. This is the case when you are using square brackets in the formula expressions.
Operators are symbols or expressions that use two inputs, one on each (left and right) side of the operator. Spaces are allowed between the inputs and the operators. If an operation is defined in an expression on an unsupported type, an error is generated. Below you can find the lists of operators.
AND - An operator used to check two Boolean expressions. It only returns true if both of the expressions are true.
Examples:
(6 > 3) AND (2 < 5)
The output is true because both of the expressions are true.
(‘text’ == ‘tekst’) AND (3 < 5)
The output is false because only the second expression is true.
The Lab Manager wants to continue from the Lab Work stage to the Report stage. In the Lab Work Review stage there are two questions at the end.
Question 1: More formulations needed?
Question 2: Is the review finished?
The first question needs to be false and the second question true to transition to the Report stage. The transition condition set up in the When field of the Actions for the stage will be:
MoreFormulations == false AND ReviewFinished == true
OR - An operator used to combine two Boolean expressions. It returns true if at least one of the expressions is true.
Examples:
(ProductPrice < ProductRecommendedPrice / 2) OR (ProductPrice > 0)
The value of field ProductPrice equals 3 and you have another field called ProductRecommendedPrice whose value equals 2. The expression will return true because at least one of the expressions is true, in this case the second one. Note that the expression would still return true if both statements had been true.
('text' == 'nottext') OR ('ciao' == 'stillnotciao')
The expression will return false because both expressions are false.
When using the logical operator OR, if the left operand is true, the right operand is not evaluated.
NOT - An operator that negates the specified Boolean expression. It returns true if the operand is false, otherwise false.
Examples:
NOT('text' == 'hallo')
The expression will return true.
NOT(true)
The expression will return false.
IN - An operator that checks whether all values of the left operand are contained in the right operand. It returns true if all the values present in the left operand are contained (are a subset) of all the values in the right operand. Otherwise, false is returned.
The left and right operand can be a single constant, enumerated constants in brackets, a single field, a single field with multiple values (multiple, column, or multiple columns), or an enumerated field in brackets.
If the left and right operands are of different types, a warning is generated.
If the left operand is empty, it returns true. If the right operand is empty, it returns false.
Example:
'Liquid' IN TypeOfSample
The expression will return true if one of the values for the field TypeOfSample is 'Liquid'
NOT IN - An operator that is a negation of IN. It returns true if all the values present in the left operand are not contained (are not a subset) of all the values in the right operand. Otherwise, false is returned.
Left and right operands can be a single constant, enumerated constants in brackets, a single field, a single field with multiple values (multiple, column, or multiple columns), or an enumerated field in brackets.
If left and right operands are of different types, a warning is generated.
If the left operand is empty, it returns false. If the right operand is empty, it returns true.
In the Formulation stage there is a list of formulations that needs to be made. That list is in the repeatable row group table.
The second column is Status:
Below the table, there is a checkbox labeled: "All formulations are done".
Chemists are able to go to the Characterization stage only when all formulations are done and the checkbox is checked.
This is possible by writing the following expression in the Formula Expression field of the checkbox:
IFS(('In Progress' NOT IN Status AND 'Pending' NOT IN Status), true, true, false)
This expression formula will check the checkbox only when ‘In Progress’ and ‘Pending’ are not in the column labeled Status, and leave it unchecked if the opposite is true. The IFS function will be explained below.
IS SET - An operator that checks whether a value of a field is set. Returns true if the supplied operand contains at least a single value, otherwise false.
If defined to be used on a constant it always returns true and generates a warning during configuration.
Example:
ModificationsApplied IS SET
The expression will return true if the value for the field ModificationsApplied is set.
NOT SET - An operator that checks whether a value of a field is set. Returns false if the supplied operand contains at least a single value, otherwise true.
If defined to be used on a constant it always returns false and generates a warning during configuration.
Example:
ModificationsApplied NOT SET
The expression will return true if the value for the field ModificationsApplied is not set.
IS VALID - An operator that checks if there is any value error at the field template. Returns true if there is no value error, otherwise false.
Example:
FieldIdentifier IS VALID
NOT VALID - An operator that checks if there is any value error at the field template. Returns true if there is a value error, otherwise false.
Example:
FieldIdentifier NOT VALID
Greater Than ( > ) - This operator determines whether the first value is greater than the second value. Returns true if the left operand is greater than the right operand, otherwise false (null value is treated as 0).
Examples:
5 > 3
Returns true.
pH1 > pH2
Returns false if the value of the pH1 field is 2.3 and the value for the pH2 field is 2.4.
Greater or Equal ( >= ) - This operator checks if the left operand is greater than or equal to the right operand. Returns true if the left operand is greater than or equal to the right operand, otherwise false.
Examples:
5 >= 3
Returns true.
3 >= 3
Returns true.
pH1 >= pH2
Returns false if the value of pH1 field is 2.3 and the value for pH2 field is 2.4.
Less Than ( < ) - This operator determines whether the first value is less than the second value. Returns true if the left operand is less than the right operand, otherwise false.
Examples:
5 < 6
Returns true.
pH1 < pH2
Returns false if the value of pH1 field is 2.4 and the value for pH2 field is 2.3.
Less Than or Equal To ( <= ) - This operator checks if the left operand is less than or equal to the right operand. Returns true if the left operand is less than or equal to the right operand, otherwise false.
Examples:
5 <= 6
Returns true.
5 <= 5
Returns true.
pH1 <= pH2
Returns false if the value of pH1 field is 2.4 and the value for pH2 field is 2.3.
Is Equal To ( == ) - This operator determines whether the two values are equal. Returns true if the left operand is equal to the right operand, otherwise false.
Text values are equal if all the characters are the same (comparison is case sensitive) and the text is of the same length. If the value of both operands is null value or an empty string, equals returns true.
Numbers are equal if the numeric value is the same, regardless of the precision. (i.e. 1 == 1.000 will return true).
Boolean is equal if both operands have the same value (true and true, false and false).
Date comparison returns true if every part of the date is the same. Namely, equals returns true if the day, month and year part of the date is the same for both operands, false otherwise (comparison is done in UTC - Coordinated Universal Time).
Link comparison works the same as a text comparison.
File comparison (when attachment field types are compared) returns true if both operands contain the same file path, false otherwise.
Process reference comparison returns true if both operands contain the same process ID, false otherwise.
Record reference comparison returns true if both operands contain the same record ID, false otherwise.
Stage reference comparison returns true if both operands contain the same stage name, false otherwise.
User reference comparison returns true if both operands contain the same user ID, false otherwise.
If empty fields are compared (Null values - no value present) comparison returns true.
Comparison between two operands of different types always returns false, a validation error is generated.
Example:
a == b
Is Not Equal To ( != ) - This operator determines whether the two values are not equal. It works like the exact opposite of the Is Equal To operator.
Example:
a != b
Assign operator ( = ) - This operator is used to assign the value from the expression on the right side to the variable on the left side.
Examples:
Addition/Concatenation ( + ) - This operator adds two numbers or concatenates two strings, depending on the operand type.
If two numbers are added together, the resulting number is the sum of the operands with the precision of the number with the highest precision.
If two string values are added together, the result is a string value formed by concatenating the two operands.
When you concatenate two alphanumeric fields, as a result you will see values of those fields glued together. In order to avoid that, add an empty string in the Formula Expression (i.e. FieldIdentifier1 + ' ' + FieldIdentifier2).
If a number and string value are added together, the resulting value is a string that is made by concatenating the string and the string representation of the number (decimal places format is conserved in string conversion).
If the addition results in a number that is higher/lower than the target field defined max/min, an error will be shown by the frontend validator (i.e. if you adjust min and max for the pH field as 1 and 14. An error will be shown in case that pH1 + pH2 = 14.2 since it is greater than 14)
If the addition results in a number greater than 2,147,483,647 an out-of-range error is shown.
If the addition result is a number smaller than -2,147,483,647 an out-of-range error is shown.
Same principle for strings; error is shown if a string is too long, otherwise, if it is longer than the string it is shortened with “...” appended.
If any of the other operands supported types is used with this operator, the values are converted to their string representation and concatenation of string values is performed.
Examples:
NumberFieldA + NumberFieldB
Returns a number.
TextFieldA + ' : ' + TextFieldB
Returns a string.
RecordIdentifier.NumberFieldIdentifier + 3.5
Returns a number.
Subtraction ( - ) This operator subtracts the second operand from the first.
If two numbers are subtracted, the resulting number is the result of subtraction of the second operand from the first operand. The result is a number with the precision of the operand with the highest precision.
If subtraction results in a number that is higher/lower than the target field defined max/min, an error will be shown by the frontend validator.
If subtraction results in a number greater than 2,147,483,647, an out-of-range error is shown.
If subtraction results in a number smaller than -2,147,483,648, an out-of-range error is shown.
Examples:
NumberFieldA - NumberFieldB
Returns a number.
NumberFieldA - 1
Returns a number.
EndDate-StartDate
Returns a number (the subtraction must happen in a number type field).
Multiplication ( * ) - This operator multiplies two numbers.
If two numbers are multiplied, the resulting number is the result of the multiplication of the two operands. The result is a number with the precision of the operand with the highest precision.
If multiplication results in a number that is higher/lower than the target field defined max/min, an error will be shown.
If multiplication results in a number greater than 2,147,483,647, an out-of-range error is shown.
If multiplication results in a number smaller than -2,147,483,648, an out-of-range error is shown.
Examples:
NumberFieldA * NumberFieldB
Returns a number.
NumberFieldA * 3
Returns a number.
Division ( / ) - This operator divides two numbers.
If two numbers are divided, the resulting number is the result of dividing the left operand with the right operand. The result is a number with the precision of the operand with the highest precision.
If division results in a number that is higher/lower than the target field defined max/min, an error is shown.
If division results in a number greater than 2,147,483,647, an out-of-range error is shown.
If division results in a number smaller than -2,147,483,648, an out-of-range error is shown.
If the right operand is 0, a divide by zero result is returned.
Examples:
NumberFieldA / NumberFieldB
Returns a number.
NumberFieldA / 3
Returns a number.
Negation ( # ) - This operator changes the sign of the number, transferring it from negative to positive or vice versa.
Examples:
#(-2)
The result is 2.
#NumberFieldA
Returns a number.
MOD - This operator calculates the remainder of the division of one number by another. The result has the same sign as the divisor. Number a is the dividend, and number b is the divisor.
Example:
23%5
The result is 3.
Note: All Alchemy functions that will be listed in the following pages are available, but not applicable in all cases. Some of the functions are generated in order to help solve specific problems and use cases, and their application at the moment is not system-wide.
Functions are expressions in Alchemy that can use one or more inputs, given in brackets (), and perform complex calculations before returning the output.
IFS (condition, value...) - This function checks whether one or more conditions are met and returns the value that corresponds to the first true condition. It accepts parameters in pairs. The first parameter is a condition and must evaluate to a boolean or an error is generated. The second parameter can be a constant, variable, or another expression that must result in the same type as the field for which you are using the IFS function. The first parameter is considered an expression before the comma, and the second one is after the comma.
If the first parameter in a pair evaluates to true, the function returns the second parameter of the pair.
If IFS is defined with an odd number of parameters, an error is generated.
If IFS is defined without parameters, an error is generated.
Examples:
IFS ( a < b, a, a> b, b)
Returns a if a<b is true. If a<b is false it will check if a>b and if it is true, it will return b.
IFS ( f <=5, d * 3, (f +2 < c), IFS (f < c, 4, e>=d, d), a = b, c, f >= 250, d + 1)
An example of nested IFS functions: If the first condition (f<=5) is false and the second condition (f +2 < c) is true then it will start evaluating second IFS function conditions.
See an example of the IFS function in the Configuration Portal Administrator Manual, section 4.6.3 - Formulas in Calculations.
SQRT ()- A function that calculates the square root of the number. When performed on an operand, it finds the square root of the number.
If the operand is negative, it returns an error.
If performed on an empty value, it returns a 0.
If the square root is used on a negative constant, a warning is shown.
If the square root is used on a number whose minimum is less than 0, a warning is shown.
Examples:
SQRT(NumberField)
Returns a number.
SQRT(NumberFieldA + NumberFieldB)
Returns a number.
SQRT(144)
The result is 12.
POW ()- A function that calculates the result of a number raised to a power. It returns the value of the first operand (before the comma) being raised to the power of the second operand (after the comma).
Examples:
POW(NumberFieldA, 2)
Returns a number.
POW(3*NumberFieldA, 3)
Returns a number.
POW(10, 2)
The result is 100.
ABS () - A function that returns the absolute value of a number or the operand (value without the sign).
Examples:
ABS(NumberFieldA)
Returns a number.
ABS(-15)
The result is 15.
SUM () - A function that returns the sum of all the values of a multiple value field, or all the values in a column. It adds all the values of the specified field or constant.
If used on a constant number, the result is that number. If used on a single value field that belongs to a simple type group, a warning is issued during configuration. In that case, the SUM will return the value of that field. If used on a constant, a warning is issued.
If used on a number field that is marked as multiple, all the values are added together and returned.
If used on a single value number field in a table (repeatable row or repeatable column group) all the values in all the rows are added together.
If used on a multiple value number field in a table, all the values in all the rows and all the multiple values within a single cell are added.
Examples:
SUM(15)
The result is 15.
SUM(NumberFieldA)
Returns a number.
LOG () - A function that calculates the logarithm (base 10) of the value in the argument.
Examples:
LOG(100)
The result is 2.
LOG(NumberFieldA)
Returns a number.
LOG(NumberFieldA/NumberFieldB)
Returns a number.
COUNT () - A function that counts all the values of a multiple value field or all the values in a column. This function counts all the values of the specified field or constant.
If used on a single value field that belongs to a simple type group, a warning is issued during configuration. It will return 1 if there is a value, 0 otherwise. If used on a constant, a warning is issued.
If used on a field that is marked as multiple, all the values are counted.
If used on a single value field in a table (repeatable row or repeatable column group) all the values in all the rows are counted.
If used on a multiple value field in a table, all the values in all the rows and all the multiple values within a single cell are counted together.
Examples:
COUNT(15)
The result is 1.
COUNT(FieldIdentifier)
Returns a number.
ROW_COUNT () - A function that counts rows or columns of a certain field.
If it is used on a constant, the result is 1. If it is used on a single value field (multiple=false) that belongs to a group that is a single type, a warning is issued during configuration. It will return 1 if there is a value, 0 otherwise.
If it is used on a field that is marked as multiple (multiple=true, groupType=SINGLE) the result is 1.
If it is used on a single value field in a table (multiple=false, group type != SINGLE) the result is the number of rows or columns.
If used on a multiple value field in a table (multiple=true, group type != SINGLE) the result is the number of rows or columns.
Examples:
ROW_COUNT(FieldIdentifier)
Returns a number.
AVERAGE () - A function that calculates the average (arithmetic mean) of all the values of a multiple value property or all the values in a column. This function works by adding together all the number values and then dividing them by the number of values. It calculates the average of the specified number field or constant.
If used on a constant number, the result is that number. If used on a single value field that belongs to a simple type group, a warning is issued during configuration. It will return that number as a result. If used on a constant, a warning is issued.
If used on a field that is marked as multiple, all the values are added together and divided.
If used on a single value field in a table (repeatable row or repeatable column group) all the values in all the rows are added together and divided.
If used on a multiple value field in a table, all the values in all the rows and all the multiple values within a single cell are added together and divided by the total count of all the values.
It is identical to SUM(NumberField)/COUNT(NumberField).
Examples:
AVERAGE(15)
The result is 15.
AVERAGE(NumberField)
Returns a number.
TODAY () - A function that returns the current date, in UTC, and can be parameterized optionally.
When defined without parameters, it returns the current timestamp without seconds.
When defined with parameters, the first parameter represents offset in days, the second represents hours and the third represents minutes (i.e. TODAY(2, 0, 0 ) will return a UTC date that is two days from now. TODAY(0, -1, 0) will return a UTC date that is one hour in the past.).
If a parameter is not supplied, it is assumed to be 0.
When a non-integer number is supplied as a parameter, a warning is generated.
Examples:
TODAY()
Returns current UTC date and time, i.e. 2022-04-06T20:40:50Z
TODAY(2)
Returns a day after tomorrow's UTC date and time, i.e 2022-04-08T20:40:50Z
TODAY(0, -1, 0)
Returns a UTC date and time that is one hour in the past, i.e. 2022-04-06T19:40:50Z
Whenever you need a date & time type of field to be filled in by today's date you can use this function. Write TODAY in the Formula Expression of the field type datetime. You should check the "Editable" checkbox in the Functions tab of that field, so if needed, the user in the User Portal can change the date of today to some other date.
DATE FORMAT () - A function that returns a text representation of a date input based on the supplied format.
The first parameter is the Date and Time variable.
The second parameter is the format, provided as a string. You can use any of the formats available as explained in Section 4.4.4. - Field Types, Date &Time Field of the Configuration Portal Administrator Manual.
Examples:
DATE_FORMAT(ProjectStartDate, 'YY-MM-DD')
The result is a text representation of the date value of ProjectStartDate field, i.e. 22-04-06.
DATE_FORMAT(Process.CreatedOn, 'EEEE, MMMM d, y')
The result is a text representation of the date value of Process.CreatedOn system data, i.e. Wednesday, April 6, 2022.
ROUND () - This function rounds the number to a given precision. It is rounded using half-up mode (i.e. everything above 12.5 will be shown as 13, and everything below 12.5 will be shown as 12. If the number that is rounded is 12.5, 13 will be shown).
Rounds the first operand to the number of digits supplied in the second operand.
If the second operand is less than 0, 0 is returned as a result.
When the rounding has more digits than the source number (first operand), the resulting number has its precision increased.
Examples:
ROUND(12, 2)
The result is 12.00.
ROUND(12.5, 0)
The result is 13.
ROUND(NumberField, 4)
Returns a number with 4 decimal places.
ROUND(NumberFieldA, NumberFieldB)
Returns a number with the number of decimals determined by the value of NumberFieldB.
TRANSITION_FROM () - This function checks whether the activation path is coming from the selected stage. It returns true if stage activation is coming from the specified stage, false otherwise. The function can only be used in process template rules (i.e., in conditions for actions). An error is generated if used in other types of expressions.
Example:
TRANSITION_FROM(Stage[Requirements])
The result is true if the stage is activated from the stage Requirements, otherwise it will return false.
Request Review in the Lab Work process can be done after the Request stage or after the Technical Call stage. The Lab Manager needs to get the task with a different subject for review. One subject should be when the task is created after the Request stage and the other subject when the task is created after the Technical Call stage. In order to set up those tasks, you need to add two Create Task actions on the Request Review stage.
In the first one in the When you will write TRANSITION_FROM(Stage[Request]) and the Task Subject you will fill in with the 'Review the Lab Work Request for ' + Process.Name.
In the second one in the When you will write TRANSITION_FROM(Stage[TechnicalCall]) and the Task Subject you will fill in with the 'Review the Lab Work Request for ' + Process.Name + ' - technical call is done'.
HAS_ANY_TAG () - A function that returns a list of users that have any of the supplied tags.
If no tags are supplied a warning is generated.
If the same tag is passed multiple times a warning is generated.
Example:
HAS_ANY_TAG(Tag[SalesDirector], Tag[President])
Returns a list of users who have the tag SalesDirector or the tag President.
HAS_ALL_TAGS () - A function that returns a list of users that have all of the supplied tags.
If no tags are supplied a warning is generated.
If the same tag is passed multiple times a warning is generated.
Example:
HAS_ALL_TAGS(Tag[SalesDirector], Tag[VPMarketing])
Returns a list of users who have the tag SalesDirector and the tag VPMarketing.
INTERSECT () - A function that finds the intersection between multiple lists of the same type. Only the values that are found in all the supplied lists are returned.
Example:
INTERSECT(HAS_ALL_TAGS(Tag[Thermosets], Tag[TechnicalService]), HAS_ANY_TAG(Tag[Manager], Tag[Representative]))
Returns a list of users who have the tags Thermosets and TechnicalService, and have the tag Manager or Representative.
UNION () - This function calculates the union between multiple lists of the same type. All the values that are found in all the supplied lists are returned. List members are not repeated if found multiple times.
Example:
UNION(HAS_ANY_TAG(Tag[Chemist], Tag[SynthesisLab]), HAS_ALL_TAGS(Tag[LabManager]))
Returns a list of users who have the tag Chemist or SynthesisLab or LabManager.
CREATED_BY () - This function determines if the process has been created by supplied users. It returns true if one of the supplied users has created the process, false otherwise.
Example:
CREATED_BY(Tag[SalesDirector]) OR CREATED_BY(Tag[LabManager])
Returns true if the process was created by a user with tag SalesDirector or LabManager, otherwise it returns false.
PATTERN () - This function returns an auto-incremented pattern based on the supplied pattern in the operand. A defined pattern supports letters (acbd, etc.), digits (1234, etc.), and date and time. The maximum length of this field is 255 characters. We support single pattern definition; if multiple patterns are defined in a formula, an error is generated. If you need a pattern to start from a specific number you can use the following expression: PATTERN('NN','41'), where 41 can be any two digits number.
Each time you reach the "end" of the pattern, the pattern will restart from the beginning. So if you use N for single digits, when N reaches 9, it will start from the 1 again; the same thing applies for letters.
This does not apply to the time-based pattern values, since their values are dependent on the current date and time, but changes in these values influence the resetting of the values from there (i.e., if you are counting Lab Works per date, the pattern would start from the beginning with the new day). Date values are calculated in the time zone from which the request is coming from.
Also, it does not apply when using n as an infinite digit pattern. Small n will start from 1 (or any other value if it’s specified as the second parameter of the PATTERN function and third parameter of the KEY_PATTERN function) and will be increased by 1 up to max value of 2,147,483,647. It does not have leading zeros.
Examples:
'Sample ' + PATTERN('ANN')
The first instance returns text ‘Sample A01’.
'Shipment ' + PATTERN('YYYY-MM-DD-NN')
The first instance returns text, i.e. 'Shipment 2022-04-06-01’.
'Lab Trial ' + PATTERN('n')
The first instance returns text, i.e. 'Lab Trial 1’; The 15th instance returns text, i.e. 'Lab Trial 15’.
In Alchemy Laboratory each Lab Work process is registered by a unique predefined pattern. It is done by defining a formula expression in the naming field (a field that gives a name to the process started, located in the first record of the first stage of the process; Identifier: Name) with the following expression:
'LW-' + LWNumber + '' + LWDescription
LWNumber is the identifier of an alphanumeric field where the pattern function is used under the formula expression:
PATTERN('YYYY-MM-NNN')
LWDescription is the identifier of an alphanumeric field where the user can enter a short description of the process started.
When creating a new process, it will automatically be titled “LW-2021-09-001 ‘description entered’ “ (for the first process in September). The following one will be named “LW-2021-09-002 ‘description entered’ “, etc. If by the end of September there are 999 Lab Works, counting will start again from 001. The first Lab Work in October will be titled “LW-2021-10-001 ‘description entered’ “.
You cannot have more than one PATTERN() formula in an expression. i.e. PATTERN('YYYY') + PATTERN('NNN') is not a valid expression. If you need to join two patterns, write the expression in two separate fields, and concatenate the strings in a third.
KEY_PATTERN () - This function returns an auto-incremented pattern based on the supplied pattern in the operand.
The first parameter defines the prefix (in further text KEY) for the pattern, and the prefix can be a constant or field value.
The second parameter is the pattern value and the same rule can be applied to the PATTERN function.
The third parameter is optional. It defines which value is the starting point from which pattern should count and can be a constant or field value.
Examples:
TextField + KEY_PATTERN(Textfield, ’NNN’)
Returns the pattern value together with the KEY.
KEY_PATTERN(TextField, ’N’)
Returns only the pattern value.
KEY_PATTERN('Text', 'NN', '23')
Returns pattern value starting from 23.
The value of KEY_PATTERN will reset with the change of KEY. If the configurator decides to return the previous KEY in the calculation, the pattern will continue to calculate from the last value that KEY returned before the change is made.
One formulation can be tested multiple times. In order to distinguish between these different test results, you can use the KEY_PATTERN function to name different Characterization Tests records.
In the Characterization Tests record template there is a field Related To Formulation (identifier RelatedToFormulation), where formulations displayed are filtered only to those created in the current process.
You need to add an alphanumeric field, identifier CharacterizationKeyNumber.This field should be hidden because it only helps you to name Characterization Tests records in the process. The Formula Expression of this field should be:
RelatedToFormulation + KEY_PATTERN(RelatedToFormulation + '', 'N.N')
Under the Lab Work Stage, under the Records tab, choose the Characterization Tests and in the Naming Pattern use the value of the field CharacterizationKeyNumber. This way, if you have more Characterization Tests records created for the same RelatedToFormulation field value, they will have different names. The difference will be in the number given by the KEY_PATTERN function: 0.1, 0.2, 0.3, etc.
The KEY_PATTERN function is a powerful tool. You can change the KEY, and reset the counter. If you change the KEY back to the previous value, it will not reset the counter again but continue from the value when it was changed for the first time. See the following example.
In the Alchemy Lab, final products receive a number based on the Product Type. The Product Number is an alphanumeric field with the formula expression:
ProductType = KEY_PATTERN(ProductType, 'NNN')
However, the new R&D director decided that the product should receive a number based on the Industry Type where it is applied. In that case, the new formula expression in the Product Number field will be:
IndustryType + KEY_PATTERN(IndustryType, 'NNN')
The first new product will have the number 001 for a certain Industry Type no matter if it is from the Product Type where the next number would be 029. The reason is that KEY is changed.
After a while the new R&D director realized that the previous product naming convention was more efficient. He asked a configurator to change Product Numbers so they again depend on the Product Type. After the formula expression in Product Number is returned to
ProductType = KEY_PATTERN(ProductType, 'NNN')
numbers will count from the number where they stopped before the change was made (the product from the certain type will have the number 030).
STAGE_COMPLETED_BY () - This function determines if the stage has been completed by supplied users. It returns true if one of the supplied users has completed the stage, false otherwise.
Example:
STAGE_COMPLETED_BY(Tag[SalesDirector])
Returns true if the stage was completed by a user with tag SalesDirector.
RUN_COUNT () - This function returns the number of runs the given Stage has.
Example:
RUN_COUNT(Stage[Review])
Returns the number of runs for the stage, Review.
CONVERT UNIT - This function converts the provided number value in the desired unit.
UnitField and UnitFieldToConvert are alphanumeric values, which have to be exact with defined units in the system, otherwise an error will be thrown.
In case UnitFieldToConvert is not provided, the result of conversion will be the same as a value of ValueToConvertField.
In case there is conversion from one Unit Type to another additional parameter needs to be defined as JSON object in form like:
var a = { “unitType”: { “value”: unitTypeValueVariable, “unit”:
unitTypeUnitVariable } }
CONVERT_UNIT (ValueToConvertField, UnitField, UnitFieldToConvert, a);
Example:
CONVERT_UNIT(ValueToConvertField, UnitField, UnitFieldToConvert);
var a = { "density": { "value": DensityValueVariable, "unit": DensityUnitVariable } }
CONVERT_UNIT(100, ‘g’,’ml’, a);
The accepted abbreviations for some of the units are given below. The details on the units’ abbreviations were based on this Source.
Abbreviations: 'mg',' g',' kg', 'gr',' lb', 'dr',' oz', 't', 'ton', 'ml', 'dl', 'cl', 'l', 'm3', 'gal', 'hl', 'tsp', 'tbsp', 'fl oz', 'cup', 'pt', 'qt', 'g/ml', 'g/dl', 'g/cl', 'g/l', 'g/m3', 'kg/ml', 'kg/dl', 'kg/cl', 'kg/l', 'kg/m3', 'lb/gal', 'lb/pt', 'lb/qt', 'oz/gal', 'oz/pt', 'oz/qt'
The following functions are used only in writing Alchemy scripts (buttons, stage execute script and On Change action scripts), not in formula or visibility expressions:
SIGNED_IN_USER () - This function returns the REFERENCED_USER which is signed in. It is only available to use in the action expression of the button field or on the field action.
Example:
UserField = SIGNED_IN_USER()
Returns the user who is signed in.
CREATE_PROCESS () - This function creates a new process or processes of the provided process template. The first parameter is the Process Template Identifier. The second parameter is the number of processes to be created.
Example:
CREATE_PROCESS('LabWork',1)
Creates a new process from the Lab Work process template and returns the created process.
CREATE_RECORD () - This function creates a new record or records of the provided Record Template. Record Templates configured to generate records outside of the process (solo records) can also be created by this function. In that case, second and third parameters should not be added to the expression.
The first parameter is Record Template Identifier, from which we want to create a new instance.
The second parameter is Stage Identifier, which defines at which stage we want to create a new record instance. This parameter is optional.
The third parameter is the Process Identifier which defines in which Process we want to create a new record instance. Using the reserved word ‘Process,’ the record instances will be created in the current process. This parameter is optional.
The fourth parameter is the number, which defines how many record instances we want to create.
Examples:
CREATE_RECORD(‘Formulation’, ‘LabWork’, Process,1)
Creates a new Formulation record in the Lab Work stage of the current process and returns the created record.
CREATE_RECORD(Material, 1)
Creates a new Material solo record and returns the created record.
ADD_ROW () - A function for adding a row in a group.
The First Parameter is a Group Identifier, which defines which group we want to add rows to.
The Second Parameter is the number, which defines how many rows we want to create.
Examples:
ADD_ROW(GroupIdentifier, 1)
Adds one row to the group determined by the GroupIdentifier.
ADD_ROW(GroupIdentifier, Group1.RowCount)
Adds the number of rows determined by the number of rows in Group1 to the group determined by the GroupIdentifier.
GET_RECORD () - A function that returns referenced record value, depending on passed record ID.
Examples:
GET_RECORD(IdOfRecord)
Returns the record with ID determined by the field IdOfRecord.
GET_RECORD(5)
Returns the record with ID 5.
CREATE_TASK () - This function creates a new task on the defined stage.
It receives next parameters comma separated:
The order of parameters defined must be as it is listed above.
The function will be executed only if all requirements are met (Stage is active, assignees have Can Edit privilege, etc.)
- Example:
CREATE_TASK(Process.Stage[LabWork], 'Title for the Task From a Script', 'This is a description for the task from a script', TODAY(), DateTimeField, 1, HAS_ANY_TAG(Tag[SalesDirector]))
Returns a new Task.
CREATE_COMPARE () - This function creates a new Compare Records.
It receives next parameters, comma separated:
Examples:
CREATE_COMPARE(Process.Stage[LabWork], ‘LabRecord’, [‘NumberField’, ‘TextField’], [‘TextField’], Record[LabRecord])
Returns a Compare Records.
CREATE_COMPARE(Process.Stage[LabWork], ‘LabRecord’, [‘NumberField’, ‘TextField’], [‘TextField’], RecordField)
Returns a Compare Records.
CREATE_VIEW () - This function creates a new View in a stage, from the View Template with predefined fields and filters.
It receives next parameters, comma separated:
Note that all parameters can be calculated using an expression. It is not necessary to put an explicit value for numbers, strings, etc. Calculation rules apply.
Standard field keyword table:
Filter comparison type list:
Example:
var filterParam = [
{
'node' : '1',
'fields' : [
{
'name' : 'PRIORITY',
'visible' : true,
'filters' : [
{
'type' : 'IS_BETWEEN',
'from' : 5 , 'to' : 15
}
]
}
]
} , {
'node' : '3',
'fields' : [
{
'name' : 'RECORD_ID'
'visible' : false,
'filters' : [
{
'type' : 'IS_ANY_OF',
'values' : [Record[LabWork], ReferenceRecordInRR, Record]
}
]
} , {
'name' : 'NumberField' ← note that this is an identifier string, so it has ‘ ’
'visible' : true,
'precision' : 3,
'filters' : [
{
'type' : 'IS_GREATER_THAN_OR_EQUAL',
'values' : [SomeOtherNumberField] ← number calculation, no ‘ ’
}
]
}
]
}
];
CREATE_VIEW(Stage[LabWork], 'View1', 'View From Button', filterParam);
SEND_EMAIL () - This function sends email to the specified user(s). CAUTION: Usage of this function needs to be carefully tested since sending email cannot be undone.
param1 is the email recipient. It can be an email address as a string, or any expression returning user reference.
param2 is the subject of email (string).
param3 is the body of email (string).
Example:
SEND_EMAIL(‘const1@mail.com’, ‘mail subject’, ‘mail body’);
SEND_EMAIL(‘const1@mail.com, const2@mail.com’, ‘mail subject2’, ‘mail body2’);
SEND_EMAIL([‘const3@mail.com, const4@mail.com’], ‘mail subject3’, ‘mail body3’);
SEND_EMAIL(UserField.Email, ‘mail subject4’, ‘mail body4’);SEND_EMAIL(UserField, RecordName + ‘ send as user 5’, RecordName + ‘ 5’);
SEND_EMAIL(UserFieldInGroup, RecordName + ‘ send as a user in group 6’, RecordName + ‘ 6’);
SEND_EMAIL(HAS_ANY_TAG(Tag[SalesDirector]), ‘mail subject 7’, ‘mail body7’);
If(){} else {} - If expressions can be used to define conditional actions in expressions. The correct syntax is the following: If(condition){ block of code } else { block of code}.
Examples:
if(CustomerType == ‘Prospect’){ NewCallDate = TODAY (4); }
Only if the value of the CustomerType field is Prospect, then it will set the value of the NewCallDate to be 4 days from now.
if(NumberA > 3){ CalcNumber = NumberA*3.14; }
else { CalcNumber = NumberA/3.14; }
If the value of the NumberA field is bigger than 3, then the value of the CalcNumber will be calculated from the value NumberA * 3.14, else the value of the CalcNumber will be calculated from the value NumberA / 3.14.
for() {} - A For loop is used to define the number of executions (iterations) of a defined code block (calculations/commands). It is used to access values of fields with multiple values or fields in repeatable groups.
The correct syntax is the following: for(var i=n; i<=m; i=i+k){code bloc}
Example:
• for(var i=NumberField; i<=5;i=i+2){code bloc}
• for(var i=1; i<=Group1.RowCount;i=i+2){code bloc}
RECALCULATE_PRIVILEGES() - This function can be used in action scripts when it needs to recalculate privileges when you need to change them (for example, when you need to mark a record as “confidential”).
Examples:
RECALCULATE_PRIVILEGES(Process)
Initiates access rights recalculation for the active process.
RECALCULATE_PRIVILEGES(Record)
Initiates access rights recalculation for the standalone records.
CREATE_LINK() - This function is used in the calculation of the link type field to generate a new link.
The first parameter is the target URL, written as a string under the single quotes. Other links can be added (again as a string) using the concatenation function (+ function) if you want the link to have a dynamic value.
The second parameter is the name of the link that will be displayed inside the link field.
Examples:
CREATE_LINK('https://www.alchemy.cloud/alchemy-knowledge-center/home', 'Alchemy Knowledge Center')
CREATE_LINK('https://pubchem.ncbi.nlm.nih.gov/#query=' + CasNumber , 'PubChem Link')
Where CASNumber is an identifier of an alphanumeric field in the same record template where the link field is. The output link is a dynamic value that depends on the CASNumber entry.
CREATE_RECORD_ASYNC - This function is used to create records asynchronously. Asynchronous creation of records enables better performance.
Number of parameters: 3 mandatory and 1 optional
Examples:
Creating solo record:
var myParams = {
"newRecordName":"new record",
"newText":RecordField.AphanumericField
};
var myScript = "RecordName = newRecordName;
AphanumericField = newText;";
CREATE_RECORD_ASYNC("RecordB", myParams, myScript);
Creating record in a process:
CREATE_RECORD_ASYNC(“RecordA”,Process.Stage[Stage_1],{ "a":Record[RecordB].NumberField}, “AlphanumericField = a;”);
CREATE_PROCESS_ASYNC - This function is used to create new processes asynchronously.
Number of parameters: 3
Examples:
var myParams = {
"recordId": Record.Id
}
var myScript = "
Process.Record[RecordA].RefRecordField = GET_RECORD(recordId);
Process.Record[RecordA].RefRecordField.ProcessNameField = Process.Name;"
CREATE_PROCESS_ASYNC("ProcessA", myParams, myScript);
CREATE_SAMPLE_RECORD_ FROM_MATERIAL() - A function that is used to create a standalone Sample from the passed Material record.
Number of parameters: 1
Example:
CREATE_SAMPLE_RECORD_FROM_MATERIAL(Material)
CREATE_MATERIAL_RECORD() - A function that is used to create a Material record from the ELN & LIMS Material record template.
Number of parameters: 1
SIN() - A function that calculates the SINE of the given angle. The angle must be in radians. If you have an angle in degrees, convert it to radians by using the RADIANS function (see below).
Example:
SIN(FieldIdentifier)
Returns a number.
COS() - A function that calculates the COSINE of the given angle. The angle must be in radians. If you have an angle in degrees, convert it to radians by using the RADIANS function (see below).
Examples:
COS(1.047)
The result is 0.500171.
COS(RADIANS(60))
The result is 0.5
TAN() - A function that calculates the TANGENT of the given angle. The angle must be in radians. If you have an angle in degrees, convert it to radians by using the RADIANS function (see below).
Examples:
TAN(0.785)
The result is 0.99920.
TAN(RADIANS(45))
The result is 1.
COT() - A function that calculates the COTANGENT of the given angle. The angle must be in radians. If you have an angle in degrees, convert it to radians by using the RADIANS function (see below).
Example:
COT(30)
The result is -0.156119952161659.
ASIN() - A function that calculates the ARCSINE of the given number (inverse SINE). The value of the number must be from -1 to 1. The resulting angle is in radians, in the range from -Pi/2 to +Pi/2. If you want an angle in degrees, convert it from radians to degrees by using the DEGREES function (see below).
Examples:
ASIN(-0.5)
The result is -0.523598776.
DEGREES(ASIN(-0.5))
The result is -30.
ACOS() - A function that calculates the ARCCOSINE of the given number (inverse COSINE). The value of the number must be from -1 to 1. The resulting angle is in radians, in the range from 0 to Pi. If you want an angle in degrees, convert it from radians to degrees by using the DEGREES function (see below).
Examples:
ACOS(-0.5)
The result is 2.094395102.
DEGREES(ACOS(-0.5))
The result is 120.
ATAN() - This function calculates the ARCTANGENT of the given number (inverse TANGENT). The value of the number must be a real number. The resulting angle is in radians, in the range from -Pi/2 to +Pi/2. If you want an angle in degrees, convert it from radians to degrees by using the DEGREES function (see below).
Examples:
ATAN(1)
The result is 0.785398163.
DEGREES(ATAN(1))
The result is 45.
ATAN2() from X- and Y-coordinates - This function calculates the ARCTANGENT of the specified x- and y-coordinates (inverse TANGENT). A line starting from origin (0,0) to the point with specific coordinates (x, y) makes an angle with the x-axis (counterclockwise and clockwise). This angle is the result of arctangent and it is given in radians, in the range from -Pi to Pi, excluding -Pi.
Example:
ATAN2(1, 1)
DEGREES(ATAN2(-1, -1))
ACOT() - This function calculates the principal value of the ARCCOTANGENT of a number (inverse COTANGENT). The value of the number must be a real number. It is a cotangent of an angle you want to calculate with this function. The resulting angle is in radians, in the range from 0 to Pi. If you want an angle in degrees, convert it from radians to degrees by using the DEGREES function (see below).
Example:
ACOT(2)
DEGREES() - This function converts an angle given in radians to an angle in degrees.
Example:
DEGREES(0.785398163)
The result is 45.
RADIANS() - This function converts an angle given in degrees to an angle in radians.
Example:
RADIANS(270)
The result is 4.712389.
LN() - This function calculates the natural logarithm of a number. The natural logarithm of a number x is the power to which constant e (e=2.718) should be raised to equal x. The given number must be a positive, real number.
Example:
LN(86)
EXP() - This function calculates the constant e (e=2.718) raised to the power of a given number. It is an inverse function of LN.
- Example:
EXP(1)
CEILING() - This function rounds a number up, to the nearest integer. A parameter is a number, or a value of a number field identifier, which you want to round up.
FLOOR() - This function rounds a number down, to the nearest integer. A parameter is a number, or value of a number field identifier, which you want to round down.
IS_DIVISIBLE() - This function checks if two numbers are divisible without the remainder. Number1 is the dividend, while number2 is the divisor.
Example:
IS_DIVISIBLE(8,2)
Returns true.
GEOMEAN() - This function calculates the geometric mean of the given numbers (not arithmetic mean, for that you can use function AVG).
ENCODEURL() - This function transforms a given string in URL code. It will replace non-alphanumeric characters with the percentage symbol and a hexadecimal number.
Example:
ENCODEURL(‘string’)
LEFT() - This function gives the leftmost characters from a text value.
Text is a string from which you want to extract the left side characters. numberOfCharacters sets how many characters you desire to extract from the left side of the given text.
Example:
RIGHT() - This function gives the rightmost characters from a text value.
Text is a string from which you want to extract the right side characters. numberOfCharacters sets how many characters you desire to extract from the right side of the given text.
Example:
RIGHT(FieldIdentifier,4)
SEARCH() - This function finds a location of one text value within another text value and returns a number of the character where it starts the searched part of the text.
Text is a string where you want to search a certain part; searchString is the part of the string you want to search; Result is the number at which is the first character of searchString in the text. Not case-sensitive.
Example:
SEARCH(AlphanumericField, AlphanumericSearchField)
AlphanumericField has the value "Lorem ipsum dolor sit amet, consectetur adipiscing elit" and AlphanumericSearchField has the value "dol". The result is 13 which is the position of “d” from “dolor”
REPLACE() - This function replaces characters within the text.
Originaltext is a string where you want to replace a part. StartingPosition is a place from where you want to replace the text; NumberOfCharactersToChange is a part of the text given in the number of characters you want to replace in the text by NewText. NewText is a string you want to have in the text after the replacement.
SUBSTITUTE() - This function substitutes new text for old text in a string.
OriginalText is a string where you want to substitute a part. This function is searching for a given part of the text - OldString in OriginalText and substitutes it with the given NewString. NumberOfOccurrences is optional and defines how many occurrences to replace. If not specified, the function will substitute all the occurrences.
LOWER() - This function converts each uppercase letter in a text string to a lower case letter.
Examples:
LOWER(FieldIdentifier)
Returns a text all in lower case.
LOWER(‘Yield’)
The result is ‘yield’.
UPPER() - This function converts a text string to uppercase.
Examples:
UPPER(FieldIdentifier)
Returns a text all in lower case.
UPPER(‘total amount’)
The result is ‘TOTAL AMOUNT’.
FORMAT_STRING() - This function gives a formatted string made from a string with placeholders and values passed to fit in the placeholders.
The number of placeholders in a string must be equal to the number of values to be placed in the string. param1, param2, are values to fit the placeholders (can be more than 2).
Example:
STRING_FORMAT(Instruction, Ingredient, Phase)
This calculation is placed on an alphanumeric field with an identifier, Procedure. Instruction, Ingredient, and Phase are alphanumeric fields. User must enter a value for the field Instruction in the following format: ‘Mix {1} than add {2}’. Number 1 in the curly brackets is where the value of field Ingredient will be placed in the text. Number 2 in the curly brackets is where the value of field Phase will be placed in the text. There should be a single number in the curly brackets without any other characters.
MID() - This function trims the given number of characters from the original string from the left and from the right side.
text can be a string, or an identifier of an alphanumeric field, etc.
numbersOfCharsLeft is the number of characters that you want to trim from the left side of the given string.
numbersOfCharsRight is the number of characters that you want to trim from the right side of the given string.
RANDOMIZE - This function generates random string according to the provided string length and returns an array of characters.
Input 1 is the length, a number type, which defines how many characters need to be returned.
Input 2 is isNumber, a boolean value, which defines whether the returned array of characters is only numbers.
Example:
RANDOMIZE(length, isNumber)
P_CORREL() - This function calculates the Pearson correlation coefficient, dimensionless index that ranges from -1.0 to 1.0 inclusive. It is a measure of linear correlation between two sets of data.
numberMatrix1 is a set of independent values, while numberMatrix2 is the other set of independent values that you want to correlate.
S_CORREL() - This function calculates the Spearman correlation coefficient.
numberMatrix1 is a set of independent values, while numberMatrix2 is the other set of independent values that you want to correlate.
MAX() - This function gives the largest value in a set of values.
MIN() - This function gives the smallest value in a set of values.
MEDIAN() - This function gives the median of the given numbers. The median is in the middle of a set of numbers.
MODE() - This function gives the most frequently occurring single value in a data set.
MODE_M() - This function gives the most frequently occurring multiple values in a data set. Only the values that are most frequently repeated and that repeat exactly the same number of times are returned.
PERCENTILE() - This function calculates the k-th percentile of values in a data set; where k is in the range from 0 to 1, excluded.
percentileNumber is k.
STDEV() - This function calculates standard deviation based on the sample of population.
DATE_DIF() - This function calculates the date difference (or the number of days, months, years, etc.) between two dates.
dateDiffKeyword can be one of the following: 'YEAR', 'MONTH', 'WEEK', 'DAY', 'HOUR', 'MINUTE', 'SECOND', 'MILLISECOND'
dateValue1 is the date you want to calculate the difference regarding to the dateValue2. The calculated difference will be displayed in units that you set by dateDiffKeyword.
DATE_ADD() - This function calculates the resulting date and time by adding the amount specified to the given date.
dateValue is the date to which you want to add the amount of time.
amount is the amount of time you want to add to dateValue (positive number for adding amount of time in future, negative number for returning date from the past).
dateDiffKeyword can be one of the following: 'YEAR', 'MONTH', 'WEEK', 'DAY', 'HOUR', 'MINUTE', 'SECOND', 'MILLISECOND'. By choosing one of these keywords you are setting a unit for the amount to be added to the dateValue
Example:
DATE_ADD(DateTimeFieldIdentifier, 3, 'MONTH')
Returns a date & time 3 months from the date provided in the field DateTimeFieldIdentifier.
DATE_GET() - This function returns a year, a month, a day of a month, or a day of a year of the given date.
dateValue is the given date for which you want to calculate the year.
dateSegmentKeyword is 'YEAR', 'MONTH', 'MONTHDAY' or 'DAY'.
Examples:
DATE_GET(DateFieldIdentifier, 'YEAR')
Returns a year for the date provided in the field DateFieldIdentifier.
DATE_GET(CreatedOn, 'MONTH')
If the value of the field CreatedOn is 25th September 2021, the result will be 9.
DATE_GET(CreatedOn, 'MONTHDAY')
If the value of the field CreatedOn is 25th September 2021, the result will be 25.
DATE_GET(CreatedOn, 'DAY')
If the value of the field CreatedOn is 25th September 2021, the result will be 268.
WEEKDAY - This function returns a day of the week as a number from 1 for Sunday to 7 for Monday.
dateValue is the given date for which you want to calculate the day of the week.
dateSegmentKeyword is 'WEEKDAY'.
HOUR - This function returns an hour of the given date & time value as a number from 0 (for 12:00 AM) to 23 (for 11:00 PM).
dateValue is the given date & time for which you want to calculate the hour.
dateSegmentKeyword is 'HOUR'.
MINUTE - This function returns a minute of the given date & time value as a number from 0 to 59.
dateValue is the given date & time for which you want to calculate the minute.
dateSegmentKeyword is 'MINUTE'.
SECOND - This function returns a second of the given date & time value as a number from 0 to 59.
dateValue is the given date & time for which you want to calculate the second.
dateSegmentKeyword is 'SECOND'.
MILLISECOND - This function returns a millisecond of the given date & time value as a number from 0 to 999.
dateValue is the given date & time for which you want to calculate the millisecond.
dateSegmentKeyword is 'MILLISECOND'.
NUMBER OF THE WEEK - This function returns a week number of the given date & time value as a number from 1 to 52. Numbering is determined by aligned-week-of-the-year and depends on the starting day of the year. The first aligned week of the year starts on day-of-year 1, the second aligned week starts on day-of-year 8, and so on.
dateValue is the given date & time for which you want to calculate the number of the week.
dateSegmentKeyword is 'WEEK'.
QUARTER OF THE YEAR - This function returns a quarter of the year for the given date & time value as a number from 1 to 4.
dateValue is the given date & time for which you want to calculate the quarter of the year.
dateSegmentKeyword is 'QUARTER'.
END_OF() - This function returns a date value which is at the end of the specified time unit for the given date. As for the DATE_GET function, the week starts on Sunday.
dateValue is the given date & time.
TimeUnit can be 'MONTH', 'WEEK', 'QUARTER' or 'YEAR'.
The functions listed below are to be used with arrays. Elements of the array can be numbers, text, another array, or struct. Different types can be elements of the same array.
APPEND() - This function adds an element at the last place in the array. Array size will be increased by one. If the added element is another array, it will be added at the last place of the main array as a subarray.
param1 is the local variable of the type array.
param2 is an element to be added to the array defined in param1.
Examples:
var a = [1, 2, 3, 4];
APPEND(a, 5); - the result is array a = [1, 2, 3, 4, 5]
var a = [1, 2, 3, 4];
APPEND(a, [5, 6]); - the result is array a = [1, 2, 3, 4, [5, 6]]
APPEND_ALL() - This function adds elements at the last place in the array. Array size will be increased by one, or more elements, depending on the type of added element. If the element added is another array, APPEND_ALL will merge the main array with the array being added. The size of the main array will be increased by the size of the added array. It is good practice to use this function instead of APPEND in Predefined Values Expressions.
param1 is the local variable of the type array.
param2 is the element to be added to the array defined in param1.
Examples:
var a = [1, 2, 3, 4];
APPEND_ALL(a, 5); - the result is array a = [1, 2, 3, 4, 5]
var a = [1, 2, 3, 4];
APPEND_ALL(a, [5, 6]); - the result is array a = [1, 2, 3, 4, 5, 6]
INSERT() - This function inserts an element to the exact position in the array. The existing element on the position of insertion will be shifted to the next position and the array size will be increased by one.
param1 is the local variable of the type array.
param2 is the position where a new element will be inserted.
param3 is the element inserted on the position defined by param2 in the array defined by param1.
Examples:
var a = [1, 2, 3, 4];
INSERT(a, 2, 11]); - the result is array a = [1, 11, 2, 3, 4]
var a = [1, 2, 3, 4];
INSERT(a, 2, [5, 6]); - the result is array a = [1, [5, 6], 2, 3, 4]
INSERT_ALL() - This function inserts element(s) to the exact position in the array.
When the element being inserted is not an array, the array size will be increased by one.
If the element being inserted is another array, the array size will be increased by the number of the elements in the inserted array.
param1 is the local variable of the type array.
param2 is the position where a new element will be inserted.
param3 is the element inserted on the position defined by param2 in the array defined by param1.
Examples:
var a = [1, 2, 3, 4];
INSERT_ALL(a, 2, 13]); - the result is array a = [1, 13, 2, 3, 4]
var a = [1, 2, 3, 4];
INSERT_ALL(a, 2, [5, 6]); - the result is array a = [1, 5, 6, 2, 3, 4]
REMOVE() - This function removes the element(s) from the array on the exact position(s). The array size will be decreased by the number of removed elements.
param1 is the local variable of type array.
param2 is the position where a single element will be removed or array of positions of elements to be removed.
Examples:
var a = [1, 2, 3, 4];
REMOVE(a, 2); - the result is array a = [1, 3, 4]
var a = [1, 2, 3, 4];
REMOVE(a, [2, 4]); - the result is array a = [1, 3]
RESIZE() - This function resizes the array to the defined size.
If the size is decreasing, elements on positions outside of the new size will be removed from the resized array.
If the size is increasing, the number of elements in the new array will increase to the new size. The new elements will be populated by null values.
param1 is local variable of type array.
param2 defines the new size of array (number of elements in a resized array).
Examples:
var a = [1, 2, 3, 4];
RESIZE(a, 3]); - the result is array a = [1, 2, 3]
var a = [1, 2, 3, 4];
RESIZE(a, 6); - the result is array a = [1, 2, 3, 4, null, null]
SUBARRAY() - This function creates a new array that will be the subarray of the main array. The new array contains elements between from and to position of the main array. Elements on from position and to position are included in the subarray. If to position is greater than the size of the main array, the returned subarray will be between from position and the last element of the main array.
param1 is local variable of type array.
param2 defines the start of the subarray (position of element in main array that will be first element in subarray).
param3 defines the end of the subarray (position of element in main array that will be last element in subarray).
Examples:
var a = [1, 2, 3, 4];
var b = SUBARRAY(a, 2, 3); - the result is array b = [2, 3]
var a = [1, 2, 3, 4];
var b = SUBARRAY(a, 2, 8); - the result is array b = [2, 3, 4]
CONTAINS() - This function checks if an array contains a specific element. If struct is used, it checks if struct contains a specific key.
param1 is a local variable of type array or type struct.
param2 has two options based on type of param1:
1) if the param1 is an array - the param2 can be text, number, struct or another array.
2) if the param1 is struct - the param2 can be only text
Examples:
var a = [1, 2, 3, 4];
CONTAINS(a, 2); // returns true
var a = [1, 2, 3, 4];
CONTAINS(a, 7); // returns false
var a = [1, 2, 3, 4];
CONTAINS(a, [1, 2]); // returns false
var a = [1, 2, 3, 4];
a[3] = [4, 5, 6]; // array a now has on position 3 array [4, 5, 6]
var s = {'key1': 'description1', 'key2': 'description2'};
CONTAINS(s, 'key1'); // returns true
CONTAINS(s, 'key5'); // returns false
var s = {'key1': 'description1', 'key2': 'description2'};
s[‘key3’] = ‘new description’; // struct is now updated {'key1': 'description1', 'key2': 'description2', 'key3': 'new description'}
var s = {'key1': 'description1', 'key2': 'description2'};
s[‘key1’] = ‘demo’; // struct is now updated {'key1': demo, 'key2': 'description2'}
CONTAINS_ALL() - This function checks if the main array contains all of the specified elements. Elements to check are defined in another array.
param1 is the local variable of type array.
param2 specifies elements to be checked, defined in another array.
Examples:
var a = [1, 2, 3, 4];
CONTAINS_ALL(a, [1, 2]); // returns true
var a = [1, 2, 3, 4];
CONTAINS_ALL(a, [4, 5, 6]); // returns false
CONTAINS_ANY() - This function checks if the main array contains any of the specified elements. Elements to check are defined in another array.
param1 is a local variable of type array.
param2 specifies elements to be checked, defined in another array.
Examples:
var a = [1, 2, 3, 4];
CONTAINS_ANY(a, [1, 2]); // returns true
var a = [1, 2, 3, 4];
CONTAINS_ANY(a, [4, 5, 6]); // returns true
COUNT_OF() - This function counts how many times a specified element (or elements in another array) is repeated in the main array.
param1 is a local variable of type array.
param2 specifies elements to be checked, defined in another array.
Examples:
var a = [1, 2, 3, 4];
COUNT_OF(a, 2); // returns 1
var a = [1, 2, 3, 4];
COUNT_OF(a, 5); // returns 0
var a = [1, 2, 3, 2, 4, 2];
COUNT_OF(a, 2); // returns 3
var a = [1, 2, [3, 4], 3, 4];
COUNT_OF(a, [3, 4]); // returns 1
FIND_AND_REMOVE - This function finds and removes the first (or all) equal item(s) in the array. The function will not return any value; what is forwarded is changed.
It can be used to configure a repeatable row table where already used predefined values need to be removed after previously used.
param1 is local variable of type array.
param2 specifies value which will be removed from param1.
Examples:
var a = [1, 2, 3, 4];
FIND_AND_REMOVE(a, 2);
NumberField=a; //NumberField = [1, 3, 4]
var a = [1, [1, 2], 2, 3];
FIND_AND_REMOVE(a, [1, 2]);
NumberField = a; //NumberField = [1, 2, 3]
INDEX_OF - This function finds the equal item(s) and returns their index as an array of number(s).
param1 is a local variable of type array.
param2 specifies the value which will be found in param1.
Examples:
var a = [10, 20, 30, 40];
INDEX_OF(a, 20); //returns [2]
var a = [10, 20, 30, 40, 30];
INDEX_OF(a, 30); // returns [3,5]
AS_ARRAY - This function converts input parameters to an array. Since it is returning the array, the field to which the value is returned needs to support multiple values.
Example 1:
var a = 20;
var index = AS_ARRAY(a); // index = [20]
Example 2:
someField is single number field out of group with predefined values 10, 20, 30 and value 10 is set.
var index = AS_ARRAY(someField); // index = [10]
Example 3:
someField is multi number field out of group with predefined values 10, 20, 30 and values 10 and 20 are set.
var index = AS_ARRAY(someField); // index = [10, 20]
Example 4:
someField is single number field in a group with predefined values 10, 20, 30 and values are set:
var index = AS_ARRAY(someField); // index = [10, 20, 30]
Example 5:
someField is multi number field in a group with predefined values 10, 20, 30 and values are set:
var index = AS_ARRAY(someField); // index = [[10, 20], [20], [30, 10, 20]]
RANDOMIZE - This function generates random string according to the provided string length and it returns an array of characters.
Input 1 is the length, number type, which defines how many characters need to be returned.
Input 2 is isNumber, boolean value, which defines whether the returned array of characters is only numbers.
Example:
RANDOMIZE(length, isNumber)
The Item keyword is used to access the specific item from the resultset used in expressions in repeatable rows or columns determined by record reference or determined by filter (Item.FieldIdentifier). Namely, they are enabling the creation of bound tables, as explained in the section Repeatable Options of the Configuration Portal Administrator Manual.
Item keyword is used as a record reference variable, to access a specific item from the result set of field values in repeatable rows or columns. Item is only used in the Formula Expression for fields in repeatable rows or columns where the repeatable group option is set to Determined by Record Reference or Determined by Filter.
In our example in the Configuration Portal Administrator Manual on how to make a bound table in Alchemy we configured a bound table in the record Work Plan that is determined by the Literature Search record reference. In this case, the Item keyword will act as a record reference variable, for the Literature Search record.
Since the Item is a record variable, all other options explained in the Chapter Variables are available, as long as they are used inside the repeatable row group. Some use cases are
Item.CreatedBy - must use in a formula expression for a user type field. Returns a user who created a certain record of the table.
In this section, you will see some functionalities that can be utilized to write a proper script.
As already described in chapter Alphanumeric of the Configuration Portal Administrator Manual, alphanumeric fields can have predefined values. In some cases, you will need to configure the first alphanumeric field with predefined values. Then, depending on the predefined value selected in this field, a specific set of predefined values should be available for selection in the second alphanumeric field. This is known as Conditional Predefined Values and it can be realized by writing a proper script. See the example below:
You need to configure the Test Instruction record template. This template will be used for the creation of different records - a variety of test instructions in your organization.
First, you need to set the type of your Test Instruction. Make an alphanumeric field (name Test Type, identifier TestType) and give it three predefined values: Characterization, Application, Microbiology.
Make the second alphanumeric field (name: Test, identifier Test), where different tests will appear in a dropdown, depending on the predefined value selected in the Test Type field. Let’s say these are the values you need to configure:
First, in the VALUES tab of the field Test, add all predefined values to the field Test (pH, Viscosity, Density, Scrub Resistance, Adhesion, Tensile Elongation, Fungal, Bacterial).
Second, write the Expression for conditional predefined values like in Figure 2.3 where the Values tab of the field Test is shown with the Expression entered.
The correct Expression is the following:
var a=[];
if(TestType=='Characterization')
{a=['pH','Viscosity', 'Density'];}
else if(TestType=='Application')
{a=['Scrub Resistance', 'Adhesion', 'Tensile Elongation'];}
else if(TestType=='Microbiology')
{a=['Fungal', 'Bacterial'];}a;
First line var a=[]; defines and initializes a variable in the code. Variable a is initialized as an empty array [].
When the first if condition if(TestType=='Characterization') is satisfied (i.e., field with identifier TestType has a value 'Characterization'), variable a can have only these values {a=['pH','Viscosity', 'Density'];}. This means that when the user in the User Portal selects 'Characterization' in the Test Type, in the dropdown of the field Type will appear only ‘pH’, ‘Viscosity’, and ‘Density’.
It goes the same for the second if condition if(TestType==’Application’), when variable a can have only one of these values {a=['Scrub Resistance', 'Adhesion', 'Tensile Elongation'];}. The same principle is for the third if condition.
Finally, there is the last part of the expression: a; that will return the value of variable a to the field Test Type and filter down the list of predefined values based on the satisfied condition.
Another important and powerful functionality that you can use in every field type is Action - On Change. Each time the value of the field is changed, this functionality will execute a specific action. The action is added to the field which will be changed.
In the Menu of the field, under tab ACTIONS, you can add a new action by clicking on the button.
Upon adding a new action you have to set On* to “Changed”. Under the Term you write an Expression of action that should be executed when a user changes the value of the field. See the example below:
In section Button of the Configuration Portal Administrator Manual, there is an Example - Button recalculates all rows in the table. In this example, you learned how the user can compose the formulation, and how they can change the formulation and easily recalculate all amounts in the table with the press of a button, “Normalize”.
Thanks to the On Change action functionality, you can make this recalculation completely automatic - there is no need for a user to press the button “Normalize”. Each time user changes Target Batch Size L, all rows in the table (all amounts of materials added to the formulation) will be recalculated automatically.
In the Actions tab of the field Target Batch Size L add a New Action. Set the On* to “Changed” and under Term write the same calculation that is in the action script of a button “Normalize”:
AddedMaterialg = AddedMaterialL / TotalVolume * TargetBatchSizeL * MaterialDensity
See how it’s done in Figure 2.4.
It is important to note where you are setting this functionality. Try to take into account all possible scenarios that can happen from the user’s perspective regarding changing the field’s value because each time the value of the field is changed, an action will happen.
As already explained, an Action can be added to the field. Each time a field's value is changed, an action will be executed.
This action can also be performed on a field in a specific row of the repeatable row. Specifying a row is done by using the keyword CurrentRow. Example - Button with Helper Field in the Configuration Portal Administrator Manual will be upgraded to explain this functionality. See the example below:
In the record template Work Plan, there is a table for defining new formulations: users can add rows, set names, and target properties for pH, Density, and Viscosity. With a click of a button, Formulation Records are created with the names defined in the table. The Formulation Record created with the button will have a name defined in an alphanumeric field, Experimental Formula Name (identifier ExperimentalFormulaName). Let’s say you want to configure an action that allows the user to change the name of the Formulation record by changing the field Experimental Formula Name in the table.
It was already explained that the Create Formulations button requires an additional record reference helper field. In Example - Button with Helper Field, the helper field is located outside of the repeatable row group. Now, in order to establish a link between each row in the table with the formulation created, you need to place a helper field inside a repeatable row.
Given the fact that the helper field is now inside the repeatable row, each line of the button script should be updated to access value for each row using FormulaHelper[i], therefore the button script needs to be modified, like this:
for(var i = 1; i <= ExperimentalFormulaRRGroup.RowCount; i = i + 1)
{
if(FormulaCreated[i] == false)
{
FormulaHelper[i] = CREATE_RECORD('FormulationDesign','LabWork',Process,1);
FormulaHelper[i].FormulationName = LabWorkNumber+' ' + ExperimentalFormulaName[i];
FormulaHelper[i].TargetpHfrom=TargetpHfrom[i];
FormulaHelper[i].TargetpHto=TargetpHto[i];
FormulaHelper[i].TargetViscosityFrom=TargetViscosityFrom[i];
FormulaHelper[i].TargetViscosityTo=TargetViscosityTo[i];
FormulaHelper[i].TargetDensityFrom=TargetDensityFrom[i];
FormulaHelper[i].TargetDensityTo=TargetDensityTo[i];
FormulaCreated[i] = true;
}
}
Changing the name of the specific Formulation Record is done by changing the field Experimental Formula Name in that specific row.
In the field Experimental Formula Name (identifier ExperimentalFormulaName), in the tab Actions, add New Action - On Change with the following script:
if(FormulaHelper[CurrentRow] IS SET)
{
FormulaHelper[CurrentRow].FormulationName = LabWorkNumber + ' ' + ExperimentalFormulaName[CurrentRow];
}
The condition if(FormulaHelper[CurrentRow] IS SET) must be placed in order to apply On Change Action only for the already created Formulations.
Conditional Formatting enables you to change the property of the field using the appropriate Alchemy script expression. It can be used on all field types except for Label, Image, and Button.
The general form of a Conditional Formatting Expression is:
FieldIdentifier.FieldProperty = PropertyValue;
Where FieldProperty is the keyword to access a specific property of the field defined by the FieldIdentifier. A specific property is getting the value defined by PropertyValue.
Conditional Formatting Expression can be placed on Formula Expression, Button Action Expression, Field Action - On Change, and Stage Action - Execute Script.
When the Action is triggered, the script will be executed and the field property will be updated. If you change the Conditional Formatting Expression in the Configuration Portal and back propagate - the field property will not be affected. It will remain as defined by the previous Conditional Formatting Expression.
Field Dimensions (Width, Height, and Margins) CANNOT be changed using Conditional Formatting.
Here is the list of all Field Properties that CAN be changed using Conditional Formatting. In the list of available field properties below, for each property there is an output type and possible values in parentheses:
* Field property Hidden will apply the change for the whole field. If the field is in a repeatable row/column table all rows will be changed. It cannot change the state of individual rows. Other properties can be used if the field is inside a repeatable row/column. If you need to target a specific row inside a table, use the Current Row system data in the form:
FieldIdentifier[CurrentRow].FieldProperty = PropertyValue;
** Field property CellUnitSymbol cannot override the unit of the field. It only returns the unit for printing purposes; example field with unit set to kg:
FieldIdentifier.CellUnit returns 'KILOGRAM'
FieldIdentifier.CellUnitSymbol returns 'kg'
Examples
Let’s build on an already existing example - IFS conditions. In this example we have already explained how an alphanumeric field can show text IN RANGE or OUT OF RANGE depending on the entered value for pH, Density or Viscosity and defined target values (i.e. range). To make it more visually appealing, let’s say you need to configure the same alphanumeric field to be green when the entered value is in range and red when it is out of range. In the Formula Expression of the alphanumeric field (identifier pHRange) there should be this expression:
var a = ' ';
if(pH>=TargetpHfrom AND pH<=TargetpHto)
{pHRange.InputBackgroundColor='#93C480';
a='IN RANGE';}
else
{pHRange.InputBackgroundColor='#DF6969';
a='OUT OF RANGE';}
a;
Let’s read and explain this script. In the first condition we are checking if entered number for pH value (in the field with identifier pH) is greater than defined start range limit (value defined in the field with identifier TargetpHfrom) and lower than defined end range limit (value defined in the field with identifier TargetpHto). If that condition is satisfied, the Conditional Formatting Expression will be executed by changing the field property InputBackgroundColor to green ('#93C480'). Also, the field will show the provided text: 'IN RANGE'. In the case that this condition is not met, the field property will be red ('#DF6969') and the field will get the value 'OUT OF RANGE'.
The Hex Code can be used as a property value by providing it as a string (under single quotes). The list of Hex Codes for the default Alchemy Colors available in any color Picker is:
Additional hex codes are available by selecting “Custom” in the Color Picker. Choosing the desired color will display its Hex Code. You can copy and paste it from there in the Conditional Formatting Expression.