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

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

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

Как программно записать дополнительные реквизиты в 1С: работа со свойствами через ПланыВидовХарактеристик, поиск по имени, заполнение табличной части, типовые ошибки и примеры кода.

Дополнительные реквизиты в 1С — это механизм БСП (Библиотеки стандартных подсистем), который позволяет добавлять к справочникам и документам произвольные поля без изменения конфигурации. Значения хранятся не в отдельных колонках таблицы, а в табличной части объекта «ДополнительныеРеквизиты», где каждая строка связывает свойство из плана видов характеристик «ДополнительныеРеквизитыИСведения» с конкретным значением.

Из-за такой структуры хранения программное заполнение отличается от обычного присвоения реквизита: нельзя просто написать Объект.Цвет = Справочники.Цвета.Красный. Нужно найти ссылку на свойство, проверить наличие строки в табличной части и записать значение подходящего типа. Ниже разобраны рабочие приёмы для типовых конфигураций — УТ, ERP, БП, ЗУП.

Как устроено хранение дополнительных реквизитов

Перед написанием кода важно понимать модель данных. Каждое дополнительное свойство описано элементом плана видов характеристик «ДополнительныеРеквизитыИСведения». У него есть заголовок, тип значения (строка, число, булево, ссылка на справочник или на дополнительные значения) и набор свойств, к которому оно привязано — например, «Номенклатура» или «Контрагенты».

Сами значения хранятся в двух местах в зависимости от вида свойства. Дополнительные реквизиты — в табличной части объекта «ДополнительныеРеквизиты» (колонки «Свойство» и «Значение»). Дополнительные сведения — в регистре сведений «ДополнительныеСведения» с измерением «Объект». Это принципиальная разница: сведения можно заполнять, не открывая и не блокируя сам объект, а для реквизитов объект придётся получать и записывать.

Как найти свойство по имени

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

Функция НайтиСвойство(ИмяСвойства)

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ ПЕРВЫЕ 1

| Свойства.Ссылка КАК Ссылка

|ИЗ

| ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения КАК Свойства

|ГДЕ

| Свойства.Заголовок = &Заголовок

| И НЕ Свойства.ПометкаУдаления";

Запрос.УстановитьПараметр("Заголовок", ИмяСвойства);

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда

Возврат Выборка.Ссылка;

КонецЕсли;

Возврат Неопределено;

КонецФункции

Поиск по заголовку хрупок: администратор может переименовать свойство, и код молча перестанет работать. Если свойство создаётся в конфигураторе как предопределённое, надёжнее искать по имени предопределённого элемента через ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.ИмяСвойства или по реквизиту «Имя» (в БСП оно называется «Имя» и используется для программной работы).

Заполнение дополнительного реквизита объекта

Базовый сценарий: открываем объект, находим или добавляем строку в табличной части «ДополнительныеРеквизиты», записываем значение, сохраняем объект. Универсальная процедура выглядит так:

Процедура УстановитьДопРеквизит(Объект, Свойство, Значение)

Строки = Объект.ДополнительныеРеквизиты.НайтиСтроки(

Новый Структура("Свойство", Свойство));

Если Строки.Количество() = 0 Тогда

Строка = Объект.ДополнительныеРеквизиты.Добавить();

Строка.Свойство = Свойство;

Иначе

Строка = Строки[0];

КонецЕсли;

Строка.Значение = Значение;

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

// Использование:

Свойство = НайтиСвойство("Цвет корпуса");

Если Свойство = Неопределено Тогда

ВызватьИсключение "Свойство не найдено";

КонецЕсли;

ТоварОбъект = СсылкаНаТовар.ПолучитьОбъект();

УстановитьДопРеквизит(ТоварОбъект, Свойство, "Чёрный");

ТоварОбъект.Записать();

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

Порядок действий
  1. 1
    Найдите ссылку на свойство в ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения по имени или заголовку
  2. 2
    Получите объект методом ПолучитьОбъект()
  3. 3
    Найдите строку свойства в табличной части ДополнительныеРеквизиты через НайтиСтроки
  4. 4
    Если строки нет — добавьте её и укажите свойство
  5. 5
    Присвойте значение, убедившись, что тип совпадает с типом свойства
  6. 6
    Вызовите Записать() и проверьте результат в карточке объекта

Заполнение дополнительных сведений через регистр

Дополнительные сведения записываются иначе — через набор записей регистра сведений «ДополнительныеСведения». Объект при этом не трогается, что быстрее и безопаснее при массовой обработке: нет блокировок карточек и не срабатывают обработчики записи объекта.

Процедура УстановитьДопСведение(ОбъектСсылка, Свойство, Значение)

Набор = РегистрыСведений.ДополнительныеСведения.СоздатьНаборЗаписей();

Набор.Отбор.Объект.Установить(ОбъектСсылка);

Набор.Отбор.Свойство.Установить(Свойство);

Запись = Набор.Добавить();

Запись.Объект = ОбъектСсылка;

Запись.Свойство = Свойство;

Запись.Значение = Значение;

Набор.Записать();

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

Отбор по измерениям «Объект» и «Свойство» обязателен: без него набор запишет все записи регистра или выбросит ошибку. В БСП также есть готовые процедуры модуля «УправлениеСвойствами» — в ряде версий доступны методы для установки значений свойств без ручной работы с регистром; их наличие зависит от версии библиотеки, поэтому перед использованием проверьте состав модуля в своей конфигурации.

Контроль типа значения и дополнительные значения

Частая причина ошибок — несовпадение типа записываемого значения с типом свойства. Если свойство объявлено как «Дополнительное значение» (ссылка на справочник «ЗначенияСвойствОбъектов»), записать туда произвольную строку нельзя: сначала нужно найти или создать элемент этого справочника, у которого владелец — наше свойство.

Функция НайтиДопЗначение(Свойство, Наименование)

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ ПЕРВЫЕ 1 Зн.Ссылка

|ИЗ Справочник.ЗначенияСвойствОбъектов КАК Зн

|ГДЕ Зн.Владелец = &Свойство И Зн.Наименование = &Наименование";

Запрос.УстановитьПараметр("Свойство", Свойство);

Запрос.УстановитьПараметр("Наименование", Наименование);

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда

Возврат Выборка.Ссылка;

КонецЕсли;

Новый = Справочники.ЗначенияСвойствОбъектов.СоздатьЭлемент();

Новый.Владелец = Свойство;

Новый.Наименование = Наименование;

Новый.Записать();

Возврат Новый.Ссылка;

КонецФункции

Проверить тип свойства можно через его реквизит «ТипЗначения»: Свойство.ТипЗначения.СодержитТип(ТипЗнч(Значение)). Такая проверка перед записью избавляет от ошибок несоответствия типов при проведении и сохранении объекта.

Типичные ошибки
01
Добавление новой строки табличной части без поиска существующей — дубли свойства ломают отчёты и отборы
02
Поиск свойства только по заголовку — после переименования свойства пользователем код перестаёт находить его
03
Запись строки в свойство с типом «Дополнительное значение» — ошибка несоответствия типов при записи объекта
04
Запись набора регистра ДополнительныеСведения без отбора по Объект и Свойство — риск затереть чужие записи
05
Игнорирование пометки удаления свойства — значение пишется в архивное свойство и не видно пользователям

Массовое заполнение и производительность

При обработке тысяч объектов наивный подход «получить объект — заполнить — записать» в цикле работает медленно и нагружает сервер. Для дополнительных сведений лучше собирать один набор записей регистра без отбора и записывать его порциями. Для реквизитов объекты придётся записывать по одному, но можно отключить лишние механизмы: Объект.ОбменДанными.Загрузка = Истина пропускает бизнес-логику, однако использовать этот приём нужно осознанно — пропускаются и проверки корректности данных.

Свойства при массовой обработке стоит закэшировать: найти все нужные ссылки один раз до цикла и хранить в соответствии «имя — ссылка». Запрос к плану видов характеристик внутри цикла по каждому объекту — типовая причина десятикратного замедления обработки.

Проверка результата и границы применения

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

Учтите ограничения механизма. Дополнительные реквизиты недоступны, если для набора свойств объекта они не добавлены в настройках «Администрирование — Общие настройки — Дополнительные реквизиты и сведения». Свойство, не входящее в набор объекта, можно записать в табличную часть программно, но пользователь его не увидит. Также помните, что в типовых отчётах дополнительные реквизиты доступны через СКД, но произвольные запросы к ним требуют соединения с табличной частью, что медленнее обычных реквизитов.

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

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

Карточка объекта, закладка «Дополнительно»
Норма

Свойство отображается с записанным значением

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

Свойства нет — оно не входит в набор свойств объекта

Табличная часть ДополнительныеРеквизиты
Норма

Одна строка на каждое свойство

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

Несколько строк с одним свойством — дубли

Запрос к регистру ДополнительныеСведения
Норма

Запись с нужными Объект, Свойство, Значение

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

Записи нет — проверьте отбор и вызов Записать()

Итог

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

Реквизиты пишутся через табличную часть объекта с поиском строки по свойству, сведения — через регистр сведений с обязательным отбором. Свойство ищите по служебному имени, а не по заголовку, контролируйте тип значения и не допускайте дублей строк. Массовые операции сначала тестируйте на копии базы.

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

Чем дополнительный реквизит отличается от дополнительного сведения?

Реквизит хранится в табличной части самого объекта и записывается вместе с ним, сведение — в отдельном регистре сведений. Сведения удобнее для массовой загрузки и не требуют блокировки объекта, реквизиты лучше подходят для данных, которые должны редактироваться в карточке и участвовать в логике объекта.

Почему записанное значение не видно в карточке объекта?

Чаще всего свойство не добавлено в набор дополнительных реквизитов для этого вида объектов. Проверьте настройку в разделе «Администрирование — Общие настройки — Дополнительные реквизиты» и убедитесь, что свойство не помечено на удаление.

Как заполнить реквизит типа «Дополнительное значение»?

Сначала найдите или создайте элемент справочника «ЗначенияСвойствОбъектов», у которого поле «Владелец» равно вашему свойству, а затем запишите ссылку на этот элемент как значение. Строку или число напрямую записать нельзя — будет ошибка несоответствия типов.

Можно ли заполнить дополнительные реквизиты без получения объекта?

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

Как удалить значение дополнительного реквизита программно?

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

Работает ли этот подход во внешних обработках и расширениях?

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