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