При автоматизации загрузки данных или доработке типовых конфигураций на базе БСП (включая 1С:Управление торговлей 11, 1С:ERP и 1С:Комплексная автоматизация) часто возникает задача программного создания дополнительных реквизитов. Если для общих реквизитов номенклатуры достаточно использовать предопределенный элемент справочника наборов, то привязка реквизита к конкретному Виду номенклатуры вызывает ошибки.
Разберем типичные ошибки при программном создании свойств, внутреннее устройство механизма дополнительных реквизитов и напишем правильный рабочий код.
При попытке напрямую обратиться к табличной части вида номенклатуры разработчики нередко пишут следующий код:
ЛСпрСсылка = Справочники.ВидыНоменклатуры.НайтиПоНаименованию("Пеналы");
лСпр = ЛСпрСсылка.ПолучитьОбъект();
стр = лСпр.ДополнительныеРеквизиты.Добавить(); // Ошибка: Поле объекта не обнаружено
Выясним причину этой ошибки. В типовых конфигурациях 1С справочник ВидыНоменклатуры сам по себе не хранит перечень дополнительных реквизитов в собственной табличной части. Для каждого элемента вида номенклатуры выделяется отдельный элемент в справочнике НаборыДополнительныхРеквизитовИСведений. Ссылка на этот набор записывается в реквизит НаборСвойств (для свойств самой номенклатуры) и НаборСвойствХарактеристик (для свойств характеристик).
Таким образом, чтобы назначить дополнительный реквизит конкретному виду номенклатуры, необходимо работать именно с набором свойств, на который ссылается данный вид.
Разберем процесс по шагам:
НаборСвойств у нужного элемента справочника ВидыНоменклатуры. Если вид номенклатуры был создан программно и поле пустое, создаем новый элемент справочника НаборыДополнительныхРеквизитовИСведений и связываем его с видом.ДополнительныеРеквизитыИСведения, настраиваем тип данных, заголовок и указываем в качестве владельца полученный набор свойств.ДополнительныеРеквизиты и записываем объект.Рассмотрим подробнее программный код, реализующий эту цепочку действий.
// 1. Находим нужный вид номенклатуры
ВидНоменклатурыСсылка = Справочники.ВидыНоменклатуры.НайтиПоНаименованию("Пеналы");
Если ВидНоменклатурыСсылка.Пустая() Тогда
ВызватьИсключение "Вид номенклатуры не найден!";
КонецЕсли;
ВидНоменклатурыОбъект = ВидНоменклатурыСсылка.ПолучитьОбъект();
// Проверяем наличие набора свойств. Если он не создан, создаем его
Если Не ЗначениеЗаполнено(ВидНоменклатурыОбъект.НаборСвойств) Тогда
НаборОбъект = Справочники.НаборыДополнительныхРеквизитовИСведений.СоздатьЭлемент();
НаборОбъект.Наименование = ВидНоменклатурыОбъект.Наименование;
НаборОбъект.Записать();
ВидНоменклатурыОбъект.НаборСвойств = НаборОбъект.Ссылка;
ВидНоменклатурыОбъект.Записать();
КонецЕсли;
НаборСвойствСсылка = ВидНоменклатурыОбъект.НаборСвойств;
// 2. Создаем описание типа для дополнительного реквизита (например, Булево или Число)
КвалификаторЧисла = Новый КвалификаторыЧисла(12, 2);
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("Число"));
ОписаниеТипаЗначения = Новый ОписаниеТипов(МассивТипов, КвалификаторЧисла);
// 3. Создаем элемент в Плане видов характеристик "ДополнительныеРеквизитыИСведения"
НовоеСвойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.СоздатьЭлемент();
НовоеСвойство.Заголовок = "Длина пенала (см)";
// По стандарту БСП наименование формируется как "Заголовок (Наименование набора)"
НовоеСвойство.Наименование = "Длина пенала (см) (" + СокрЛП(НаборСвойствСсылка.Наименование) + ")";
НовоеСвойство.НаборСвойств = НаборСвойствСсылка;
НовоеСвойство.ТипЗначения = ОписаниеТипаЗначения;
НовоеСвойство.Виден = Истина;
НовоеСвойство.Доступен = Истина;
НовоеСвойство.Записать();
// 4. Добавляем созданный реквизит в набор свойств вида номенклатуры
НаборОбъект = НаборСвойствСсылка.ПолучитьОбъект();
СтрокаНабора = НаборОбъект.ДополнительныеРеквизиты.Добавить();
СтрокаНабора.Свойство = НовоеСвойство.Ссылка;
НаборОбъект.Записать();
После создания реквизита и привязки его к виду номенклатуры мы можем заполнять этот реквизит у конкретных позиций справочника Номенклатура.
Для корректного сохранения значений в типовых конфигурациях рекомендуется использовать процедуры подсистемы БСП УправлениеСвойствами, что исключает прямую модификацию табличных частей и гарантирует выполнение всех проверок прав и валидации:
// Подготовка таблицы значений для записи свойств
ТаблицаСвойств = Новый ТаблицаЗначений;
ТаблицаСвойств.Колонки.Добавить("Свойство", Новый ОписаниеТипов("ПланВидовХарактеристикСсылка.ДополнительныеРеквизитыИСведения"));
ТаблицаСвойств.Колонки.Добавить("Значение");
НоваяСтрока = ТаблицаСвойств.Добавить();
НоваяСтрока.Свойство = НовоеСвойство.Ссылка;
НоваяСтрока.Значение = 21.5;
// Запись значений реквизитов для выбранной номенклатуры
УправлениеСвойствами.ЗаписатьСвойстваУОбъекта(НоменклатураСсылка, ТаблицаСвойств);
Для чтения значения используем типовую функцию:
ЗначениеРеквизита = УправлениеСвойствами.ЗначениеСвойства(НоменклатураСсылка, НовоеСвойство.Ссылка);
Такой подход обеспечивает полную совместимость с механизмами БСП, предотвращает ошибки дублирования свойств и корректно отображает добавленные реквизиты в пользовательском интерфейсе карточки номенклатуры.