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