При создании первых внешних обработок и форм начинающие разработчики часто сталкиваются с ситуацией, когда добавленный реквизит «не виден» в коде, обработчики событий выдают синтаксические ошибки при попытке передать в них пользовательские данные, а вызов процедур расчета из других методов завершается сбоем. Разберем по шагам внутреннее устройство управляемых форм, правила передачи данных и алгоритмы вычислений.
Проанализируем структуру управляемой формы. На управляемой форме данные строго отделены от элементов их визуального отображения:
ПолеВвода), то на форме он доступен через основной реквизит формы — Объект (тип ДанныеФормыСтруктура). Обращение к нему на клиенте и сервере выглядит как Объект.ПолеВвода. Если реквизит был добавлен в объект конфигурации уже после создания формы, необходимо убедиться, что он присутствует в структуре реквизита Объект на вкладке «Реквизиты» формы.Реквизит1), обращение к ней выполняется напрямую по имени: Реквизит1.Элементы (например, Элементы.ПолеВвода). В управляемом интерфейсе элементы отвечают исключительно за отображение и свойства визуальных контролов (видимость, доступность), а не за хранение данных. Получать значение через элементы напрямую нельзя — обращаться нужно к связанному реквизиту данных.Рассмотрим распространенную ошибку, возникающую при попытке передать аргумент в платформенный обработчик команды или события. Платформа 1С жестко регламентирует список параметров для системных событий:
(Команда).ПриИзменении всегда принимает ровно один параметр: (Элемент).Попытка объявить обработчик с дополнительными переменными вида Процедура Рассчитать(Команда, Ввод) приводит к критической ошибке времени выполнения: платформа при нажатии кнопки или изменении поля передает только один системный параметр и не может вызвать процедуру с неподходящим количеством параметров.
Выясним, как правильно организовать вызов: для расчетов создается отдельная служебная процедура, в которую передаются нужные параметры, а обработчики событий лишь вызывают ее.
&НаКлиенте
Процедура ПолеВводаПриИзменении(Элемент)
// Из обработчика события передаем значение реквизита в отдельную процедуру
ВыполнитьРасчет(Объект.ПолеВвода);
КонецПроцедуры
&НаКлиенте
Процедура КомандаРассчитать(Команда)
// Из команды кнопки также вызываем общую расчетную процедуру
ВыполнитьРасчет(Объект.ПолеВвода);
КонецПроцедуры
&НаКлиенте
Процедура ВыполнитьРасчет(Знач СтрокаВыражения)
Если ПустаяСтрока(СтрокаВыражения) Тогда
Возврат;
КонецЕсли;
// Алгоритм обработки выражения
КонецПроцедуры
Разберем готовый компактный вариант вычисления строковых выражений с использованием функции глобального контекста Вычислить(). Данная функция принимает строку с математическим или логическим выражением и возвращает результат.
Посмотрим на пример безопасной реализации с перехватом ошибок через конструкцию Попытка ... Исключение и выводом сообщений пользователю:
&НаКлиенте
Процедура РассчитатьВыражение(Команда)
СтрокаВыражения = Объект.ПолеВвода;
Если ПустаяСтрока(СтрокаВыражения) Тогда
Возврат;
КонецЕсли;
Попытка
Результат = Вычислить(СтрокаВыражения);
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Результат: " + Строка(СтрокаВыражения) + " = " + Строка(Результат);
Сообщение.Поле = "Объект.ПолеВвода";
Сообщение.Сообщить();
Исключение
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Ошибка при вычислении выражения: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
Сообщение.Сообщить();
КонецПопытки;
КонецПроцедуры
Проанализируем технические нюансы работы метода Вычислить():
Вычислить() выполняет любую синтаксически корректную конструкцию встроенного языка 1С. Если пользователь введет вызов системной функции, платформа выполнит ее с текущими правами сеанса. В реальных продуктивных решениях не рекомендуется применять Вычислить() для непроверенных пользовательских строк.Вычислить() могут блокироваться платформой.ТабличныйДокумент, куда формула подставляется со знаком равенства в ячейку.Чтобы избежать путаницы в передаче параметров между процедурами, придерживаемся следующих правил:
Объект.Перем ИмяПеременной; в самом начале модуля формы вне процедур с директивой &НаКлиенте.