[This local archive copy is from the official and canonical URL, http://www.w3.org/1999/05/XFA/xfa-formcalc-19990614; please refer to the canonical source document if possible.]
© Copyright 1999, JetForm Corporation. All rights reserved.
This document is a Submission to W3C from JetForm Corporation.
This document, as part of a family of specifications referred to as the XML Forms Architecture, describes an XML based language, XFA-Template, for modelling electronic form templates. XFA provides for the specific needs of electronic forms and the applications that use them. XFA addresses the needs of organizations to securely capture, present, move, process, output and print information associated with electronic forms. This document specifically describes a simple scripting language optimized for creating e-form centric logic and calculations.
FormCalc is a simple scripting language whose roots lie in electronic form software from JetForm, and common spreadsheet software. It is largely an expression-based language with few control flow statements. It is also a type-less language, where values of type string or type number are promotable to strings, numbers or booleans to suit the context.
FormCalc is tailored to the skills of the non-programmer who is comfortable with spreadsheet-class application software. This user can, with the addition of a few FormCalc expressions, validate user input and/or unburden the form user from the spreadsheet like calculations.
To that aim, the language provides a large set of built-in functions to perform arithmetic, scientific, and financial tasks. Locale-sensitive date and time functions are provided, as are string manipulation functions.
To better illustrate the capabilities of the FormCalc language, we present a simple purchase order application, and focus on those spreadsheet like calculations and validations typically required of such forms.
Down-pointing call-outs indicate all the field names on this form. In the tabular area of the form are four fields called Item, four fields called Quantity, four fields called UnitPrice, and four fields called Amount. We will focus on these shortly.
Green up-pointing call-outs indicate fields with embedded calculations, and the red up-pointing call-outs indicate fields with embedded validations.
A subset of the XML used to defined this purchase order form might be as follows:
<XFA> <Template Name="FormCalc Example"> <Subform> <Area Name="Leader" ...> ... </Area> <Area Name="Table"> <Field Name="Item"> ... </Field> <Field Name="Quantity"> <Valid>Within($, 0, 19)</Valid> </Field> <Field Name="UnitPrice"> ... </Field> <Field Name="Amount"> <Calc>Quantity * UnitPrice</Calc> </Field> <Field Name="Item"> ... </Field> <Field Name="Quantity"> <Valid>Within($, 0, 19)</Valid> </Field> <Field Name="UnitPrice"> ... </Field> <Field Name="Amount"> <Calc>Quantity * UnitPrice</Calc> </Field> <Field Name="Item"> ... </Field> <Field Name="Quantity"> <Valid>Within($, 0, 19)</Valid> </Field> <Field Name="UnitPrice"> ... </Field> <Field Name="Amount"> <Calc>Quantity * UnitPrice</Calc> </Field> <Field Name="Item"> ... </Field> <Field Name="Quantity"> <Valid>Within($, 0, 19)</Valid> </Field> <Field Name="UnitPrice"> ... </Field> <Field Name="Amount"> <Calc>Quantity * UnitPrice</Calc> </Field> </Area> <Area Name="Summary" ...> <Field Name="ShipDate"> <Calc>Num2Date(Date() + 2, DateFmt())</Calc> </Field> <Field Name="Total"> <Calc>Str(Sum(Amount[*], 10, 2))</Calc> </Field> </Area> </Subform> </Template> </XFA>Focusing our attention on the contents of the <Calc> and <Valid> elements, we see text like
The first of these ensures that the entered field value is within the range of 0 to 19. The second computes the product of two fields, while the third simply displays a date that is two days hence from the current date. Some of these expressions are continually being re-executed as the user interacts with the form and enters new data.
On each of the four Quantity fields is the validation:
Within($, 0, 19)
This is used to limit the user's input to between 0 and 19 items. Any other
value entered in these fields will cause a validation error, requiring to user
to modify his input. Here the symbol $ is an identifier that references the
value of the field to which this FormCalculation is bound; in this case, the
Quantity field.
On each of the four Amount fields is the calculation:
Quantity * UnitPrice
which multiplies the value of the Quantity field by the value of the UnitPrice
field on that row, and stores the resulting product in the Amount field. Whenever
the user changes any of the quantity fields, this calculation is re-executed
and the new value is displayed in the corresponding Amount field.
Below the column of Amounts is the Total field. It contains the calculation:
Str(Sum(Amount[*], 10, 2))
This sums all four occurences of the field Amount, and formats the resulting
number to two decimal places in a string, 10 characters wide. Whenever any of
the amount fields change, this calculation is re-executed and a new value is
displayed in the Total field.
Finally, the field named ShipDate also contains a calculation, specifically,
a date calculation
Num2Date(Date() + 2, DateFmt())
This calculation gets the value of the current date (in days), adds 2 days to
it and then formats this date value into a locale-sensitive date string. Were
that user to be in the United States, in the year 2000, and on the ides of March,
the result that would be displayed in the ShipDate field, is:
Mar 17, 2000
A user in Germany, on that same day, would see the value
17.03.1999
displayed in the same field. The latter is an illustration of the built-in internationalization
capabilities of FormCalc's date and time functions.
Admitedly, this is a very simple application. A real-world purchase order form would be significantly more complex, with perhaps several dozen calculations and validations. Hopefully that this example will suffice to introduce some of the capabilites of the FormCalc language.
We will now proceed to formalize the definition of this language. More complex language examples will be presented throughout.
The FormCalc language is defined in terms of a context-free grammar. This is a specification of the lexical and syntactic structure of FormCalc calculations.
A context-free grammar is defined as a number of productions. Each production has an abstract symbol called a non-terminal as its left-hand side, and a sequence of one or more non-terminal and terminal symbols as its right-hand side. The grammar specifies the set of possible sequences of terminal symbols that can result from repeatedly replacing any non-terminal in the sequence with a right-hand side of a production in which the non-terminal is the left-hand side.
The following convention in notation or metasymbols is used to describe the grammar of FormCalc:
::= | start of the definition of a non-terminal symbol. |
|... | alternative symbol. |
[...] | one from the set of enclosed terminal symbols. |
(...) | one occurrence of the enclosed symbol(s). |
(...)_{*} | zero or more occurrences of the enclosed symbol(s). |
(...)_{?} | at most one occurrence of the enclosed symbol(s). |
The non-terminal symbols of the grammar are always in normal print, or are often sub scripted by a integer, as in LogicalAndExpression_{[25]} or Identifier_{[14]}. The terminal symbols of the grammar are always enclosed in single quotes, as in '=' and 'then', or enclosed in square brackets, as in [0-9].
This section describes the lexical grammar of the FormCalc language. This grammar has as its terminal symbols the characters of the Unicode character set. It defines a set of productions, starting from the non-terminal symbol Input_{1}, to describe how sequences of Unicode characters are translated into a sequence of input elements.
Input elements other than white space and comment form the terminal symbols for the syntactic grammar of FormCalc, and are called tokens. These tokens are the literals, identifiers, keywords, separators and operators of the FormCalc language.
[1] Input ::= WhiteSpace | LineTerminator | Comment | Token
The source text for a FormCalc calculation is a sequence of characters using the Unicode character encoding. These Unicode characters are scanned from left to right, repeating taking the longest possible sequence of characters as the next input element.
[2] Character ::= #x9 | #xB | #xC | [#x20-#xD7FF] | [#xE000-#xFFFD]
Note: not all FormCalc hosting environments recognize these characters, e.g., XML does not allow the vertical tab (#xB) and form feed (#xC) characters as input.
White space characters are used to separate tokens from each other and improve readability but are otherwise insignificant.
[3] WhiteSpace ::= #x9 | #xB | #xC | #x20
Line terminators, like white spaces are used to separate tokens and improve readability but are otherwise insignificant.
[4] LineTerminator ::= #xA | #xD
Comments are used to improve readability but are otherwise insignificant.
A comment is introduced with a semi-colon (;) character and continues until a Line Terminator is encountered.
[5] Comment ::= ';' ( Character - LineTerminator )*
A string literal is a sequence of Unicode characters enclosed within double quote characters, e.g., "the cat jumped over the fence." The string literal "" defines an empty sequence of text characters called the empty string.
To embed a double quote within a string literal, specify two double quote characters, as in "He said ""She said.""". Moreover within string literals, any Unicode character may be expressed as a Unicode escape sequence of 6 characters consisting of \u followed by four hexadecimal digits, e.g.,
"\u0047\u006f \u0066\u0069\u0073\u0068\u0021"
To embed a control character with a string literal, specify its Unicode escape sequence, e.g., specify \u000d for a carriage return, and \u000a for a newline character.
[6] HexDigit ::= [0-9] | [a-f] | [A-F] [7] EscapedCharacter ::= '"' '"' | '\' 'u' HexDigit HexDigit HexDigit HexDigit [8] StringLiteral ::= '"' ( Character - '"' | EscapedCharacter )* '"'
A number literal is a sequence of mostly digits consisting of an integral part, a decimal point, a fractional part, an e (or E) and an optionally signed exponent part. Either the integral part or the fractional part may be missing, but not both. In the fractional part, either the decimal point or the e and exponent part may be missing, but not both. Examples of number literals include 12, 1.2345, .12, 1e-2, and 1.2E+3.
All number literals are internally converted to IEEE754 64-bit binary values.
However, IEEE754 values can only represent a finite quantity of numbers. Specifically,
but not limited to, number literals having more than 16 significant digits in
the non-exponent part will be the rounded to the nearest representable IEEE754
64-bit value using a round-to-nearest mechanism. This means that a number literal
like
123456789.012345678
will be rounded to the (nearest) value
123456789.01234567
and a number literal like
99999999999999999
will be rounded to the (nearest) value
100000000000000000
This behaviour is conformant to the IEEE754 standard.
IEEE754 64-bit values also support representations like NaN (not a number), +Inf (positive infinity), and -Inf (negative infinity). However for simplicity, FormCalc does not support these; any intermediate expression that evaluates to NaN, +Inf, or -Inf results in an error exception which is propagated in the remainder of the expression.
[9] Integer ::= [0-9]+ [10] Exponent ::= [Ee] [+-]? Integer [11] NumberLiteral ::= Integer '.' [0-9]* Exponent? | '.' Integer Exponent? | Integer Exponent?
[12] Literal ::= StringLiteral | NumberLiteral
Keywords in FormCalc are reserved words and are case insensitive. Of these, the 'if', 'then', 'else', 'endif' keywords delimit the components of an IfExpression_{39}. The remaining keywords are keyword operators.
These keywords may not be used as identifiers:
[13] Keyword ::= 'if' | 'then' | 'else' | 'endif' | 'or' | 'and' | 'not' | 'eq' | 'ne' | 'le' | 'ge' | 'lt' | 'gt'
An identifier is a sequence of characters of unlimited length but always beginning with an alphabetic character, or an underscore (_) character, or a dollar sign ($) character.
FormCalc identifiers are case sensitive, i.e., identifiers whose characters only differ in case, are considered distinct. Case sensitivity is mandated by FormCalc's hosting environments.
[14] Identifier ::= ( AlphabeticCharacter | _ | $ ) ( AlphaNumericCharacter | _ | $ )*An alphabetic character is any Unicode character classified as a letter. An alphanumeric character is any Unicode character classified as either a letter, or a digit.
FormCalc defines a number of operators; they include unary operators, multiplicative operators, additive operators, relational operators, equality operators, logical operators, and the assignment operator.
FormCalc operators are symbols common to most other scripting languages:
[15] Operator ::= '=' | '|' | '&' | '==' | '<>' | '<=' | '>=' | '<' | '>' | '+' | '-' | '*' | '/'
Several of the FormCalc operators have an equivalent mnemonic operator keyword, e.g., RelationalOperator_{34}. These keyword operators are useful whenever FormCalc expressions are embedded in HTML and XML source text, where symbols <, >, and & have predefined meanings and must be escaped.
[16] Separator ::= '(' | ')' | '[' | ']' | ',' | '.' [17] Token ::= Literal | Keyword | Identifier | Operator | Separator
The syntactic grammar for FormCalc has the tokens defined in the preceding lexical grammar as its terminal symbols, and defines the set of productions, starting from the non-terminal symbol FormCalculation_{20}, to describe how sequences of tokens can form a syntactically valid calculation.
[20] FormCalculation ::= ExpressionList [21] ExpressionList ::= Expression ( Expression )* [22] Expression ::= AssignmentExpression | IfExpression | SimpleExpression [23] SimpleExpression ::= LogicalOrOperator [24] LogicalOrExpression ::= LogicalAndExpression ( LogicalOrOperator LogicalAndExpression )* [25] LogicalAndExpression ::= EqualityExpression ( LogicalAndOperator EqualityExpression )* [26] EqualityExpression ::= RelationalExpression ( LogicalAndOperator RelationalExpression )* [27] RelationalExpression ::= AdditiveExpression ( RelationalOperator AdditiveExpression )* [28] AdditiveExpression ::= MultiplicativeExpression ( AdditiveOperator MultiplicativeExpression )* [29] MultiplicativeExpression ::= UnaryExpression ( MultiplicativeOperator UnaryExpression )* [30] UnaryExpression ::= UnaryOperator UnaryExpression | PrimaryExpression [31] LogicalOrOperator ::= '|' | 'or' [32] LogicalAndOperator ::= '&' | 'and' [33] EqualityOperator ::= '==' | '<>' | 'eq' | 'ne' [34] RelationalOperator ::= '<=' | '>=' | '<' | '>' | 'le' | 'ge' | 'lt' | 'gt' [35] AdditiveOperator ::= '+' | '-' [36] MultiplicativeOperator ::= '*' | '/' [37] UnaryOperator ::= '-' | 'not' [38] PrimaryExpression ::= Literal | AccessorReference | BuiltinFunction | '(' SimpleExpression ')' [39] IfExpression ::= 'if' '(' SimpleExpression ')' 'then' ExpressionList [ 'else' ExpressionList ] 'endif' [40] AssignmentExpression ::= AccessorReference '=' SimpleExpression [41] AccessorReference ::= ContainerReference ('.' ContainerReference )* ('.' PropertyReference )? [42] ContainerReference ::= Identifier | Identifier '[' [+-]? Integer ']' | Identifier '[' '*' ']' [43] PropertyReference ::= Identifier [44] BuiltinFunction ::= Identifier '(' [ ArgumentList ] ')' [45] ArgumentList ::= SimpleExpression (',' SimpleExpression )*
A FormCalculation_{[20]} is just a list of expressions. Under nominal circumstances, each Expression_{[22]} evaluates to a value, and the value of an ExpressionsList_{[21]} is the value of last expression in the list. For example, if the FormCalculation_{[20]}
5 + abs(JF02) "Hello World" 10 * 3 + 5 * 4is associated with object
JF01
, then after the evaluation of this
FormCalculation_{[20]}, the value of object JF01
would be
50.
The grammar presented above defining a SimpleExpression_{[23]} is common to conventional languages. Operator precedence rules behave as expected, so, e.g.,
10 * 3 + 5 * 4is equivalent to
(10 * 3) + (5 * 4)and evaluates to 50. Similarly
0 and 1 or 2 > 1is equivalent to
(0 and 1) or (2 > 1)and evaluates to 1. Enumerating all the FormCalc operators in order, from high precedence to lowest precedence yields:
= (unary) - not * / + - < <= > >= lt le gt ge == <> eq ne & and | or
When performing numeric operations involving non numeric operands, the non numeric operands are first promoted to numbers; if the non numeric operand can be fully converted to a numeric value then that is its value; otherwise its value is zero (0). When promoting null-valued operands to numbers, their value is always zero. As examples, the expression
(5 - "abc") * 3evaluates to 15, i.e., (5 - 0) * 3 = 15, whereas
"100" / 10e1evaluates to 1, and
5 + null() + 3evaluates to 8.
When performing boolean operations on non boolean operands, the non boolean operands are first promoted to booleans; if the non boolean operand can be fully converted to a non zero value then its value is true (1); otherwise its value is false (0). When promoting null-valued operands to booleans, their value is always false. As examples, the expression
"abc" | 2evaluates to 1, i.e., false | true = true, whereas
if ("abc") then 10 else 20 endifevaluates to 20.
When performing string operations on non string operands, the non string operands are first promoted to strings by using their value as a string. When promoting null-valued operands to strings, their value is always the empty string. As examples, the expression
concat("The total is ", 2, " dollars and ", 57, " cents.")evaluates to "The total is 2 dollars and 57 cents."
All the intermediate results of numeric expressions are evaluated as double precision IEEE754 64 bit values. The final result is displayed with up to 11 fractional digits of precision. Should an intermediate expression yield an NaN, +Inf or -Inf, FormCalc will generate an error exception and propagate that error for the remainder of that expression, and the expression's value will always be zero, e.g.,
3 / 0 + 1
Handling of error exceptions returned from the evaluation of FormCalc expressions is application defined.
A LogicalOrExpression_{24} returns the result of a logical disjunction of its operands, or null if both operands are null. If not both null, the operands are promoted to numeric values, and a numeric operation is performed.
The LogicalOrOperators '|' and 'or', both represent the same logical-or operator. The logical-or operator returns the boolean result true, represented by the numeric value 1, whenever either operand is not 0 and returns the boolean result false, represented by the numeric value 0, otherwise.
A LogicalAndExpression_{25} returns the result of a logical conjunction of its operands, or null if both operands are null. If not both null, the operands are promoted to numeric values, and a numeric operation is performed.
The LogicalAndOperators '&' and 'and', both represent the same logical-and operator. The logical-and operator returns the boolean result true, represented by the numeric value 1, whenever both operand are not 0 and returns the boolean result false, represented by the numeric value 0, otherwise.
An EqualityExpression_{26} returns the result of an equality comparison of its operands.
If either operand is null, then a null comparison is performed. Null valued operands compare identically whenever both operands are null, and compare differently whenever one operand is not null.
If both operands are string valued, then a locale-sensitive string comparison is performed on the operands. Otherwise, if not both null, the operands are promoted to numeric values, and a numeric comparison is performed.
The EqualityOperators '==' and 'eq', both denote the equality operator. The equality operator returns the boolean result true, represented by the numeric value 1, whenever both operands compare identically and returns the boolean result false, represented by the numeric value 0, otherwise.
The EqualityOperators '<>' and 'ne', both denote the inequality operator. The inequality operator returns the boolean result true, represented by the numeric value 1, whenever both operands compare differently and returns the boolean result false, represented by the numeric value 0, otherwise.
A RelationalExpression_{27} returns the result of a relational comparison of its operands.
If either operand is null valued, then a null comparison is performed. Null valued operands compare identically whenever both operands are null and the relational operator is less-than-or-equal or greater-than-or-equal, and compare differently otherwise.
If both operands are string valued, then a locale-sensitive string comparison is performed on the operands. Otherwise, if not both null, the operands are promoted to numeric values, and a numeric comparison is performed.
The RelationalOperators '<' and 'lt', both denote the same less-than operator. The less-than-or-equal relational operator returns the boolean result true, represented by the numeric value 1, whenever the first operand is less than the second operand, and returns the boolean result false, represented by the numeric value 0, otherwise.
The RelationalOperators '<=' and 'le', both denote the less-than-or-equal operator. The less-than-or-equal relational operator returns the boolean result true, represented by the numeric value 1, whenever the first operand is less than or equal to the second operand, and returns the boolean result false, represented by the numeric value 0, otherwise.
The RelationalOperators '>' and 'gt', both denote the same greater-than operator. The greater-than relational operator returns the boolean result true, represented by the numeric value 1, whenever the first operand is greater than the second operand, and returns the boolean result false, represented by the numeric value 0, otherwise.
The RelationalOperators '>=' and 'ge', both denote the greater-than-or-equal operator. The greater-than-or-equal relational operator returns the boolean result true, represented by the numeric value 1, whenever the first operand is greater than or equal to the second operand, and returns the boolean result false, represented by the numeric value 0, otherwise.
An AdditiveExpression_{28} returns the result of an addition (or subtraction) of its operands, or null if both operands are null. If not both null, the operands are promoted to numeric values, and a numeric operation is performed.
The AdditiveOperator '+', is the addition operator; it returns the sum of its operands.
The AdditiveOperator '-', is the subtraction operator; it returns the difference of its operands.
A MultiplicativeExpression_{29} returns the result of a multiplication (or division) of its operands, or null if both operands are null. If not both null, the operands are promoted to numeric values, and a numeric operation is performed.
The MultiplicativeOperator '*', is the multiplication operator; it returns the product of its operands.
The MultiplicativeOperator '/', is the division operator; it returns the quotient of its operands.
A UnaryExpression_{30} returns the negation of its operand.
The UnaryOperator '-' denotes the arithmetic negation operator; it returns the arithmetic negation of its operand, or null if its operand is null. If its operand is not null, it is promoted to a numeric value, and the negation operation is performed.
The UnaryOperator 'not' denotes the logical negation operator. it returns the logical negation of its operand. Its operand is promoted to a boolean value, and the logical operation is performed.
The logical negation operation returns the boolean result true, represented by the numeric value 1, whenever its operand is 0, and returns the boolean result false, represented by the numeric value 0, otherwise.
Note: the arithmetic negation of a null operand yields the result null, whereas the logical negation of a null operand yields the boolean result true. This is justified by the common sense statement: If null means nothing then "not nothing" should be something.
A PrimaryExpression_{38} is the building block of all simple expressions. It consists of Literals_{12}, AccessorReferences_{41}, BuiltinFunctions_{44}, and parenthesised SimpleExpressions_{39}.
An IfExpression_{39} is a conditional expression, which will either evaluate and return the value of the ExpressionList_{21} in its then-part or evaluate and return the value of the ExpressionList_{21} in its else-part depending upon the value of the SimpleExpression_{39} in the if-part.
In either circumstance, only one of the expression lists is ever evaluated.The value of the SimpleExpression_{39} in the if-part is promoted to a boolean value and a logical boolean operation is performed. If this boolean operation evaluates to true (1), the value of the ExpressionList_{21} in the then-part is returned. Otherwise, the value of the ExpressionList_{21} in the else-part is returned; if there is no else-clause, the value 0 is returned.
An AssignmentExpression_{40} sets the property identified by the AccessorReference_{41} to the value of the SimpleExpression_{39}.
The value of an AssignmentExpression is the value of the SimpleExpression.
FormCalc provides access to object properties and values. An AccessorReference_{41} is the syntactic element through which object values and properties are assigned, when used on the left-hand side of an AssignmentExpression_{40}, or retrieved, when used in a SimpleExpression_{39}, as in:
Invoice.VAT = Invoice.subtotal * (8 / 100)Accessor references may consist of a fully qualified hierarchy of objects optionally followed by a property reference, as in:
Invoice.Border.Edge[1].Color = "255,9,9"An hierarchy of objects presupposes an architectural model, but that description is outside the scope of this document.
Because there can be multiple instances of referenced objects with the same name on a form, each instance gets assigned an occurrence number, starting from one. To refer to a specific instance of an object which bears the same ambiguous name as other objects, it is required that the name by qualified by an occurrence number corresponding to the desired ordinal instance of the object.
Aside from a reference to the absolute occurrence of a object, there also exists the need to refer to the relative occurrence of a object, and to all occurrences of a object. To that end, FormCalc uses the notation:
Identifier |
to refer to an occurrence of the object that bears the same ordinal occurrence number as the referencing object. |
Identifier[n] |
to refer to the n'th occcurence of the identified object. |
Identifier[+n] |
to refer to the n'th succeeding occcurence of the identified object, relative to the referencing object's occurence number. |
Identifier[-n] |
to refer to the n'th preceding occcurence of the identified object, relative to the referencing object's occurence number. |
Identifier[*] |
to reference every occcurence of the identified object. |
Identifier[+0]
, Identifier[-0]
, and Identifier[0]
all refer to the identified object whose occurence number is the same as the referencing
object.
For a definition of referencing object and object scoping rules, you are referred to Scripting Object Model Specification for a thorough description of these.
This specification recommends that the processing application forbids from including a dollar sign ($) character in the names of objects and properties, so that this character can be successfully reserved for special application-defined names.
FormCalc supports a large set of built-in functions to do arithmetic, scientific, financial, logic, date, time, and string operations.
The names of the FormCalc functions are case insensitive, but are not reserved. This means that calculations on forms with objects whose names coincide with the names of built-in functions do not conflict; any object or built-in function can be equally referenced. Case insensitivity of built-in function names is mandated by FormCalc's historical legacy.
All built-in functions take an ArgumentList_{45}. The number and type of arguments varies with each function. Some, like Pi() take no arguments. Others, like Num2Date() take 1, 2 or 3 arguments, the first argument being a number, with the remaining arguments being strings. Many functions accept a variable number of arguments. Leading arguments are mandatory, and trailing arguments are often optional. This maintains the complexity of most functions at a low level. Increased functionality is provided to those users who need it by requiring them to supply the additional arguments.
All arguments in an ArgumentList_{45} are evaluated in order, leading arguments first. If the number of mandatory arguments passed to a function is less than the number required, the function generates an error exception.
Expressions can often evaluate to a set of values, so it is not always possible to determine the exact number of arguments passed to a function at time of compilation. For example, consider the following FormCalculation
Max(JF01[*])If there are no occurrences of object
JF01
, then the function Max()
will generate an error exception. If there is a single occurrence of object JF01
,
then the function Max() will return the value of that object occurrence. If there
are multiple occurrences of object JF01
, then the function Max()
will return the maximum value of all those object occurrences.
Note: for all occurrences of a given object to be are included in a calculation,
the object must be specified using the [*]-style reference, e.g., Sum(JF01[*])
will sum all occurrences of object JF01
. Specifying Sum(JF01)
will only sum a single occurrence of object JF01
.
In many built-in functions, the description of the formal arguments stipulates that it must be a single value, but it may be that the passed argument evaluates to a set of values. In such circumstances, the function will generate an error exception. For example, the following FormCalculation
Sqrt(JF01[*])will always generate an error exception, irrespectively of the number of occurrences of object
JF01
.
Many functions require numeric arguments. If any of the passed arguments are non-numeric, they are promoted to numbers. Some function arguments only require integral values; in such cases, the passed arguments are always promoted to integers by truncating the fractional part.
This function returns the absolute value of a given number.
Abs(n1)
The absolute value or null if its parameter is null.
Abs(1.03)
returns 1.03.
Abs(-1.03)
returns 1.03.
Abs(0)
returns 0.
This function returns the average of the non-null elements of a given set of numbers.
Avg(n1 [, n2...])
The average of its non-null parameters, or null if its parameter are all null.
Avg(JF01, JF02, JF03, JF04)
returns 9 if JF01
has a value of 8, JF02
has value
10, and JF03
and JF04
are null.
Avg(JF01[*])
returns 9 if JF01
has two occurrences with values of 8 and 10,
and returns null if all occurrences of JF01
are null.
This function returns the whole number greater than or equal to a given number.
Ceil(n1)
The ceiling or null if its parameter is null.
Ceil(1.9)
returns 2.
Ceil(-1.9)
returns -1.
Ceil(A)
is 100 if the value A is 99.999
This function returns the count of the non-null elements of a given set of numbers.
Count(n1 [, n2...])
The count.
Count(5, "ABCD", "", null())
returns 3.
Count(JF01[*])
returns the number of occurrences of JF01
that are non-null, and
returns 0 if all of occurrences of JF01
are null.
This function returns the largest whole number that is less than or equal to a given value.
Floor(n1)
The floor or null if its parameter is null.
Floor(6.5)
returns 6.
Floor(7.0)
returns 7.
Floor(JF01)
returns 99 if the value of JF01
is 99.999.
This function returns the maximum value of the non-null elements of a given set of numbers.
Max(n1 [, n2...])
The maximum of its non-null parameters, or null if all its parameters are null.
Max(JF01[*], 100)
returns the maximum value of all occurrences of the object JF01 or 100, whichever is greater.
Max(7, 10, null(), -4, 6)
returns 10.
Max(null())
returns null.
This function returns the minimum value of the non-null elements of a given set of numbers.
Min(n1 [, n2...])
The minimum of its non-null parameters, or null if all its parameters are null.
Min(7, 10, null(), -4, 6)
returns -4.
Min(JF01[*], 100)
returns the minimum value of all occurrences of the object JF01 or 100, whichever is less.
Min(null())
returns null.
This function returns the modulus of one number divided by another.
Mod(n1, n2)
The modulus or null if any of its parameter are null.
The modulus is the remainder of the implied division of the dividend and the divisor. The sign of the remainder always equals the sign of the dividend.
For integral operands, this is simple enough. For floating point operands,
the floating point remainder r
of mod(n1, n2)
is defined
as r = n1 - (n2 * q)
where q
is an integer whose sign
is negative when n1 / n2
is negative, and positive when n1
/ n2
is positive, and whose magnitude is the largest integer less than
the quotient n1 / n2
.
If the divisor is zero, the function generates an error exception.
Mod(64, 2)
returns 0.
Mod(-13, 3)
returns -1.
Mod(13, -3)
returns 1.
Mod(-13.6, 2.2)
returns -0.4.
This function returns a number rounded to a given number of decimal places.
Round(n1 [, n2])
The rounded value or null if any of its parameters are null.
Round(33.2345, 3)
returns 33.235.
Round(20/3, 2)
returns 6.67.
Round(-1.3)
returns -1.
Round(JF01, 2)
returns 2.33 if the value of the object JF01 is 2.3333
This function returns the sum of the non-null elements of a given set of numbers.
Sum(n1 [, n2...])
The sum of its non-null parameters, or null if all of its parameters are null.
Sum(1, 2, 3, 4)
returns 10.
Sum(JF01[*])
returns the sum of all occurrences of the object JF01.
Sum(JF01[2], JF01[3])
returns the sum of two occurrences of the object JF01.
This function returns the arc cosine value of a given number.
Acos(n1)
The arc cosine value in radians or null if its parameter is null.
If n1 is outside the range -1 to 1, the function generates an error exception.
Acos(1)
returns 0.
Acos(-1)
returns 3.14159265359.
This function returns the arc sine value of a given number.
Asin(n1)
The arc sine value in radians or null if its parameter is null.
If n1 is outside the range -1 to 1, the function generates an error exception.
4 * Asin(1 / Sqrt(2))
returns 3.14159265359.
This function returns the arc tangent value of a given number.
Atan(n1)
The arc tangent value in radians or null if its parameter is null.
4 * Atan(1)
returns 3.14159265359.
This function returns the arc tangent value of the quotient of two given numbers. The signs of the given numbers are used to calculate the quadrant of the result.
Atan2(n1, n2)
The arc tangent value in radians of n1 / n2, or null if its parameters are null.
Atan2(0, -2.33)
returns 3.14159265359.
This function returns the cosine value of a given number.
Cos(n1)
The cosine value or null if its parameter is null.
Cos(0)
returns 1.
This function returns the radian value of a given number.
Deg2Rad(n1)
The radian value or null if its parameter is null.
Deg2Rad(180)
returns 3.14159265359.
This function returns the value of e raised to the power of a given number.
Exp(n1)
e raised to a power or null if its parameter is null.
Exp(1)
returns 2.71828182846.
Exp(-1)
returns 0.36787944117.
This function returns the natural logarithm value a given number.
Log()
The natural logarithm or null if its parameter is null.
If n1 is non-positive, the function generates an error exception.
Log(Exp(1))
returns 1.
This function returns the value of pi which is 3.14159265359.
Pi()
pi.
Pi() * (RADIUS * RADIUS)
returns the area of a circle given by the value of the object RADIUS.
This function returns the value of a given number raised to the power of another.
Pow(n1, n2)
The value raised to the power or null if any of its parameters are null.
If n2 is 0, the function returns 1.
Pow(3, 2)
returns 9.
Pow(-12.0, 2.2)
returns 144.
This function returns the degree value of a given number.
Deg2Rad(n1)
The degree value or null if its parameter is null.
Rad2Deg(Pi() / 4)
returns 45.
This function returns the sine value of a given number.
Sin(n1)
The sine value or null if its parameter is null.
Sin(Pi() / 2)
returns 1.
This function returns the square root of a given number.
Sqrt(n1)
The square root or null if its parameter is null.
If n1 is negative, the function generates an error exception.
Sqrt(4)
returns 2.
Sqrt(100)
returns 10.
This function returns the tangent value of a given number.
Tan(n1)
The tangent value or null if its parameter is null.
Tan(Pi() / 4)
returns 1.
A number of built-in date and time functions are provided, to allow the form designer to:
DateFmt()
and LocalDateFmt()
),
Date2Num()
),
Date()
),
Num2Date()
).
TimeFmt()
and LocalTimeFmt()
),
Time2Num()
),
Time()
),
Num2Time()
).
IsoDate2Num()
and IsoTime2Num()
).
To properly parse and format a date, we need to know what format it is in, and what locale it comes from. As we all know, dates are represented differently, even within the same country. So we need to define the concepts of locale and date format more precisely.
FormCalc is locale sensitive; see the section "Locale" in the XFA-Template specification for more information.
Short date formats tend to be purely numeric, e.g.,
10/2/70.
Medium date formats specify use of abbreviated month names, e.g.,
10-Feb-70,
and long date formats specify use of full month names, e.g.,
February 10, 1970.
Full date formats tend to include the weekday name, as in:
Thursday, February 10, 1970.
The default format tends to coincide with the medium date format.
Specifically, in the default en_US locale, the default
date format is
MMM D, YYYY.
Properly internationalized applications then, will always query the locale for a date format. The form designer has the option of choosing from either the default, short, medium, long or full formats, and will never present to the user a hand-crafted date format. Except for the need of a common format for data interchange, use of hand-crafted date formats are best avoided.
For a specification of how to construct date formats, refer to the section "Date Pictures" within the XFA-Template specification for more information.
Examples of date formats include:
Date formats are used to both format and parse date strings, using the built-in functions Num2Date() and Date2Num(). All formatting and parsing is strict; when formatting, all literals and punctuations are included, and when parsing, all literals and punctuations must be matched exactly. If the date format is meaningless, no formatting nor parsing is attempted.
As another example, the full date format for the German-speaking part of Switzerland
is
"EEEE, D. MMMM YYYY".
The equivalent localized date format is
"EEEE, t. MMMM uuuu",
which is hopefully more meaningful to these users than it is to us, and that
"EEEE, D. MMMM YYYY"
is to them.
The built-in functions Num2Date() and Date2Num() do not understand localized date formats; they only understand the date formats defined above. Use of these localized date formats is for UI presentation only.
The default time format tends to coincide with the medium time format. Specifically, in the default en_US locale, the default time format is h:MM:SS A.
Just as with a date format, a time format is a shorthand specification to format a time. It consists of punctuations, literals, and pattern symbols, e.g., "HH:MM:SS" is a time format.
For a specification of how to construct time formats, refer to the section "Time Pictures" within the XFA-Template specification for more information.
Examples of time formats include:
Any time format containing incorrectly specified pattern symbols, e.g., HHH are invalid. When parsing, time formats with multiple instances of the same pattern symbols, e.g., HH:MM:HH are invalid, as are time formats with conflicting pattern symbols, e.g., h:HH:MM:SS. Time formats with adjacent one letter pattern symbols, e.g., HMS, are inherently ambiguous and should be avoided.
To do basic arithmetic on dates and times, we introduce the concept of date values and time values. Both of these are of numeric type, but their actual numeric value is implementation defined and thus meaningless in any context other than a date or time function. In other words, a FormCalculation obtains a date value from a date function, performs some arithmetic on that date value, and only passes that value to another date function. These same rules apply to time values.
Both date values and time values have an associated origin or epoch -- a moment in time when things began. Any date value prior to its epoch is invalid, as is, any time value prior to its epoch.
The unit of value for all date function is the number of days since the epoch. The unit of value for all time functions is the number of milliseconds since the epoch.
The reference implementation defines the epoch for all date functions such that day 1 is Jan 1, 1900, and defines the epoch for all time functions such that millisecond 1 is is midnight, 00:00:00, GMT. This means negative time values may be returned to users in timezones east of Greenwich Mean Time.
The return values provided as examples in the following functions are based on this implementation; a number followed by an ^{*} indicates implementation-specific date and time values. Actual values may vary.
This function returns the current system date as the number of days since the epoch.
Date()
The number of days for the current date.
Date()
returns 35733^{*} on Oct 31 1998.
This function returns the number of days since the epoch, given a date string.
Date2Num(d1[, f1[, k1]])
The days since the epoch or null if any of its parameters are null.
If the given date is not in the format given, or the format is invalid, or the locale is invalid, the function returns 0.
Sufficient information must be provided to determine a unique day since the epoch: if any of the day of the year and year of the era are missing, or any of the day of the month, month of the year and year of the era are missing, the function returns 0.
Date2Num("Mar 15, 1996")
returns 35138^{*}.
Date2Num("1/1/1900", "D/M/YYYY")
returns 1^{*}.
Date2Num("03/15/96", "MM/DD/YY")
returns 35138^{*}.
Date2Num("Aug 1,1996", "MMM D,YYYY")
returns 35277^{*}.
Date2Num("31-ago-96", "DD-MMM-YY", "es_ES")
returns 35307^{*}.
Date2Num("1/3/00", "D/M/YY") - Date2Num("1/2/00", "D/M/YY")
returns 29, year 2000 being a leap year!
Num2Date()
, and DateFmt()
.
This function returns a date string, given a number of days since the epoch.
Num2Date(n1 [,f1 [, k1]])
The date string or null if any of its parameters are null.
The formatted date is in the format given in f1, governed by the locale given in k1.
If the given date is invalid, the function returns an empty string.
Num2Date(1, "DD/MM/YYYY")
returns "01/01/1900".
Num2Date(35139, "DD-MMM-YYYY", "de_CH")
returns "16-Mrz-1996".
Num2Date(Date2Num("31-ago-98", "DD-MMM-YY", "es_ES") - 31, "D' de 'MMMM' de 'YYYY", "pt_BR")
returns "31 de Julho de 1998".
Date2Num()
, DateFmt()
, and Date()
.
This function returns a date format string, given a date format style.
DateFmt([n1[, k1]]])
The date format or null if any of its parameters are null.
If the given format style is invalid, the function returns default-style date format.
DateFmt()
returns "MMM D, YYYY". This is the default date format .
DateFmt(1)
returns "M/D/YY".
DateFmt(2, "fr_CA")
returns "YY-MM-DD".
DateFmt(3, "de_DE")
returns "D. MMMM YYYY".
DateFmt(4, "es_ES")
returns "EEEE D' de 'MMMM' de 'YYYY".
Num2Date()
, Date2Num()
, and LocalDateFmt()
.
This function returns a localized date format string, given a date format style.
LocalDateFmt([n1[, k1]]])
The localized date format or null if any of its parameters are null.
If the given format style is invalid, the function returns default-style localized date format.
The date format strings returned by this function are not usable in the functions
Date2Num()
and Num2Date()
.
LocalDateFmt(1, "de_DE")
returns "tt.MM.uu".
LocalDateFmt(2, "fr_CA")
returns "j nnn aa".
LocalDateFmt(3, "de_DE")
returns "t. MMMM uuuu".
LocalDateFmt(4, "es_ES")
returns "EEEE t' de 'MMMM' de 'uuuu".
DateFmt()
.
This function returns the current system time as the number of milliseconds since the epoch.
Time()
The number of milliseconds for the current time.
Time()
returns 61200001^{*} at precisely noon to a user in Boston.
This function returns the number of milliseconds since the epoch, given a time string.
Time2Num(d1[, f1[, k1]])
The milliseconds from the epoch or null if any of its parameters are null.
If the time string does not include a timezone, the current timezone is used.
The locale is used to parse any timezone names.
If the given time is not in the format given, or the format is invalid, or the locale is invalid, the function returns 0.
Sufficient information must be provided to determine a second since the epoch: if any of the hour of the meridiem, minute of the hour, second of the minute, and meridiem are missing, or any of the hour of the day, minute of the hour, and second of the minute are missing, the function returns 0.
Time2Num("00:00:00 GMT", "HH:MM:SS Z")
returns 1^{*}.
Time2Num("1:13:13 PM")
returns 76393001^{*} to a user in California.
(Time2Num("13:13:13", "HH:MM:SS") - Time2Num("13:13:13 GMT", "HH:MM:SS Z")) / (60 * 60 * 1000)
returns 8 to a user in Vancouver and returns 5 to a user in Ottawa.
Time2Num("1.13.13 PM GMT+01:00", "h.MM.SS A Z", "it_IT")
returns 43993001^{*}.
Num2Time()
, and TimeFmt()
.
This function returns a GMT time string, given a number of milliseconds from the epoch.
Num2GMTime(n1 [,f1 [, k1]])
The GMT time string or null if any of its parameters are null.
The formatted time is in the format given in f1, governed by the locale given in k1.
The locale is used to format any timezone names.
If the given time is invalid, the function returns an empty string.
Num2GMTime(1, "HH:MM:SS")
returns "00:00:00".
Num2GMTime(65593001, "HH:MM:SS Z")
returns "18:13:13 GMT".
Num2GMTime(43993001, TimeFmt(4, "de_CH"), "de_CH")
returns "12.13 Uhr GMT".
Num2Time()
.
This function returns a time string, given a number of milliseconds from the epoch.
Num2Time(n1 [,f1 [, k1]])
The time string or null if any of its parameters are null.
The formatted time is in the format given in f1, governed by the locale given in k1.
The locale is used to format any timezone names.
If the given time is invalid, the function returns an empty string.
Num2Time(1, "HH:MM:SS")
returns "00:00:00" in Greenwich, England and "09:00:00" in Tokyo.
Num2Time(65593001, "HH:MM:SS Z")
returns "13:13:13 EST" in Boston.
Num2Time(65593001, "HH:MM:SS Z", "de_CH")
returns "13:13:13 GMT-05:00" to a German Swiss user in Boston.
Num2Time(43993001, TimeFmt(4, "de_CH"), "de_CH")
returns "13.13 Uhr GMT+01:00" to a user in Zurich.
Num2Time(43993001, "HH:MM:SSzz")
returns "13:13+01:00" to that same user in Zurich.
Date2Num()
, DateFmt()
, and Date()
.
This function returns a time format given a time format style.
TimeFmt([n1[, k1]]])
The time format or null if any of its parameters are null.
If the given format style is invalid, the function returns default-style time format.
TimeFmt()
returns "h:MM:SS A".
TimeFmt(1)
returns "h:MM A".
TimeFmt(2, "fr_CA")
returns "HH:MM:SS".
TimeFmt(4, "de_DE")
returns "H.MM' Uhr 'Z".
Time()
.
This function returns a localized time format string, given a time format style.
LocalTimeFmt([n1[, k1]]])
The localized time format or null if any of its parameters are null.
If the given format style is invalid, the function returns default-style localized time format.
The time format strings returned by this function are not usable in the functions
Time2Num()
and Num2Time()
.
LocalTimeFmt(1, "de_DE")
returns "HH:mm".
LocalTimeFmt(2, "fr_CA")
returns "HH:mm:ss".
LocalTimeFmt(3, "de_DE")
returns "HH:mm:ss z".
LocalTimeFmt(4, "es_ES")
returns "HH'H'mm'' z".
TimeFmt()
.
This function returns the number of days since the epoch, given an [ISO-8601] date string.
IsoDate2Num(d1)
The days from the epoch or null if its parameter is null.
If the given date is not in one of the accepted formats, the function returns 0.
IsoDate2Num("1900")
returns 1.
IsoDate2Num("1900-01")
returns 1.
IsoDate2Num("1900-01-01")
returns 1.
IsoDate2Num("19960315T20:20:20")
returns 35138.
IsoDate2Num("2000-03-01") - IsoDate2Num("20000201")
returns 29.
IsoTime2Num()
, and Num2Date()
.
This function returns the number of milliseconds since the epoch, given an [ISO-8601] time string.
IsoTime2Num(d1)
The number of milliseconds from the epoch or null if its parameter is null.
If the time string does not include a timezone, the current timezone is used.
If the given time is not in a valid format, the function returns 0.
IsoTime2Num("00:00:00Z")
returns 1.
IsoTime2Num("13")
returns 64800001 to a user in Boston.
IsoTime2Num("13:13:13")
returns 76393001 to a user in California.
IsoTime2Num("19111111T131313+01")
returns 43993001.
IsoDate2Num()
, and Num2Time()
.
Note: the value of the results in the examples of this section have all been rounded for presentation purposes. A number followed by an ^{*} indicates a rounded return value.
This function returns the annual percentage rate for a loan.
Apr(n1, n2, n3)
The annual percentage rate or null if any of its parameters are null.
If any of n1, n2, or n3 are non-positive, the function generates an error exception.
Apr(35000, 269.50, 30 * 12)
returns 0.085^{*} (8.5%) which is the annual interest rate on a loan of $35,000 being repaid at $269.50 per month over 30 years.
This function returns the number of periods needed for an investment earning a fixed, but compounded, interest rate to grow to a future value.
CTerm(n1, n2, n3)
The number of periods or null if any of its parameters are null.
If any of n1, n2, or n3 are non-positive, the function generates an error exception.
CTerm(.02, 200, 100)
returns 35^{*}, which is the required period for $100 invested at 2% to grow to $200.
This function returns the future value of periodic constant payments at a constant interest rate.
FV(n1, n2, n3)
The future value or null if any of its parameters are null.
If n1 or n3 are non-positive, or if n2 is negative, the function generates an error exception.
If n2 is 0, the function returns the product of n1 and n3, i.e., the payment amount multiplied by the number of payments.
FV(100, .075 / 12, 10 * 12)
returns 17793.03^{*}, which is the amount present after paying $100 a month for 10 years in an account bearing an annual interest of 7.5%.
FV(1000, 0.01, 12)
returns 12682.50^{*}.
This function returns the amount of interest paid on a loan over a period of time.
IPmt(n1, n2, n3, n4, n5)
The interest amount or null if any of its parameters are null.
If any of n1, n2, or n3 are non-positive, the function generates an error exception.
If n4 or n5 are negative, the function generates an error exception.
If the payment is less than the monthly interest load, the function returns 0.
IPmt(30000, .085, 295.50, 7, 3)
returns 624.88^{*} which is the amount of interest paid starting in July (month 7) for 3 months on a loan of $30,000.00 at an annual interest rate of 8.5% being repaid at a rate of $295.50 per month.
This function returns the net present value of an investment based on a discount rate, and a series of periodic future cash flows.
NPV(n1, n2 [, ...])
The net present value rate or null if any of its parameters are null.
The function uses the order of the values n2, ... to interpret the order of the cash flows. Ensure payments and incomes are specified in the correct sequence.
If n1 is non-positive, the function generates an error exception.
NPV(0.15, 100000, 120000, 130000, 140000, 50000)
returns 368075.16^{*} which is the net present value of an investment projected to generate $100,000, $120,000, $130,000, $140,000 and $50,000 over each of the next five years and the rate is 15% per annum.
NPV(0.10, -10000, 3000, 4200, 6800)
returns 1188.44^{*}.
NPV(0.08, 8000, 9200, 10000, 12000, 14500)
returns 41922.06^{*}.
This function returns the payment for a loan based on constant payments and a constant interest rate.
Pmt(n1, n2, n3)
The loan payment or null if any of its parameters are null.
If any of n1, n2, or n3 are non-positive, the function generates an error exception.
Pmt(30000.00, .085 / 12, 12 * 12)
returns 333.01^{*}, which is the monthly payment for a loan of a $30,000, borrowed at a yearly interest rate of 8.5%, repayable over 12 years (144 months).
Pmt(10000, .08 / 12, 10)
returns 1037.03^{*}, which is the monthly payment for a loan of a $10,000 loan, borrowed at a yearly interest rate of 8.0%, repayable over 10 months.
This function returns the amount of principal paid on a loan over a period of time.
PPmt(n1, n2, n3, n4, n5)
The principal paid or null if any of its parameters are null.
If any of n1 , n2 , or n3 are non-positive, the function generates an error exception.
If n4 or n5 are negative, the function generates an error exception.
If payment is less than the monthly interest load, the function generates an
error exception.
PPmt(30000, .085, 295.50, 7, 3)
returns 261.62^{*}, which is the amount of principal paid starting in July (month 7) for 3 months on a loan of $30,000 at an annual interest rate of 8.5%, being repaid at $295.50 per month. The annual interest rate is used in the function because of the need to calculate a range within the entire year.
This function returns the present value of an investment of periodic constant payments at a constant interest rate.
PV(n1, n2, n3)
The present value or null if any of its parameters are null.
If any of n1 and n3 are non-positive, the function generates an error exception.
PV(1000, .08 / 12, 5 * 12)
returns 49318.43^{*} which is the present value of $1000.00 invested at 8% for 5 years.
PV(500, .08 / 12, 20 * 12)
returns 59777.15^{*}.
This function returns the compound interest rate per period required for an investment to grow from present to future value in a given period.
Rate(n1, n2, n3)
The compound rate or null if any of its parameters are null.
If any of n1, n2 , or n3 are non-positive, the function generates an error exception.
Rate(110, 100, 1)
returns 0.10 which is what the rate of interest must be for and investment of $100 to grow to $110 if invested for 1 term.
This function returns the number of periods needed to reach a given future value from periodic constant payments into an interest bearing account.
Term(n1, n2, n3)
The number of periods or null if any of its parameters are null.
If any of n1, n2, or n3 are non-positive, the function generates an error exception.
Term(475, .05, 1500)
returns 3^{*} which is the number of periods for an investment of $475, deposited at the end of each period into an account bearing 5% compound interest, to grow to $1500.00.
Most of these Logical functions return the boolean results true or false, represented by the numeric values of 1 and 0, respectively.
Some of the following built-in function examples make use of the identifier $ to mean a reference to the value of the object to which the FormCalculation is bound.
Returns conditional values based on the value of a given number.
If(n1, e1 [,e2])
The conditional value or null if its first parameter is null.
Note that both simple expressions e1 and e2 are always evaluated.
If(JF01 > 100, .10, .05)
returns the value .10 if object JF01
is greater than 100, and
.05 otherwise.
If(RESPONSE == "YES" | RESPONSE =="Y", "GO TO SECTION A")
returns "GO TO SECTION A" if the object RESPONSE contains the value "YES" or "Y"; otherwise an empty string is returned.
See also the IfExpression_{39} which provides for more flexible conditional expressions, particularly when the expressions e1 and e2 need to be lists of expressions.
If(FF01 <> Null(), "is not null", "is null")
returns "is not null" if object FF01 is not null, and "is null" if object FF01 is null.
Return()
.
This function selects a value from a given set of parameters.
Choose(n1, s1 [, s2...])
The selected argument or null if its first parameter is null.
If n1 is less than 1 or greater than the number of arguments in the set, the function returns an empty string.
Choose(3, "Accounting", "Administration", "Personnel", "Purchasing")
returns "Personnel".
Choose(JF01, "A", "B", "C")
returns B if the value in JF01 is 2.
This logical function returns true if a value is in a given set.
Oneof(s1, s2 [, s3...])
True (1) if the first parameter is in the set, false (0) if it is not in the set.
Oneof($, 4, 13, 24)
returns true (1) if the current object has a value of 4, 13 or 24; otherwise it returns false (0).
Oneof(JF01, null(), "A", "B", "C")
returns true (1) if the value in the object JF01 is null, "A", "B" or "C"; otherwise it returns false (0).
This logical function returns true if a value is within a given range.
Within(s1, s2, s3)
True (1) if the first parameter is within range, false (0) if it is not in range, or null if the first parameter is null.
If the first value is numeric then the ordering comparison is numeric.
If the first value is non-numeric then the ordering comparison uses the collating sequence for the current locale.
Within("C", "A", "D")
returns true (1).
Within(1.5, 0, 2)
returns true (1).
Within(-1, 0, 2)
returns false (0).
Within ($, 1, 10)
returns true (1) if the value of the current object is between 1 and 10.
This function stops the evaluation of an expression and returns a given value. It is typically used in the body of an IfExpression_{39} to alter the flow of expression evaluation.
Return([v1])
The return value.
If (F1 == F2) Then Return() Endif F3
will return without ever evaluating F3 whenever F1 equals F2.
1 + Return(2)
returns 2, and not 3. The additive expression never gets evaluated.
This list of functions may grow over time, for instance to include to retrieve system or application specific properties, but for now, its limited to the following
This function returns the value of a given expression.
Eval(e1)
The value of the expression.
If e1 is not a valid expression, the function generates an error exception.
Eval("ABC")
returns "ABC".
Eval("10 * 3 + 5 * 4")
returns 50.
Eval(FF01)
returns FF02 if the value of FF01 was "FF02".
Sum(Eval(FF01))
returns 133 if the value of FF01 was "FF02 + 10", and the value of FF02 was 123.
This function returns the null value.
Null()
The null value. The null value really means no value.
Concat("ABC", Null(), "DEF")
returns "ABCDEF".
Null() + 5
returns 5.
FF01 = Null()
returns null and assigns null to the object FF01.
FF01 = Null() + 5
returns 5 and assigns the value 5 to the object FF01.
FormCalc provides a large number of function to operate on the content of strings, including the ability to:
Many of these functions require a numeric position argument. All strings are indexed starting at character position one; i.e., character position 1 is the first character of the array. The last character position coincides with the length of the string.
Any character position less than one refers to the first character string, and any character position greater than the length of the string refers to the last character of the string.
This function locates the starting character position of string s2 within string s1.
At(s1,s2)
The character position of the start of s2 within s1 or null if any of its parameters are null.
If string s2 is not in s1, the function returns 0.
If string s2 is empty, the function returns 1.
At("ABC", "AB")
returns 1.
At("ABCDE", "DE")
returns 4.
At("WXYZ", "YZ")
returns 3.
At("123999456", "999")
returns 4.
This function returns the string concatenation of a given set of strings.
Concat(s1 [, s2...])
The concatenated string or null if all of its parameters are null.
Concat("ABC", "CDE")
returns "ABCCDE".
Concat("XX", JF01, "-01")
returns "XXABC-01" if the value of JF01
is "ABC".
This function extracts a number of characters from a given string, starting with the first character on the left.
Left(s1, n1)
The extracted string or null if any of its parameters are null.
If the number of characters to extract is greater than the length of the string, the function returns the whole string.
If the number of characters to extract is 0 or less, the function returns the empty string.
Left("ABCD", 2)
returns "AB".
Left("ABCD", 10)
returns "ABCD".
Left("XYZ-3031", 3)
returns "XYZ".
This function returns the length of a given string.
Len(s1)
The length or null if it parameter is null.
Len("ABC")
returns 3.
Len("ABCDEFG")
returns 7.
This function returns a string where all given uppercase characters are converted to lowercase.
Lower(s1[, k1])
The lowercased string or null if it parameter is null.
In some locales, there are alphabetic characters that do not have an lowercase equivalent.
Lower("Abc123X")
returns "abc123x".
Lower("ÀBÇDÉ")
returns "àbçdé".
This function returns a string with all leading white space characters removed.
Ltrim(s1)
The trimmed string or null if it parameter is null.
White space characters includes the ASCII space, horizontal tab, line feed, vertical tab, form feed, carriage return, file separator, group separator, record separator, and unit separator characters, as well as, the Unicode space, line, and paragraph separator characters.
Ltrim(" ABC")
returns "ABC".
Ltrim(" XY ABC")
returns "XY ABC".
This function replaces all occurrences of one string with another within a given string.
Replace(s1, s2[, s3])
The replaced string or null if any of its mandatory parameters are null.
Replace("it's a dog's life", "dog", "cat")
returns the string to "it's a cat's life".
Replace("it's a dog's life", "dog's ")
returns the string to "it's a life".
This function extracts a number of characters from a given string, beginning with the last character on the right.
Right(s1, n1)
The extracted string or null if any of its parameters are null.
If the number of characters to extract is greater than the length of the string, the function returns the whole string.
If the number of characters to extract is 0 or less, the function returns the empty string.
Right("ABC", 2)
returns "BC".
Right("ABC", 10)
returns "ABC".
Right("XYZ-3031", 4)
returns "3031".
This function returns a string with all trailing white space characters removed.
Rtrim(s1)
The trimmed string or null if any of its parameters are null.
White space characters includes the ASCII space, horizontal tab, line feed, vertical tab, form feed, carriage return, file separator, group separator, record separator, and unit separator characters, as well as, the Unicode space, line, and paragraph separator characters.
Rtrim("ABC ")
returns "ABC".
Rtrim("XYZ ABC ")
returns "XYZ ABC".
This function returns a string consisting of a given number of blank spaces.
Space(n1)
The blank string or null if it parameter is null.
Concat("Hello ", null(), "world.")
returns "Hello world.".
Concat(FIRST, Space(1), LAST)
returns "Gerry Pearl" when the value of the object FIRST is Gerry, and the value of the object LAST is Pearl.
This function converts a number to a character string.
Str(n1 [, n2 [, n3]])
The formatted number or null if any of its parameters are null.
The number is formatted to specified width and rounded to the specified precision; the number may have been zero-padded on the left of the decimal to the specified precision.
If the resulting string is longer than the maximal width of the string, as defined by n2, then the function returns a string of '*' (asterisk) characters of the specified width.
This function inserts a string into another string.
Stuff(s1, n1, n2[, s2])
The stuffed string or null if any of its mandatory parameters are null.
Stuff("ABCDE", 3, 2, "XYZ")
returns "ABXYZE".
Stuff("abcde", 4, 1, "wxyz")
returns "abcwxyze".
Stuff("ABCDE", 2, 0, "XYZ")
returns "AXYZBCDE".
Stuff("ABCDE", 2, 3)
returns "AE".
This function extracts a portion of a given string.
Substr(s1, n1, n2)
The sub string or null if any of its parameters are null.
If n1 + n2 is greater than the length of s1 then the function returns the sub string starting a position n1 to the end of s1 .
Substr("ABCDEFG", 3, 4)
returns "CDEF".
Substr("abcdefghi", 5, 3)
returns "efg".
This function returns a string with all given lowercase characters converted to uppercase.
Upper(s1[, k1])
The uppercased string or null if it parameter is null.
In some locales, there are alphabetic characters that do not have a lowercase equivalent.
Upper("abc")
returns "ABC".
Upper("àbCdé")
returns "ÀBCDÉ".
This function returns the English text equivalent of a given number.
WordNum(n1 [, n2 [, k1]])
The English text or null if any of its parameters are null.
By specifying an locale identifier other than the default, it should be possible to have this function return something other than English text. Note however that the language rules used to implement this function are inherently English.
If the integral value of n1 is negative or greater than 922,337,203,685,477,550 the function returns "*" (asterisk) characters to indicate an error condition.
WordNum(123.54)
returns "One Hundred Twenty-three".
WordNum(1011.54, 1)
returns "One Thousand Eleven Dollars".
WordNum(73.54, 2)
returns "Seventy-three Dollars And Fifty-four Cents".