FormCalc String, Date, and Finance Functions
XFA calculate scripts support the implemented function families beyond arithmetic: string functions, date conversion, and the finance library, with string literals and mixed-type expressions
String functions
Values and References documents Ref, value-copy semantics, reference assignment, null detachment, function arguments, object identity comparisons and retained handles across repeated-instance movement
Dynamic Eval executes source text through the native compiler and general runtime, including locally declared variables, functions, loops, field mutations, locale requests and recorded host transport responses
Concat, Len, Left, Right, Substr, Replace, Lower, Upper, Trim, and Space operate on quoted literals and field references; numeric sub-expressions convert to text automatically
Date functions
The native scalar evaluator converts ISO YYYY-MM-DD text with Date2Num and Num2Date; FormCalc serial days use 1900-01-01 as day 1, and Date() returns today's serial
General execution with EnableJavaScript also supports locale pictures through Date2Num(value, picture, locale), Num2Date(serial, picture, locale), DateFmt, TimeFmt, IsoTime2Num, Time2Num, Num2Time, Num2GMTime and Time
In general execution, omitted Num2Date pictures now use the ambient locale's default pattern; pass "YYYY-MM-DD" explicitly to preserve earlier ISO output, and use IsoDate2Num for strict ISO input
FormCalc Locale and Picture Functions documents parameters, inherited locale selection, embedded localeSet overrides, numeric/text pictures, units, encoding and number words
Advanced Picture Clauses documents scientific notation, expressed fractional precision, ordinal and ISO week dates, clock variants, global symbols and compound parsing in general events, calculations and validation
Finance functions
Financial functions now follow XFA FormCalc parameter semantics in the native calculate evaluator and the general event compiler
| Function | Parameters and result |
|---|---|
Pmt(principal, rate, periods) | Positive periodic loan payment; all arguments must be positive |
FV(payment, rate, periods) | Future value of equal payments; zero rate returns payment times periods |
PV(payment, rate, periods) | Present value of equal payments; zero rate returns payment times periods |
Rate(future, present, periods) | Compound rate required to grow the present value to the future value |
CTerm(rate, future, initial) | Periods required for a compounded initial investment |
Term(payment, rate, future) | Periods required for equal payments to reach the future value |
Apr(principal, monthlyPayment, periods) | Annual percentage rate found by a bounded monthly-rate solver |
NPV(rate, cashFlow1, ...) | Discounted end-of-period cash flows in argument order |
IPmt and PPmt | Interest or principal paid for (principal, annualRate, monthlyPayment, firstMonth, months); month indices start at 1 and 0 also selects the first month |
This corrects earlier spreadsheet-style argument ordering and sign handling: migrate Pmt(rate, periods, principal) to Pmt(principal, rate, periods) and expect a positive result; FV and PV now operate on periodic payments instead of a single initial or final amount
Rate now computes compound growth; NPer(rate, payment, future) remains a nonstandard extension equivalent to Term(payment, rate, future)
Invalid financial domains reject general events atomically; the native calculate evaluator reports a failed expression, and iteration consumes the configured operation and time budgets
General event library
The general FormCalc event compiler supports case-insensitive built-in names, leading decimal literals, Null, scientific trigonometric functions, Pi, degree/radian conversion, Stuff and Str; Count includes empty text and omits null values, and all-null aggregates return null
Mod preserves the dividend sign in both evaluation paths; Mod(-13, 3) returns -1
Typing
Numeric evaluation stays Double-typed: a formula whose head is a string function resolves textually, and finance results convert back into numeric expressions so Round(Pmt(...), 2) works; any type mismatch still degrades to a blank value
Conditional logic and repeated arrays
Comparisons, And, Or, Not, booleans, and lazy If(condition, whenTrue, whenFalse) expressions provide bounded conditional control flow
Sum, Avg, Min, Max, and Count accept repeated numeric selectors such as rows[*].amount, while their ordinary argument-list forms continue to aggregate scalar expressions
Dynamic instance requests
InstanceAdd(name, count) and InstanceRemove(name, index) invoke the validated instance callback configured by the caller and return the resulting instance count
See Bounded XFA FormCalc and JavaScript for the optional QuickJS path, typed arrays, runtime isolation, budgets, and telemetry
Explicit HTTP transport
General event scripts support case-insensitive Get, Post and Put through explicit application host transport; arguments are forwarded in order and the application supplies the response
These functions require EnableJavaScript and a configured HostTransport callback in the widget runtime; the native scalar evaluator does not perform network requests