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

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

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

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

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

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

Важно помнить ограничение: изменять состав реквизитов можно только на сервере, поэтому код размещается в серверной процедуре с директивой &НаСервере. Клиентская процедура может только инициировать вызов, но не изменяет структуру формы напрямую.

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

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

Метод ИзменитьРеквизиты() принимает два параметра: массив добавляемых реквизитов и массив имён удаляемых. Оба параметра необязательны — можно только добавлять или только удалять. Каждый добавляемый реквизит описывается объектом ОписаниеРеквизитаФормы (конструктор Новый РеквизитФормы() в некоторых версиях синтаксиса — фактически используется конструктор объекта описания).

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

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

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

&НаСервере

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

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

ОписаниеТипа = Новый ОписаниеТипов("Строка", ,

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

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

"КомментарийДинамический", ОписаниеТипа, , "Комментарий");

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

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

// Теперь добавляем элемент формы

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

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

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

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

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

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

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

После выполнения кода реквизит доступен в коде формы как ЭтаФорма.КомментарийДинамический или просто КомментарийДинамический внутри модулей формы. Пользователь увидит обычное поле ввода, ничем не отличающееся от созданного в конфигураторе.

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

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

&НаСервере

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

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

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

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

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

// Колонки таблицы — третий параметр: путь к таблице

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

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

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

"ДинамическиеДанные", "Номенклатура"));

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

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

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

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

"ДинамическиеДанные", "Количество"));

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

// Элемент таблицы

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

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

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

// Колонки элемента таблицы

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

"ДинамическиеДанныеНоменклатура", Тип("ПолеФормы"), ЭлементТаблица);

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

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

КолонкаКоличество = Элементы.Добавить(

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

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

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

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

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

Заполнение такой таблицы выполняется обычным способом: НоваяСтрока = ДинамическиеДанные.Добавить(); НоваяСтрока.Номенклатура = .... Также можно загрузить готовую таблицу значений через ЗначениеВРеквизитФормы(ТаблицаЗначений, "ДинамическиеДанные").

Порядок добавления динамической таблицы
  1. 1
    Создайте массив добавляемых реквизитов
  2. 2
    Добавьте реквизит типа ТаблицаЗначений
  3. 3
    Добавьте реквизиты-колонки с путём к таблице в третьем параметре
  4. 4
    Вызовите ИзменитьРеквизиты(Массив) на сервере
  5. 5
    Создайте элемент ТаблицаФормы с ПутьКДанным на реквизит таблицы
  6. 6
    Добавьте поля-колонки с путями вида Таблица.Колонка
  7. 7
    Заполните таблицу данными и проверьте отображение

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

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

&НаСервере

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

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

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

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

Элементы.Удалить(Элементы.КомментарийДинамический);

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

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

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

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

Типичные ошибки и их устранение

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

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

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

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

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

Ограничения и альтернативные подходы

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

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

Ещё одна альтернатива — динамический список с произвольным запросом: колонки подхватываются из запроса автоматически, и ручное создание реквизитов не требуется. Это удобно для списков данных, но не подходит для ввода значений вручную.

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

Программное добавление реквизитов

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

Реквизиты в конфигураторе

Надёжно и прозрачно, но состав фиксирован. Подходит, когда набор полей известен заранее.

СКД или динамический список

Колонки формируются автоматически из запроса. Подходит для просмотра данных, а не для ручного ввода.

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

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

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

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

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

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

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

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

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

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

Сохранность данных
Норма

Введённое значение доступно в коде после серверного вызова

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

Значение пропадает — реквизиты пересоздаются при каждом вызове

Колонки таблицы
Норма

Ячейки редактируются, типы соответствуют заданным

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

Колонка пустая или только для чтения — неверный путь вида Таблица.Колонка

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

Форма открывается без ошибок, структура создаётся заново

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

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

Итог

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

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

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

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

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

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

Сформируйте ОписаниеТипов с массивом типов: Новый ОписаниеТипов("Строка,СправочникСсылка.Номенклатура", , Квалификаторы). Поле ввода тогда позволит выбирать значение любого из перечисленных типов.

Почему данные в динамических реквизитах пропадают после серверного вызова?

Обычно потому, что код пересоздания реквизитов выполняется повторно и удаляет старые реквизиты вместе со значениями. Добавляйте реквизиты один раз — например, при создании формы — либо сохраняйте значения во временную структуру перед перестроением.

Как узнать, какие реквизиты формы уже существуют?

Используйте ЭтаФорма.ПолучитьРеквизиты() — метод возвращает массив описаний реквизитов верхнего уровня. Для колонок таблицы передайте путь: ПолучитьРеквизиты("ИмяТаблицы"). Перебором массива можно проверить имя перед добавлением.

Можно ли программно добавить реквизит в расширении конфигурации?

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

Чем программное добавление отличается от создания реквизита в конфигураторе?

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