Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.abbyy.com/llms.txt

Use this file to discover all available pages before exploring further.

The following JavaScript samples illustrate common patterns for Advanced Script Rules — checking field presence, comparing numeric values, applying conditional validation, and validating table data. Copy and adapt them to your own field names and business rules.

Check that a field is present

For example, check that the MyField field is found and filled in:
var field = Context.GetField("MyField");

if (!field) {
  Context.CheckSucceeded = false;
  Context.ErrorMessage = 'MyField field not found';
} else if (!field.Value) {
  Context.CheckSucceeded = false;
  Context.ErrorMessage = 'MyField field empty';
}

Compare floating-point numbers

Comparing floating-point numbers directly can yield unpredictable results. Use methods from the built-in Math object to compare numbers — especially money values — reliably.
// compare two floating-point numbers
var floatField1 = Context.GetField("Number Field 1");
var floatField2 = Context.GetField("Number Field 2");
var floatVal1 = floatField1.Value;
var floatVal2 = floatField2.Value;

if (Math.round(floatVal1) === Math.round(floatVal2)) {
    return;
} else {
    Context.CheckSucceeded = false;
    Context.ErrorMessage = 'The values are different';
}

// compare two money values
var moneyField1 = Context.GetField("Money Field 1");
var moneyField2 = Context.GetField("Money Field 2");
var value1 = moneyField1.Value.Amount;
var value2 = moneyField2.Value.Amount;

if (Math.abs(value1 - value2) <= 0.0001) {
    return;
} else {
    Context.CheckSucceeded = false;
    Context.ErrorMessage = 'The values are different';
}

Require a non-empty value depending on another field

An optional field can become required based on another field’s value. For example, if MaritalStatus is Married, the spouse name fields should be filled in. This script rule verifies that when MaritalStatus is Married, both SpouseFirstName and SpouseLastName are filled in:
function checkFieldValuePresence(field) {
    if (!field.Value) {
        Context.ErrorMessage = 'Value of ' + field.Name + ' field should not be empty';
        return false;
    }
    return true;
}

var conditionField = Context.GetField("MaritalStatus");

if (conditionField === null) {
    Context.CheckSucceeded = false;
    Context.ErrorMessage = 'MaritalStatus field not found';
} else if (checkFieldValuePresence(conditionField)) {
    var lastName = Context.GetField("SpouseLastName");
    var firstName = Context.GetField("SpouseFirstName");
    if (conditionField.Text === "Married") {
        if (lastName === null || firstName === null) {
            Context.CheckSucceeded = false;
            Context.ErrorMessage = 'Spouse name field not found';
        } else if (!checkFieldValuePresence(lastName) || !checkFieldValuePresence(firstName)) {
            Context.CheckSucceeded = false;
        }
    }
} else { // marital status not filled in, check failed
    Context.CheckSucceeded = false;
}

Check that a field is located on the document

Rules can also fill in field values, even if the value isn’t printed on the document. For example, if several taxes apply, the total tax can be calculated automatically. However, some countries require the total tax amount to be printed on the document. This script rule checks that for receipts from Germany the total tax is present on the image. For other countries, no additional check is needed because the Required field flag is turned on for the total tax field:
function checkFieldRegion(field) {
    if (!field || !field.HasRegion) {
        Context.ErrorMessage = 'The (' + field.Name + ') field is not present on the document image';
        return false;
    }
    return true;
}

var conditionField = Context.GetField("CountryOfOrigin");

if (!conditionField.Value) {
    Context.ErrorMessage = 'Country of origin unknown, cannot check taxes';
    Context.CheckSucceeded = false;
} else {
    var totalTaxField = Context.GetField("TotalTax");
    if (conditionField.Text === "DE" && !checkFieldRegion(totalTaxField)) {
        Context.CheckSucceeded = false;
    }
}

Validate the data in particular cases

Checking that the total tax equals the sum of all taxes can be done with a predefined rule (Check Sum). But if one of the taxes can have a negative value in certain countries, only a script rule can handle both cases — adding all taxes, or adding and subtracting a return tax, depending on the country of origin. This script checks that the sum of two taxes equals the total tax, except for receipts from Spain, where either the sum or the difference of the two can equal the total tax:
var conditionField = Context.GetField("CountryOfOrigin");
var totalTaxField = Context.GetField("TotalTax");
var tax1Field = Context.GetField("Tax1");
var tax2Field = Context.GetField("Tax2");

if (!conditionField.Value || !totalTaxField.Value || !tax1Field.Value || !tax2Field.Value) {
    Context.ErrorMessage = 'Cannot check taxes';
    Context.CheckSucceeded = false;
} else {
    if (conditionField.Text === "ES") {
        Context.CheckSucceeded = ((Math.round(tax1Field.Value - tax2Field.Value) === Math.round(totalTaxField.Value))
            || (Math.round(tax1Field.Value + tax2Field.Value) === Math.round(totalTaxField.Value)));
    } else {
        Context.CheckSucceeded = (Math.round(tax1Field.Value + tax2Field.Value) === Math.round(totalTaxField.Value));
    }
}

Compare a column sum to an external field

Scripts can reference table values, not just regular fields. To speed up rule checks, save tables as variables and reference the variables instead of re-fetching the table. If a variable holds an entire table, use the Instances property to access rows, then use GetChild to get a specific cell in a row. The sample below sums all values in the Total Price column and compares the result to the Total field:
var totalField = Context.GetField("Total");
var tableField = Context.GetField("MyTable");

if (!totalField) {
    Context.CheckSucceeded = false;
    Context.ErrorMessage = "Total field is not found";
    return;
}

if (!tableField) {
    Context.CheckSucceeded = false;
    Context.ErrorMessage = "MyTable field is not found";
    return;
}

var sum = 0;

for (var i = 0; i < tableField.Instances.length; i++) {
    var tableTotalField = tableField.Instances[i].GetChild("MyTable/Total Price");
    sum += tableTotalField.Value.Amount;
}

if (Math.abs(sum - totalField.Value.Amount) > 0.02) {
    Context.CheckSucceeded = false;
    Context.ErrorMessage = "The sum of Total Price in the table doesn't match Total";
}

Compare column cells to an external field and list failing rows

Reference table columns with Context.GetFields to get every cell in the column, which is useful for looping. The sample below compares each row’s tax rate to the overall tax rate. When values don’t match, the script continues instead of failing immediately, collecting the row numbers with mismatches and reporting them in the error message:
var taxRateFields = Context.GetFields("MyTable/TaxRate");
var taxRateField = Context.GetField("TaxRate");

if (!taxRateFields || !taxRateField)
    return;

var taxRate = taxRateField.Value ? taxRateField.Value : 0;
var wrongLines = [];
for (var i = 0; i < taxRateFields.length; i++) {
    if (taxRateFields[i].Value != taxRate)
        wrongLines.push(i + 1);
}

if (wrongLines.length > 0) {
    Context.CheckSucceeded = false;
    Context.ErrorMessage = "Wrong tax rate in lines: " + wrongLines.join(", ");
}

Compare the product of row values to another row value

You can perform operations on different columns in a table row-by-row without using explicit loops — reference each column using Context.GetField. This creates a repeating rule that runs automatically for each row. All columns referenced this way must belong to the same table. The sample below multiplies unit quantity by unit price for each row and compares the result to the line item’s total price:
var quantityField = Context.GetField("MyTable/Quantity");
var unitPriceField = Context.GetField("MyTable/Unit Price");
var totalField = Context.GetField("MyTable/Total Price");

if (!quantityField || !unitPriceField || !totalField)
    return;

var quantity = quantityField.Value ? quantityField.Value : 0;
var unitPrice = unitPriceField.Value?.Amount ? unitPriceField.Value.Amount : 0;
var total = totalField.Value?.Amount ? totalField.Value.Amount : 0;

var result = quantity * unitPrice;

if (Math.abs(result - total) > 0.01) {
    Context.CheckSucceeded = false;
    Context.ErrorMessage = "Quantity * Unit price is not equal to Total";
}

Business rules automation

Add scripted rules to a Document skill, configure readable and writable fields, and reference table columns.

Object model

Full JavaScript object reference for use in Advanced Script Rules.

Context

The Context global object — access the document, fields, and skill parameters from inside a rule.

Field

The Field object — inspect and modify a document field during rule execution.