В конфигурации «1С:Управление нашей фирмой» (УНФ) версии 1.6, как и в других современных решениях на платформе «1С:Предприятие 8.3», механизм дополнительных реквизитов и сведений реализован на базе Библиотеки стандартных подсистем (БСП). При попытке программно создать дополнительный реквизит и привязать его к объекту (например, к номенклатуре определенной категории) начинающие разработчики часто сталкиваются с тем, что реквизиты не отображаются в интерфейсе, не сохраняются или их невозможно найти поиском.
В этой статье мы подробно разберем, как устроен этот механизм изнутри, проанализируем типичные ошибки и напишем готовый к использованию программный код для корректного создания дополнительных реквизитов и записи их значений с помощью стандартных методов БСП.
Прежде чем перейти к написанию кода, разберем ключевые объекты метаданных, которые участвуют в этом процессе:
ДополнительныеРеквизитыИСведения — здесь хранятся сами свойства (например, «Производитель», «Размер», «Цвет»). Каждый элемент ПВХ определяет тип значения реквизита и его поведение.НаборыДополнительныхРеквизитовИСведений — группирует свойства для конкретных объектов (например, для всей номенклатуры или для конкретной категории номенклатуры).ЗначенияСвойствОбъектов — хранит конкретные значения для реквизитов, у которых тип данных определен как «Дополнительное значение» (например, значения «Bosch», «LG» для свойства «Производитель»).ДополнительныеРеквизиты в номенклатуре) — хранят непосредственно значения дополнительных реквизитов для каждого конкретного элемента.Важная особенность 1С:УНФ: При создании новой категории номенклатуры система автоматически создает для нее уникальный набор свойств и записывает ссылку на него в реквизит категории НаборСвойств. Пытаться создавать этот набор вручную по наименованию или искать его общими методами не нужно — достаточно просто получить его из записанной категории.
---
Для начала рассмотрим, как правильно создать сам дополнительный реквизит. Обязательно нужно указать тип значения, имя для формул и привязать его к набору свойств.
Разберем пример создания дополнительного реквизита «Производитель» для конкретной категории номенклатуры:
// Предположим, у нас уже есть ссылка на Категорию Номенклатуры - КатСсылка
НаборСвойствКатегории = КатСсылка.НаборСвойств; // Извлекаем готовый набор свойств, созданный системой автоматически
Если НЕ ЗначениеЗаполнено(НаборСвойствКатегории) Тогда
ВызватьИсключение "У выбранной категории номенклатуры не заполнен набор свойств! Возможно, категория не записана.";
КонецЕсли;
// Формируем наименование свойства по стандарту БСП: "ИмяРеквизита (НаименованиеНабора)"
ИмяСвойства = "Производитель";
ПолноеНаименованиеСвойства = ИмяСвойства + " (" + СокрЛП(КатСсылка.Наименование) + ")";
// Ищем, не создан ли уже такой реквизит
СсылкаНаРеквизит = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию(ПолноеНаименованиеСвойства);
Если СсылкаНаРеквизит.Пустая() Тогда
НовыйРеквизит = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.СоздатьЭлемент();
НовыйРеквизит.Заголовок = ИмяСвойства;
НовыйРеквизит.Наименование = ПолноеНаименованиеСвойства;
// Задаем уникальное имя для формул и запросов (без пробелов)
НовыйРеквизит.Имя = "Производитель_" + СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", "_");
// Указываем тип значения. Если это список выбора - используем СправочникСсылка.ЗначенияСвойствОбъектов
НовыйРеквизит.ТипЗначения = Новый ОписаниеТипов("СправочникСсылка.ЗначенияСвойствОбъектов");
НовыйРеквизит.НаборСвойств = НаборСвойствКатегории;
НовыйРеквизит.Виден = Истина;
НовыйРеквизит.Доступен = Истина;
НовыйРеквизит.ДополнительныеЗначенияИспользуются = Истина;
НовыйРеквизит.Записать();
СсылкаНаРеквизит = НовыйРеквизит.Ссылка;
КонецЕсли;
---
Просто создать элемент в плане видов характеристик недостаточно. Чтобы реквизит появился на форме карточки номенклатуры, его необходимо физически добавить в табличную часть ДополнительныеРеквизиты соответствующего набора свойств.
Проанализируем, как это сделать программно без дублирования записей:
ОбъектНабора = НаборСвойствКатегории.ПолучитьОбъект();
// Проверяем, добавлено ли уже наше свойство в этот набор
СтрокаСвойства = ОбъектНабора.ДополнительныеРеквизиты.Найти(СсылкаНаРеквизит, "Свойство");
Если СтрокаСвойства = Неопределено Тогда
НоваяСтрока = ОбъектНабора.ДополнительныеРеквизиты.Добавить();
НоваяСтрока.Свойство = СсылкаНаРеквизит;
// Для дополнительных реквизитов (отображаемых в карточке) заполняем эту ТЧ.
// Если бы создавали Дополнительное Сведение - заполняли бы ТЧ "ДополнительныеСведения".
ОбъектНабора.Записать();
КонецЕсли;
---
Поскольку мы выбрали тип значения СправочникСсылка.ЗначенияСвойствОбъектов, нам нужно программно создавать элементы этого справочника (например, значение «Bosch» для свойства «Производитель»). Обязательным условием является заполнение реквизита Владелец — в его качестве выступает наш созданный дополнительный реквизит (ПВХ).
НазваниеБренда = "Bosch"; // Значение, которое мы хотим создать
// Ищем, существует ли уже такое значение для нашего свойства
СсылкаНаЗначение = Справочники.ЗначенияСвойствОбъектов.НайтиПоНаименованию(НазваниеБренда, Истина, , СсылкаНаРеквизит);
Если СсылкаНаЗначение.Пустая() Тогда
НовоеЗначение = Справочники.ЗначенияСвойствОбъектов.CreateItem();
НовоеЗначение.Наименование = НазваниеБренда;
НовоеЗначение.Владелец = СсылкаНаРеквизит; // Указываем владельца-свойство
НовоеЗначение.Записать();
СсылкаНаЗначение = НовоеЗначение.Ссылка;
КонецЕсли;
---
Существует два способа записи значения свойства в конкретный элемент номенклатуры: прямое изменение табличной части объекта и использование программного интерфейса БСП. Рассмотрим оба варианта, уделив особое внимание наиболее надежному.
В БСП предусмотрен специальный общий модуль УправлениеСвойствами, который берет на себя всю рутину по обновлению кэша, проверке прав, заполнению сопутствующих регистров и записи изменений. Использование метода ЗаписатьСвойстваУОбъекта гарантирует стабильность базы данных и предотвращает рассинхронизацию информации.
// Подготавливаем таблицу свойств и значений по структуре БСП
ТаблицаСвойств = Новый ТаблицаЗначений;
ТаблицаСвойств.Колонки.Добавить("Свойство", Новый ОписаниеТипов("ПланВидовХарактеристикСсылка.ДополнительныеРеквизитыИСведения"));
ТаблицаСвойств.Колонки.Добавить("Значение");
// Добавляем строку с нашим свойством и созданным значением
НоваяСтрока = ТаблицаСвойств.Добавить();
НоваяСтрока.Свойство = СсылкаНаРеквизит;
НоваяСтрока.Значение = СсылкаНаЗначение;
// Записываем свойства для конкретной Номенклатуры (передаем ссылку на номенклатуру)
УправлениеСвойствами.ЗаписатьСвойстваУОбъекта(СсылкаНаНоменклатуру, ТаблицаСвойств);
Если по какой-то причине вам необходимо внести изменения непосредственно в открытый объект (например, в форме перед записью или внутри обработчика объекта), можно обратиться к табличной части ДополнительныеРеквизиты напрямую:
// Предположим, у нас есть объект номенклатуры - НоменклатураОбъект
СтрокаРеквизита = НоменклатураОбъект.ДополнительныеРеквизиты.Найти(СсылкаНаРеквизит, "Свойство");
Если СтрокаРеквизита = Неопределено Тогда
СтрокаРеквизита = НоменклатураОбъект.ДополнительныеРеквизиты.Добавить();
СтрокаРеквизита.Свойство = СсылкаНаРеквизит;
КонецЕсли;
СтрокаРеквизита.Значение = СсылкаНаЗначение;
НоменклатураОбъект.Записать();
---
При работе с механизмами свойств в 1С:УНФ важно помнить следующие правила:
ТипЗначения пустым, система не сможет корректно отобразить поле ввода на форме, а записанные значения могут «теряться».ЗначенияСвойствОбъектов всегда указывайте конкретное свойство в качестве владельца, иначе вы получите некорректно работающие списки выбора.УправлениеСвойствами.ЗаписатьСвойстваУОбъекта. Это делает ваш код чище, надежнее и устойчивее к будущим обновлениям конфигурации.