Контроль выполнения: условия, функции и обработка ошибок#
В этом разделе описаны основные конструкции управления выполнением кода в 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); // Отображение логов на экране