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

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

Как программно вывести реквизит на форму в 1С

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

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

Важно понимать разделение ответственности: реквизит формы — это данные, элемент формы — это их представление. Можно добавить реквизит без элемента (данные будут, но пользователь их не увидит), но нельзя создать элемент без пути к данным — форма выдаст ошибку при открытии.

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

Как устроены данные и элементы управляемой формы

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

Из-за этого разделения программный вывод реквизита всегда состоит из двух независимых операций. Пропуск любой из них приводит к предсказуемому результату: либо данные есть, но их не видно, либо форма падает с ошибкой «Поле не найдено» при попытке привязать элемент к несуществующему пути.

Ещё одна особенность — контекст выполнения. Метод ИзменитьРеквизиты() доступен только на сервере, поэтому весь код по добавлению реквизитов пишется в директиве &НаСервере, чаще всего в обработчике ПриСозданииНаСервере. Элементы формы также добавляются серверным кодом, хотя сама коллекция Элементы доступна и на клиенте для чтения и изменения свойств.

Шаг 1: добавление реквизита формы методом ИзменитьРеквизиты

Метод ИзменитьРеквизиты(ДобавляемыеРеквизиты, УдаляемыеРеквизиты) принимает два массива объектов типа РеквизитФормы. Каждый объект создаётся конструктором Новый РеквизитФормы(Имя, ОписаниеТипов, Путь, Заголовок, СохраняемыеДанные).

Типовой код добавления строкового реквизита выглядит так:

&НаСервере

Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

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

ОписаниеТипа = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(150));

НовыйРеквизит = Новый РеквизитФормы(

"КомментарийДинамический", // имя реквизита

ОписаниеТипа, // тип значения

"", // путь (пусто — реквизит верхнего уровня)

"Комментарий", // заголовок для пользователя

Ложь); // не сохранять между сеансами

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

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

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

Параметр «Путь» нужен при добавлении реквизита внутрь существующего реквизита-объекта или таблицы. Например, чтобы добавить колонку в реквизит типа «ТаблицаЗначений» с именем ТоварыТаблица, в параметре «Путь» указывается "ТоварыТаблица", а в имени — только имя новой колонки.

Параметр «Сохраняемые данные» определяет, будет ли значение реквизита сохраняться при сохранении настроек формы. Для динамических полей, которые заполняются при каждом открытии, обычно передают Ложь.

Шаг 2: создание элемента формы и привязка к данным

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

&НаСервере

Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

// ... добавление реквизита через ИзменитьРеквизиты ...

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

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

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

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

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

Третий параметр метода Добавить — родительский элемент. Если его не указать, поле попадёт в корень формы. На практике удобнее заранее создать в конфигураторе пустую группу-контейнер (например, «ГруппаДополнительно») и добавлять динамические поля внутрь неё — так сохраняется контроль над расположением.

Свойство ПутьКДанным должно точно совпадать с именем реквизита, включая регистр не имеет значения, но ошибка в одной букве приведёт к исключению. После привязки значение реквизита и содержимое поля синхронизируются автоматически: изменение в коде через ЭтаФорма.КомментарийДинамический = "текст" сразу отобразится в поле.

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

Вывод реквизита объекта: когда ничего добавлять не нужно

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

Достаточно создать элемент и привязать его к пути через объект: НовыйЭлемент.ПутьКДанным = "Объект.Комментарий". Платформа сама подхватит значение из данных объекта, а при записи формы оно сохранится в базу.

Этот же приём работает для табличных частей: чтобы программно добавить колонку в таблицу формы, связанную с табличной частью объекта, создаётся элемент с Родитель, указывающим на таблицу формы, и путём вида "Объект.Товары.Цена".

Сравнение вариантов

Привязка к Объект.ИмяРеквизита

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

Новый реквизит формы через ИзменитьРеквизиты

Подходит для вычисляемых и временных полей, которых нет в метаданных. Значение живёт только в данных формы, сохранять его нужно вручную.

Декорация с надписью

Подходит для вывода значения только на просмотр. Используется элемент типа ДекорацияФормы со свойством Заголовок, реквизит можно не создавать.

Динамический набор полей: дополнительные реквизиты и свойства

Наиболее востребованный сценарий программного вывода — отрисовка дополнительных реквизитов и сведений (механизм БСП) или произвольного набора свойств, описанного в настройках. Здесь набор полей неизвестен на момент разработки формы, поэтому весь цикл «реквизит + элемент» выполняется в цикле по выборке настроек.

Ключевые правила для такого цикла: имена реквизитов и элементов должны быть уникальными — удобно формировать их по шаблону "ДопРеквизит_" + Строка(Свойство.УникальныйИдентификатор()), заменяя дефисы. Все реквизиты собираются в один массив и добавляются одним вызовом ИзменитьРеквизиты, а элементы создаются уже после него.

&НаСервере

Процедура СоздатьДинамическиеПоля()

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

СоответствиеИмен = Новый Соответствие;

Для Каждого СтрокаСвойства Из ТаблицаСвойств Цикл

ИмяРеквизита = "ДопРеквизит_" + СтрЗаменить(СтрокаСвойства.Ид, "-", "_");

Реквизит = Новый РеквизитФормы(ИмяРеквизита, СтрокаСвойства.ТипЗначения, "", СтрокаСвойства.Наименование, Ложь);

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

СоответствиеИмен.Вставить(ИмяРеквизита, СтрокаСвойства.Наименование);

КонецЦикла;

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

Для Каждого КлючЗначение Из СоответствиеИмен Цикл

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

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

Элемент.ПутьКДанным = КлючЗначение.Ключ;

КонецЦикла;

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

Обратите внимание: тип значения для дополнительных свойств берётся из самих настроек (обычно там хранится ОписаниеТипов). Если тип составной, платформа сама покажет кнопку выбора типа в поле ввода.

Если форма может открываться повторно в том же сеансе, перед добавлением проверяйте, существует ли реквизит — например, попыткой найти элемент с тем же именем. Повторный вызов ИзменитьРеквизиты с уже существующим именем вызовет ошибку.
ПЗ
Практическое замечание

Ограничения, тонкие места и типичные ошибки

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

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

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

Типичные ошибки
01
Создание элемента до вызова ИзменитьРеквизиты — ошибка «Поле не найдено», так как путь к данным ещё не существует
02
Вызов ИзменитьРеквизиты в цикле по одному реквизиту — многократное перестроение формы и заметное замедление открытия
03
Имя реквизита с дефисами или пробелами из GUID или наименования — исключение при создании
04
Ожидание, что значение динамического реквизита сохранится в базу само — оно живёт только в форме, сохранение нужно программировать отдельно
05
Привязка ПутьКДанным с опечаткой — форма не открывается, ошибка видна только в режиме предприятия

Проверка результата и отладка

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

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

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

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

Открытие формы
Норма

Форма открывается без сообщений об ошибках

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

Ошибка «Поле не найдено» или «Реквизит уже существует» при открытии

Привязка данных
Норма

Присвоение значения реквизиту в коде сразу отображается в поле

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

Поле пустое или не реагирует на изменение реквизита

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

Второе и третье открытие формы работают так же, как первое

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

При повторном открытии ошибка дублирования реквизита

Расположение
Норма

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

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

Поле попало в корень формы или за пределы видимой области

Если поле создано, но не видно, проверьте свойства Видимость у самого элемента и у всех родительских групп, а также не перекрыто ли оно другими элементами при горизонтальной группировке. В управляемых формах платформа сама рассчитывает компоновку, и неочевидные настройки группировки — частая причина «пропавших» полей.

Итог

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

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

Частые вопросы

Можно ли вывести реквизит на форму без изменения конфигурации?

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

Как вывести реквизит только для чтения?

Создайте элемент с видом ВидПоляФормы.ПолеНадписи — данные будут отображаться без возможности редактирования. Альтернатива — оставить ПолеВвода, но установить свойство ТолькоПросмотр = Истина у элемента.

Как удалить программно добавленный реквизит?

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

Почему поле не появляется, хотя код выполняется без ошибок?

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

Работает ли этот способ в обычных формах?

Нет, метод ИзменитьРеквизиты существует только в управляемых формах. В обычных формах элементы добавляются через коллекцию ЭлементыФормы с привязкой к данным объекта напрямую, а состав реквизитов формы динамически не меняется.

Как сохранить значение динамического реквизита в базу?

Автоматически оно не сохраняется — реквизит существует только в данных формы. В обработчике записи объекта (например, ПередЗаписьюНаСервере или ПриЗаписиНаСервере) значение нужно перенести в реквизит объекта, дополнительное сведение, регистр или другое хранилище, предусмотренное архитектурой решения.