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