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