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