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