К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как программно добавить элемент на управляемую форму 1С

Программное добавление элементов на управляемую форму 1С: свойство Элементы, методы Добавить и Изменить, примеры кода, типичные ошибки и проверка результата.

Управляемые формы в 1С:Предприятие 8.3 строятся декларативно, но платформа позволяет изменять их состав программно — прямо в модуле формы, в процессе её создания или уже после открытия. Это нужно, когда набор реквизитов заранее неизвестен: например, форма настройки отчёта с произвольным списком параметров, динамический опросник, панель с кнопками по данным таблицы значений.

Основной инструмент — свойство формы Элементы, через которое доступны методы Добавить(), Вставить(), Изменить(), Найти() и Удалить(). Вместе с коллекцией РеквизитыФормыВЗначение и методом ИзменитьРеквизиты() этого достаточно, чтобы построить на форме практически любой динамический интерфейс.

Ниже разобран рабочий порядок действий: от создания реквизита до вывода поля ввода и команды с обработчиком, а также ограничения, о которых часто забывают, и способы проверить, что элемент добавлен корректно.

Где и когда выполняется программное изменение формы

Управляемая форма существует в двух «мирах»: на сервере, где доступны данные и структура формы, и на клиенте, где работает только интерфейс. Добавление элементов — серверная операция. Правильные места для неё:

  • ПриСозданииНаСервере — основной сценарий. Форма ещё не показана пользователю, изменения дёшевы и предсказуемы.
  • Командная процедура с директивой &НаСервере — допустимо, но каждое изменение структуры вызывает пересоздание формы и перерисовку на клиенте.
  • ПриОткрытии на клиенте — не подходит: коллекция Элементы там доступна только на чтение для добавления.

Если элементы нужно добавлять по кнопке уже в открытой форме, вызовите серверную процедуру из клиентской команды. Учтите, что при этом теряются несохранённые данные, введённые в динамически созданные ранее поля, — их значения нужно сохранить в реквизиты формы до перестройки.

Создание реквизита формы перед добавлением элемента

Поле ввода, флажок или таблица должны отображать какие-то данные. Если подходящего реквизита нет, его создают методом ИзменитьРеквизиты(). Метод принимает два массива: добавляемые и удаляемые реквизиты — объекты типа ОписаниеРеквизитаФормы.

// Серверная процедура формы

ДобавляемыеРеквизиты = Новый Массив;

ОписаниеРеквизита = Новый ОписаниеРеквизитаФормы;

ОписаниеРеквизита.Имя = "ДинамическоеПоле";

ОписаниеРеквизита.ТипЗначения = Новый ОписаниеТипов("Строка", ,

Новый КвалификаторыСтроки(150));

ОписаниеРеквизита.Заголовок = "Дополнительный комментарий";

ДобавляемыеРеквизиты.Добавить(ОписаниеРеквизита);

ИзменитьРеквизиты(ДобавляемыеРеквизиты);

После вызова ИзменитьРеквизиты реквизит доступен в модуле формы по имени: ЭтаФорма.ДинамическоеПоле = "текст";. Повторное добавление реквизита с тем же именем вызовет ошибку, поэтому перед созданием проверяйте существование — например, перебором структуры формы через ПолучитьРеквизиты() или в попытке/исключении.

Добавление элемента: метод Элементы.Добавить

Когда реквизит готов (или элементу данные не нужны — как надписи), добавьте сам элемент. Синтаксис: Элементы.Добавить(ИмяЭлемента, ТипЭлемента, Родитель). Тип задаётся системным перечислением ТипЭлементаФормы, родитель — группа, страница или сама форма.

НовыйЭлемент = Элементы.Добавить("ПолеДинамическое",

Тип("ПолеФормы"), Элементы.ГруппаОсновная);

НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;

НовыйЭлемент.ПутьКДанным = "ДинамическоеПоле";

НовыйЭлемент.Заголовок = "Комментарий";

Ключевые моменты:

  • Имя элемента должно быть уникально в пределах формы и состоять из допустимых символов идентификатора.
  • Свойство ПутьКДанным связывает поле с реквизитом. Без него поле отрисуется, но вводить данные будет некуда.
  • Сначала задайте Вид, затем остальные свойства — часть свойств доступна только для конкретного вида поля.
  • Если родитель не указан, элемент попадёт в корень формы, что обычно не то, что нужно.

Для надписи всё проще — реквизит не требуется:

Надпись = Элементы.Добавить("НадписьПодсказка", Тип("ДекорацияФормы"),

Элементы.ГруппаОсновная);

Надпись.Вид = ВидДекорацииФормы.Надпись;

Надпись.Заголовок = "Заполните дополнительные сведения";

Порядок добавления поля ввода
  1. 1
    Откройте серверную процедуру формы, например ПриСозданииНаСервере
  2. 2
    Создайте реквизит через ОписаниеРеквизитаФормы и ИзменитьРеквизиты()
  3. 3
    Вызовите Элементы.Добавить() с типом ПолеФормы и укажите родителя
  4. 4
    Установите Вид, ПутьКДанным и Заголовок нового элемента
  5. 5
    Откройте форму в режиме 1С:Предприятие и проверьте отображение и ввод данных

Добавление групп, кнопок и команд

Чтобы динамические элементы не выстраивались в одну колонку, сначала создают контейнер — группу:

Группа = Элементы.Добавить("ГруппаДинамическая", Тип("ГруппаФормы"), ЭтаФорма);

Группа.Вид = ВидГруппыФормы.ОбычнаяГруппа;

Группа.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Горизонтальная;

Группа.ОтображатьЗаголовок = Ложь;

Кнопка требует двух сущностей: команды формы и самого элемента-кнопки. Команду добавляют в коллекцию Команды, обработчик указывают именем процедуры модуля формы:

// 1. Команда

НоваяКоманда = Команды.Добавить("КомандаОбновить");

НоваяКоманда.Действие = "Подключаемый_ОбновитьДанные";

НоваяКоманда.Заголовок = "Обновить";

// 2. Кнопка

Кнопка = Элементы.Добавить("КнопкаОбновить", Тип("КнопкаФормы"), Группа);

Кнопка.ИмяКоманды = "КомандаОбновить";

Процедура-обработчик должна существовать в модуле формы с клиентской директивой:

&НаКлиенте

Процедура Подключаемый_ОбновитьДанные(Команда)

ОбновитьДанныеНаСервере();

КонецПроцедуры

Если кнопок много и они однотипные (например, по строкам таблицы), используйте одну команду, а различайте кнопки по имени элемента — в обработчике оно доступно через ЭтаФорма.ТекущийЭлемент.Имя после установки, либо кодируйте ключ в имени команды и разбирайте его строковыми функциями.

bsl
НовыйЭлемент = Элементы.Добавить("Поле1", Тип("ПолеФормы"), Родитель);
НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
НовыйЭлемент.ПутьКДанным = "Реквизит1";

Динамическая таблица значений на форме

Частая задача — показать таблицу с заранее неизвестным набором колонок. Порядок такой: создаётся реквизит типа ТаблицаЗначений, затем для каждой колонки — отдельный реквизит с указанием пути ИмяТаблицы.ИмяКолонки, затем элемент таблицы и поля колонок.

Добавляемые = Новый Массив;

РеквизитТаблица = Новый ОписаниеРеквизитаФормы;

РеквизитТаблица.Имя = "ТаблицаДанных";

РеквизитТаблица.ТипЗначения = Новый ОписаниеТипов("ТаблицаЗначений");

Добавляемые.Добавить(РеквизитТаблица);

РеквизитКолонка = Новый ОписаниеРеквизитаФормы;

РеквизитКолонка.Имя = "Наименование";

РеквизитКолонка.ТипЗначения = Новый ОписаниеТипов("Строка");

РеквизитКолонка.Путь = "ТаблицаДанных";

Добавляемые.Добавить(РеквизитКолонка);

ИзменитьРеквизиты(Добавляемые);

ЭлементТаблица = Элементы.Добавить("ТаблицаДанных", Тип("ТаблицаФормы"), ЭтаФорма);

ЭлементТаблица.ПутьКДанным = "ТаблицаДанных";

Колонка = Элементы.Добавить("ТаблицаНаименование", Тип("ПолеФормы"), ЭлементТаблица);

Колонка.Вид = ВидПоляФормы.ПолеВвода;

Колонка.ПутьКДанным = "ТаблицаДанных.Наименование";

Заполняется такая таблица обычным присваиванием: ЗначениеВРеквизитФормы(МояТаблицаЗначений, "ТаблицаДанных"); — либо построчно через ЭтаФорма.ТаблицаДанных.Добавить().

Типичные ошибки
01
Добавление элемента до создания реквизита — ошибка «Реквизит не найден» при установке ПутьКДанным
02
Повторный вызов Добавить() с тем же именем — исключение о неуникальном имени; проверяйте Элементы.Найти()
03
Установка свойств до указания Вида поля — часть свойств недоступна, код падает
04
Попытка добавить элемент на клиенте — метод доступен только на сервере
05
Пересоздание элементов при каждом серверном вызове без сохранения введённых значений — данные пользователя теряются

Изменение и удаление существующих элементов

Не всегда нужно создавать элемент с нуля. Метод Элементы.Изменить(Имя) возвращает элемент для настройки, Элементы.Найти(Имя) — для проверки существования, Элементы.Удалить(Элемент) — для удаления. Типовой безопасный шаблон:

Если Элементы.Найти("ПолеДинамическое") = Неопределено Тогда

// создаём элемент

Иначе

Элементы.Изменить("ПолеДинамическое").Видимость = Истина;

КонецЕсли;

Удаление элемента не удаляет связанный реквизит — его убирают отдельно, тем же ИзменитьРеквизиты(), но с массивом удаляемых имён во втором параметре. Обратное тоже верно: удалённый реквизит «уронит» форму, если на него ещё ссылается элемент.

Контрольные точки

Как проверить результат

Элемент виден на форме
Норма

Поле отображается в нужной группе с заданным заголовком

Тревожный признак

Элемента нет — проверьте родителя и видимость родительских групп

Ввод данных
Норма

Введённое значение сохраняется в реквизите формы

Тревожный признак

Поле сбрасывается — не задан ПутьКДанным или реквизит пересоздаётся

Работа кнопки
Норма

Нажатие вызывает процедуру-обработчик

Тревожный признак

Ничего не происходит — проверьте ИмяКоманды и наличие процедуры в модуле

Повторное открытие формы
Норма

Нет ошибок о дублировании имён

Тревожный признак

Исключение — добавьте проверку Элементы.Найти()

Ограничения и альтернативы

Программное построение формы — мощный, но не бесплатный механизм. Каждое изменение структуры заставляет платформу пересоздавать форму, что при десятках элементов заметно сказывается на скорости открытия. Кроме того, динамические элементы не видны в конфигураторе, что усложняет поддержку: следующий разработчик не найдёт их в дереве элементов формы.

Прежде чем строить форму кодом, рассмотрите альтернативы:

  • Заранее созданные скрытые элементы. Если набор вариантов конечен, создайте все элементы в конфигураторе и управляйте только видимостью — это быстрее и понятнее.
  • Условное оформление и функциональные опции. Для показа/скрытия по условиям часто достаточно штатных механизмов без единой строки кода.
  • Динамический список или табличный документ. Для отображения произвольных данных иногда проще вывести табличный документ, чем конструировать таблицу формы.

Когда какой подход выбрать

Скрытые элементы + управление видимостью

Набор полей известен заранее. Просто, быстро, видно в конфигураторе

Программное добавление через Элементы.Добавить

Состав полей определяется данными в момент выполнения. Гибко, но требует аккуратности с реквизитами

Табличный документ / динамический список

Нужно только показать данные без интерактивного редактирования в полях формы

Часто задаваемые вопросы

Можно ли добавить элемент на форму из внешней обработки?

Да, если код выполняется в модуле формы самой обработки — механизм тот же: Элементы.Добавить() на сервере. Извне изменить чужую открытую форму нельзя: доступа к коллекции Элементы другой формы у внешнего кода нет.

Почему добавленный элемент не виден, хотя ошибок нет?

Чаще всего элемент попал не в того родителя — например, в корень формы под страницами, либо родительская группа скрыта или свёрнута. Проверьте свойство Родитель элемента и видимость всей цепочки групп до корня формы.

Как добавить элемент в конкретное место, а не в конец группы?

Используйте метод Элементы.Переместить(Элемент, Родитель, ПередЭлементом) после добавления — третий параметр задаёт соседний элемент, перед которым нужно разместить новый. Метода Вставить с индексом в управляемых формах нет.

Сохранятся ли динамические реквизиты при повторном открытии формы?

Нет. Реквизиты, созданные через ИзменитьРеквизиты(), живут только в текущем экземпляре формы. При закрытии они исчезают; если значения нужны позже, сохраняйте их в базу данных или в хранилище настроек самостоятельно.

Можно ли программно задать обработчик события поля, например ПриИзменении?

Да: свойству УстановитьДействие (в новых версиях) или через назначение имени процедуры соответствующему событию элемента. Процедура должна существовать в модуле формы с клиентской директивой и стандартной сигнатурой параметров.

Что делать, если элементов нужно добавить несколько десятков и форма «подвисает»?

Выполняйте все изменения одним серверным вызовом в ПриСозданииНаСервере, а не по кнопке, и создавайте реквизиты одним вызовом ИзменитьРеквизиты с полным массивом. Если данных много, рассмотрите вывод через табличный документ вместо отдельных полей.

Итог

Что важно запомнить

Динамический элемент создаётся на сервере: сначала реквизит через ИзменитьРеквизиты(), затем элемент через Элементы.Добавить() с указанием типа, родителя и ПутьКДанным. Проверяйте уникальность имён, задавайте Вид до остальных свойств и помните, что динамическая структура живёт только в текущем сеансе формы.