跳转到主要内容

检查某个 field 是否存在

例如,让我们检查是否已找到并填写了 MyField field:
var field = Context.GetField("MyField");

if (!field) {
  Context.CheckSucceeded = false;
  Context.ErrorMessage = '未找到 MyField 字段';
} else if (!field.Value) {
  Context.CheckSucceeded = false;
  Context.ErrorMessage = 'MyField 字段为空';
}

比较浮点数

直接比较浮点数可能产生不可预测的结果。建议使用内置的 Math 对象提供的方法来正确比较数值,尤其是货币金额。
// 比较两个浮点数
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 = '数值不同';
}

// 比较两个货币值
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 = '数值不同';
}

根据另一个 field 的值要求非空

一个可选的 field 可能会因另一个 field 的取值而变为必填。例如,如果婚姻状况为“已婚”,则应填写配偶姓名。或者,如果根据出生日期计算该人的年龄未满法定年龄,则需要监护人签名。 此脚本规则会验证:对于婚姻状况 field 值为“Married”的文档,配偶的名和姓均已填写:
function checkFieldValuePresence(field) {
    if (!field.Value) {
        Context.ErrorMessage = field.Name + ' 字段的值不能为空';
        return false;
    }
    return true;
}

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

if (conditionField === null) {
    Context.CheckSucceeded = false;
    Context.ErrorMessage = '未找到 MaritalStatus 字段';
} 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 = '未找到配偶姓名字段';
        } else if (!checkFieldValuePresence(lastName) || !checkFieldValuePresence(firstName)) {
            Context.CheckSucceeded = false;
        }
    }
} else { // 婚姻状况未填写,检查失败
    Context.CheckSucceeded = false;
}

检查是否已在文档上定位该字段

这些规则可用于填充字段值,即使该值并未实际印在文档上。例如,如果适用多种税种,可以自动计算总税额。然而,一些国家要求在文档上打印总税金金额。 此脚本规则用于检查:对于德国的收据,总税额不仅需计算,还必须在图像上可见。对于其他国家,无需额外检查,因为总税字段已启用必填字段标志:
function checkFieldRegion(field) {
    if (!field || !field.HasRegion) {
        Context.ErrorMessage = '(' + field.Name + ') 字段在文档图像中不存在';
        return false;
    }
    return true;
}

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

if (!conditionField.Value) {
    Context.ErrorMessage = '原产国未知,无法检查税费';
    Context.CheckSucceeded = false;
} else {
    var totalTaxField = Context.GetField("TotalTax");
    if (conditionField.Text === "DE" && !checkFieldRegion(totalTaxField)) {
        Context.CheckSucceeded = false;
    }
}

在特定情况下验证数据

可以使用预定义规则(Check Sum)来检查总税额是否等于所有税项之和。但如果在某些国家/地区,某项税可能为负值,则只能通过脚本规则同时覆盖这两种情况。根据文档来源国家/地区的不同,规则要么将所有税额相加,要么在存在退税为负值时进行加总并相应抵扣。 以下示例脚本用于检查两项税之和是否等于总税额;但如果收据来自西班牙,则两项税的和或差任一者均可等于总税额:
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 = '无法验证税额';
    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));
    }
}

将表格列的合计与表格外的值进行比较

脚本不仅可以引用常规字段,还可以引用表格内的值。为加快规则校验,建议将表格保存为变量,然后引用这些变量而非原始表格。如果变量包含整个表格,您可以使用 Instances 属性访问表格的各行,再使用 Field GetChild 方法获取某一行中特定单元格的值。 下面的示例脚本将汇总 “Total Price” 列中的所有值,并将结果与 “Total” 字段的值进行比较:
var totalField = Context.GetField("Total");
var tableField = Context.GetField("MyTable");

if (!totalField) {
    Context.CheckSucceeded = false;
    Context.ErrorMessage = "未找到总计字段";
    return;
}

if (!tableField) {
    Context.CheckSucceeded = false;
    Context.ErrorMessage = "未找到 MyTable 字段";
    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 = "表格中总价的总和与总计不匹配";
}

将列中的各个单元格数值与表格外的数值进行比较,并显示包含错误的行号

也可以使用 Field GetFields 方法引用表格列。该方法可获取表格中所有单元格的列表,有助于设置循环。 下面的示例脚本将每个明细行的税率与总体税率进行比较。如果数值不匹配,脚本不会中断;相反,出现不匹配的行号会传递给一个特殊变量,规则可用它检查整列。示例脚本中的错误消息将列出所有包含错误的行号:
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 = "以下行的税率错误: " + wrongLines.join(", ");
}

将同一行中多个字段的乘积与同一行中另一个字段的值进行比较

您可以在不使用循环的情况下,按顺序(逐行)对表格中的不同列执行各种操作。为此,您需要使用 Field GetField 方法来引用每一列。该规则将作为重复规则,自动应用于表格的每一行。以这种方式引用的所有列必须来自同一张表。 下面的示例脚本将每行的单位数量与单价相乘,并将结果与该行项目的总价进行比较:
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 = "数量 * 单价不等于总价";
}