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

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

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

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

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

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

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

Какой сценарий вам нужен: форма или метаданные

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

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

Сравнение подходов

ИзменитьРеквизиты на форме

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

Расширение конфигурации

Подходит для добавления хранимых реквизитов в типовые объекты. Безопасно при обновлениях, требует публикации расширения.

Изменение в конфигураторе

Подходит для собственных (нетиповых) объектов. Для типовой конфигурации усложняет обновление.

Дополнительные реквизиты (БСП)

Подходит, когда реквизит добавляет пользователь без разработчика. Хранится в отдельных таблицах, медленнее в запросах.

Добавление реквизита на управляемую форму через ИзменитьРеквизиты

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

&НаСервере

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

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

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

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

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

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

"Комментарий (динамический)", // Заголовок

Истина); // Сохраняемые данные

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

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

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

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

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

Создание элемента формы для нового реквизита

Элементы формы добавляются через коллекцию Элементы.Добавить() с указанием типа элемента и родителя. Для поля ввода тип — Тип("ПолеФормы"), а вид устанавливается через свойство Вид (например, ВидПоляФормы.ПолеВвода).

&НаСервере

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

// ... сначала ИзменитьРеквизиты()

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

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

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

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

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

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

Добавление колонки в динамическую таблицу значений на форме

Частный и более сложный сценарий — программное создание таблицы значений как реквизита формы с набором колонок. Здесь сначала добавляется реквизит типа ТаблицаЗначений, а затем каждая колонка описывается отдельным ОписаниеРеквизитаФормы с указанием пути — имени таблицы.

&НаСервере

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

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

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

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

"ТаблицаРезультатов", Новый ОписаниеТипов("ТаблицаЗначений")));

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

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

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

"ТаблицаРезультатов", "Номенклатура", Ложь));

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

"Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)),

"ТаблицаРезультатов", "Количество", Ложь));

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

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

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

ЭлементТаблица.ПутьКДанным = "ТаблицаРезультатов";

Колонка = Элементы.Добавить("ТаблицаРезультатовНоменклатура", Тип("ПолеФормы"), ЭлементТаблица);

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

Колонка.ПутьКДанным = "ТаблицаРезультатов.Номенклатура";

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

Обратите внимание на ПутьКДанным колонки: он строится как «ИмяТаблицы.ИмяКолонки». Если пропустить этот путь или указать только имя колонки, поле окажется пустым или форма выдаст ошибку при открытии.

Добавление реквизита в метаданные объекта

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

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

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

Маршрут решения

Как выбрать способ

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

Проверка результата и типичные ошибки

После вызова ИзменитьРеквизиты() убедитесь, что реквизит действительно создан: обратитесь к нему как ЭтаФорма["ИмяРеквизита"] — при отсутствии реквизита будет выброшено исключение. Для элементов формы проверка выполняется через Элементы.Найти("ИмяЭлемента"): если возвращается Неопределено, элемент не создан.

Наиболее частые ошибки разработчиков при программном добавлении реквизитов:

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

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

Метод ИзменитьРеквизиты() — относительно «тяжёлая» операция: платформа пересоздаёт структуру данных формы. Не вызывайте его в цикле при добавлении множества реквизитов — формируйте один массив и выполняйте один вызов. Это заметно быстрее и снижает риск ошибок при сериализации формы.

При динамическом изменении формы учитывайте, что условное оформление, связи параметров выбора и обработчики событий для новых элементов тоже придётся настраивать программно. Для поля ввода, например, событие ПриИзменении назначается через УстановитьДействие("ПриИзменении", "ИмяПроцедуры"), а сама процедура-обработчик должна существовать в модуле формы до компиляции.

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

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

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

Реквизит создан
Норма

Обращение ЭтаФорма[Имя] не вызывает исключения

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

Ошибка «Поле объекта не обнаружено» — реквизит не добавлен

Элемент на форме
Норма

Элементы.Найти(Имя) возвращает элемент, поле видно пользователю

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

Возвращается Неопределено или поле не отображается

Связь элемента и данных
Норма

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

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

Поле пустое при заполненном реквизите — неверный ПутьКДанным

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

Форма открывается в режиме предприятия, журнал регистрации чист

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

Ошибки при создании формы — проверьте порядок вызовов на сервере

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

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

Штатного безопасного способа изменить структуру метаданных из кода в рабочей базе нет — платформа не предоставляет такого API для прикладного решения. Для типовых конфигураций используйте расширение, для пользовательских доработок без программиста — механизм дополнительных реквизитов и сведений БСП.

Почему после ИзменитьРеквизиты поле не видно на форме?

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

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

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

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

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

Работает ли ИзменитьРеквизиты в обычных формах (толстый клиент)?

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

Что выбрать: динамические реквизиты формы или дополнительные реквизиты БСП?

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

Итог

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

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