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