Контроль выполнения: условия, функции и обработка ошибок#

В этом разделе описаны основные конструкции управления выполнением кода в JEXL: условные операторы, циклы, методы и функции, обработка ошибок. Материал содержит синтаксис и практические примеры для каждого элемента.

Условные конструкции и циклы#

Условия if-else#

Синтаксис:

if (условие) {
    // блок кода при true
} else {
    // блок кода при false
}

Пример:

if (order.total > 10000) {
    discount = 0.1;
} else if (order.total > 5000) {
    discount = 0.05;
} else {
    discount = 0;
}

Тернарный оператор#

Синтаксис:

условие ? значение_если_true : значение_если_false

Пример:

// Простой пример
var access = (id >= 18) ? "Разрешено" : "Запрещено";

Циклы#

While#

Синтаксис:

while (условие) {
    // действие
}

Пример:

// Простой пример
var i = 0;
while (i < 10) {
    total++;
    i++;
}

For#

При использовании циклов важно понимать область видимости переменных:

  • Если итерируемая переменная объявлена с let или const - она доступна только внутри блока цикла.

  • Если переменная объявлена без ключевого слова (неявно) - она ведёт себя как var:

    • Доступна после выполнения цикла.

    • Сохраняет последнее присвоенное значение.

    • Если переменная с таким именем уже существовала, то переменная созданная в цикле затрет значение ранее объявленной переменной.

Способ 1:
Классический C-подобный цикл с индексом.

Синтаксис:

for (инициализация; условие; шаг) {
    // тело цикла
}

Пример:

let x = 0;
for (let i = 0; i < 10; ++i) {
    x += i
}
dialogs.showMessage(toString(x));

Подходит также для массивоподобных структур, где есть доступ по индексу (array[i]).

let x = 0;
let array = [100, 200, 300];
for (let i = 0; i < size(array); ++i) {
    x += array[i];
}

Позволяет гибко управлять индексом коллекции (например, менять шаг i += 2).

Способ 2:

Синтаксис:

for (let элемент : коллекция) {
    // тело цикла
    // элемент доступен только здесь
}

Используется для перебора элементов итерируемой структуры (массива, коллекции и т. д.). Итерируемая переменная получает значение каждого элемента на каждой итерации.

let x = 0;
let array = [1, 2, 3];
for (let item : array) {
    x += item;
}

Переменная item доступна только внутри цикла (если используется let).

Способ 3:

Синтаксис:

for (элемент : коллекция) {
    // тело цикла
    // элемент доступен здесь
}
// элемент ДОСТУПЕН и здесь (ведёт себя как var)

Если итерируемую переменную не объявлять никаким ключевым словом(let, const, var), то она будет объявлена как var, и будет иметь последнее присвоенное значение.

Пример коллекции:

let x = 0;
let array = [1, 2, 3];
for (item : array) {
    x += item;
}
dialogs.showMessage(toString(item)); // Будет выведено значение '3'
  • item не объявляется явно — она создаётся неявно и «живёт» после цикла.

  • Может привести к неожиданным эффектам, если item уже была определена ранее.

  • Обход результатов объектного запроса с преобразованием в список.

    var l= toJRops(Btk_SomeEntityApi.byParent(rop)).asList()
    for(r:l){
        logInfo(r.id);
        logInfo(r.sSystemName)
    }
    

Пример множества:

var mvStock = {"P-1001", "P-1002", "P-1003"};
for(item : mvStock) {
    dialogs.showMessage(item);
}

Пример карты:

var mvStock = {"P-1001" : 1, "P-1002" : 2, "P-1003" : 3};
for(item : mvStock) {
    dialogs.showMessage(item); // Здесь item это значения словаря по ключу
}

Foreach#

Синтаксис:

коллекция.foreach(элемент -> {
    // действия с элементом
});

В JEXL оператор foreach используется исключительно для функционального подхода, когда данные поступают в виде потока (например, из SQL-запроса или коллекции).

Ключевые особенности:

  • потоковая обработка;

  • нет возвращаемого значения.

Пример:

sql("SELECT name FROM users").foreach(row -> {
    logInfo("User: " + row.name);
});

Вызов методов и функций в JEXL#

Базовый вызов методов#

Синтаксис:

объект.метод(параметры)

Пример:

dialogs.showMessage(ropvInvoice);
dialogs.showMessage(toString(ropvInvoice.nsum));

Поддерживается цепочка вызовов:

sheet.getRow(0).getCell(1)

Определение пользовательской функции#

Синтаксис:

function имяФункции(параметры) {
    // тело функции
    результат; // опционально
}

Пример:

function calculateSum(a, b) {
    // Тело функции
    a + b; // Возвращаемый результат (неявный return)
}

dialogs.showMessage(toString(calculateSum(2, 3)));

Объявление локальных функций#

Синтаксис:

var fun_LoadInvoiceTemplate = function(x) {
    // Тело функции
    return true;
};

Пример:

function test(params) {
    dialogs.showMessage("hello world");
}

const FX_DeleteInvisibleSymbolsF = function(sText) {
    var querry = sql(`Select regexp_replace('${sText}', '[\\s\\u200B\\u200C\\u200D\\uFEFF]', '', 'g') as ShortText;`).asSingle();
    return querry.shorttext;
}

//--------------------------------------------------------------------------
//main code block
//--------------------------------------------------------------------------
{
    var sCaptionLong = 'А 694 ЕМ 147_2024 12 105'
    var sCaptionFunc = FX_DeleteInvisibleSymbolsF(sCaptionLong);
    dialogs.showMessage('FUNC: '+ sCaptionFunc);
}

const FX_DeleteInvisibleSymbolsF = function(sText) {
    var querry = sql(`
        SELECT regexp_replace('${sText}', '[\\s\\u200B\\u200C\\u200D\\uFEFF]', '', 'g') AS ShortText;
    `).asSingle();
    return querry.shorttext;
}

//--------------------------------------------------------------------------
// Main code block
//--------------------------------------------------------------------------
{
    var sCaptionLong = 'А 694 ЕМ 147_2024 12 105';
    var sCaptionFunc = FX_DeleteInvisibleSymbolsF(sCaptionLong);
    dialogs.showMessage('FUNC: ' + sCaptionFunc);
}

Обработка ошибок#

Jexl в ядре не поддерживает исключения, механизм исключений реализован через аннотации.

Синтаксис:

@begin{
    //code
}@exception function(e){
    // code
}

Для бросания исключения можно воспользоваться командой raise: raise("Текст исключения");

Пример:

const ErrorHandler = new java.util.concurrent.atomic.AtomicReference(null); // Объявим обработчик ошибок

... // Произвольный блок кода

var svLogList = ''; // Переменная для лога успешности и ошибок
ErrorHandler.set(null); // Сбросим обработчик ошибок перед попыткой поймать ошибку

@begin { // Блок кода, в котором попытаемся поймать ошибку
    ... // Произвольный блок кода
    raise("Текст ошибки"); // Событие, которое вызывает ошибку
}
@exception function(vEx1) { // Обработка исключения
    ErrorHandler.set(vEx1); // Сохраняем ошибку в наш обработчик
}; // Обязательно ставим точку с запятой

const ErrorCatch = ErrorHandler.get(); // Запросим значение из обработчика

if (isNotNull(ErrorCatch)) { // Проверяем, была ли ошибка
    svLogList += `\r\n - Ошибка! ${ErrorCatch.getCause().getMessage()}`;
} else {
    svLogList += `\r\n - Успешно!`;
}

dialogs.showMessage(svLogList); // Отображение логов на экране