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

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

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

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

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

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

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

Как устроен механизм динамических реквизитов формы

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

Метод ИзменитьРеквизиты(ДобавляемыеРеквизиты, УдаляемыеРеквизиты) принимает два массива объектов типа ОписаниеРеквизитаФормы. Первый массив содержит реквизиты для добавления, второй — для удаления. Оба параметра необязательны, но обычно используется только добавление. После вызова метода реквизит появляется в коллекции ЭтаФорма и доступен по имени как свойство формы.

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

Пошаговое добавление простого реквизита

Базовый сценарий — добавление строкового или числового реквизита и вывод его на форму полем ввода. Весь код размещается в модуле формы в директиве &НаСервере.

&НаСервере

Процедура ДобавитьРеквизитНаСервере()

// 1. Описываем тип будущего реквизита

МассивТипов = Новый Массив;

МассивТипов.Добавить(Тип("Строка"));

ОписаниеТипа = Новый ОписаниеТипов(МассивТипов, ,

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

// 2. Формируем описание реквизита

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

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

"ДополнительныйКомментарий", ОписаниеТипа, "",

"Дополнительный комментарий", Ложь);

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

// 3. Изменяем состав реквизитов формы

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

// 4. Создаём элемент формы и привязываем к реквизиту

НовыйЭлемент = Элементы.Добавить("ПолеКомментария",

Тип("ПолеФормы"), Элементы.ГруппаДополнительно);

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

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

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

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

Обратите внимание на третий параметр конструктора ОписаниеРеквизитаФормы — путь к владельцу. Для реквизита верхнего уровня он пустой. Если реквизит должен стать колонкой динамической таблицы, здесь указывается имя реквизита-таблицы.

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

Добавление таблицы значений с колонками

Часто нужно добавить не одиночное поле, а целую таблицу с динамическим набором колонок. Для этого сначала описывается реквизит типа ТаблицаЗначений, затем каждая колонка добавляется отдельным описанием с указанием пути к таблице.

&НаСервере

Процедура ДобавитьТаблицуНаСервере()

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

// Сама таблица

Добавляемые.Добавить(Новый ОписаниеРеквизитаФормы(

"ДанныеЗагрузки", Новый ОписаниеТипов("ТаблицаЗначений")));

// Колонки таблицы — путь указывает на таблицу-владельца

Добавляемые.Добавить(Новый ОписаниеРеквизитаФормы(

"Номенклатура",

Новый ОписаниеТипов("СправочникСсылка.Номенклатура"),

"ДанныеЗагрузки", "Номенклатура"));

Добавляемые.Добавить(Новый ОписаниеРеквизитаФормы(

"Количество",

Новый ОписаниеТипов("Число", ,

Новый КвалификаторыЧисла(15, 3)),

"ДанныеЗагрузки", "Количество"));

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

// Элемент-таблица и колонки

ТаблицаЭлемент = Элементы.Добавить("ДанныеЗагрузки",

Тип("ТаблицаФормы"), Элементы.ГруппаДанные);

ТаблицаЭлемент.ПутьКДанным = "ДанныеЗагрузки";

КолонкаНом = Элементы.Добавить("ДанныеЗагрузкиНоменклатура",

Тип("ПолеФормы"), ТаблицаЭлемент);

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

КолонкаНом.ПутьКДанным = "ДанныеЗагрузки.Номенклатура";

КолонкаКол = Элементы.Добавить("ДанныеЗагрузкиКоличество",

Тип("ПолеФормы"), ТаблицаЭлемент);

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

КолонкаКол.ПутьКДанным = "ДанныеЗагрузки.Количество";

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

Заполнение такой таблицы выполняется обычным образом: ЭтаФорма.ДанныеЗагрузки.Добавить() или загрузка готовой таблицы значений через ЗначениеВРеквизитФормы — если данные готовятся вне контекста формы, например в менеджере объекта или общем модуле.

Удаление и повторное создание реквизитов

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

&НаСервере

Процедура ПересоздатьРеквизиты()

// Удаляем элементы, затем реквизиты

Если Элементы.Найти("ПолеКомментария") <> Неопределено Тогда

Элементы.Удалить(Элементы.ПолеКомментария);

КонецЕсли;

Удаляемые = Новый Массив;

Удаляемые.Добавить("ДополнительныйКомментарий");

ИзменитьРеквизиты(, Удаляемые);

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

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

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

Где размещать код и какие есть ограничения

Оптимальное место для добавления реквизитов — обработчик ПриСозданииНаСервере: форма строится один раз, реквизиты доступны сразу после открытия. Если состав полей зависит от действий пользователя, выносите логику в отдельную серверную процедуру и вызывайте её из клиентских обработчиков через серверный вызов.

У механизма есть принципиальные ограничения. Нельзя программно добавить реквизит к основному реквизиту формы (например, к объекту документа) — состав его полей определяется метаданными. Динамические реквизиты не участвуют в стандартном механизме сохранения данных формы и не попадают в данные объекта. Типы реквизитов ограничены допустимыми для формы: нельзя создать реквизит типа, например, ДокументОбъект — только ссылочные и примитивные типы, таблицы значений, деревья и некоторые другие.

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

Как проверить, что реквизит добавлен корректно

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

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

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

Отображение элемента
Норма

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

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

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

Связь с данными
Норма

Ввод в поле доступен, значение читается из реквизита формы

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

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

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

Форма открывается без исключений при повторном вызове

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

Ошибка о дублировании реквизита — нет проверки существования

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

Итог

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

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

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

Можно ли добавить реквизит на клиенте без вызова сервера?

Нет. Метод ИзменитьРеквизиты() доступен только в серверном контексте формы. Клиентский обработчик может лишь инициировать серверный вызов, внутри которого выполняется изменение состава реквизитов.

Как добавить реквизит с типом «СправочникСсылка»?

Создайте описание типов через Новый ОписаниеТипов("СправочникСсылка.ИмяСправочника") и передайте его в ОписаниеРеквизитаФормы. Поле ввода на форме автоматически получит кнопку выбора и стандартные механизмы подбора для этого типа.

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

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

Как избежать ошибки при повторном добавлении реквизита?

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

Можно ли добавить колонку в динамический список формы?

Нет, состав колонок динамического списка определяется его запросом и настройками. ИзменитьРеквизиты() работает только с реквизитами формы. Для произвольных колонок используйте реквизит типа ТаблицаЗначений, заполняемый программно.

Работает ли этот способ в расширении конфигурации?

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