При переносе данных из внешних систем (например, старых баз 1С v7.7 или таблиц Excel) в современные конфигурации на платформе 1С:Предприятие 8.3 (такие как 1С:Бухгалтерия 3.0 или 1С:Управление торговлей 11) часто возникает необходимость расширить стандартные реквизиты объектов без изменения конфигурации на уровне метаданных. Для этого идеально подходит механизм Дополнительных реквизитов и сведений, входящий в состав Библиотеки стандартных подсистем (БСП).
Однако при работе с такими реквизитами стандартные методы поиска (например, НайтиПоРеквизиту) не работают напрямую, так как эти данные хранятся в подчиненных табличных частях. В этой статье мы подробно разберем, как связать сторонний справочник с номенклатурой через механизм дополнительных реквизитов, как быстро находить связанные объекты и как одним запросом выявить элементы, оставшиеся без привязки.
Прежде чем переходить к написанию кода, проанализируем, где именно хранятся нужные нам данные. Подсистема «Свойства» в БСП разделяет свойства объектов на две категории:
Номенклатура.ДополнительныеРеквизиты.РегистрСведений.ДополнительныеСведения. Связующим звеном выступает измерение Объект.Важный нюанс: Если при импорте данных из Excel свойства были записаны как дополнительные сведения, то любые попытки обратиться к табличной части Номенклатура.ДополнительныеРеквизиты вернут пустой результат. Всегда проверяйте, какой тип свойств используется в вашей системе.
Рассмотрим ситуацию, когда у нас есть вспомогательный справочник (например, Справочник.Ярлыки), элементы которого выбраны в качестве значений дополнительного реквизита номенклатуры. Нам необходимо определить, какие элементы справочника Ярлыки еще не привязаны ни к одной номенклатуре.
Типичная ошибка начинающих разработчиков — это построение алгоритма через выборку всех элементов в цикле и выполнение запроса на каждой итерации (как показано в Сообщении 10 форума). Такой подход генерирует сотни и тысячи лишних обращений к СУБД, что критически снижает производительность системы. Мы решим эту задачу правильно — одним оптимальным запросом с использованием механизма левого соединения.
Рассмотрим текст запроса:
ВЫБРАТЬ
Ярлыки.Ссылка КАК Ярлык
ИЗ
Справочник.Ярлыки КАК Ярлыки
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК НоменклатураДополнительныеРеквизиты
ПО Ярлыки.Ссылка = НоменклатураДополнительныеРеквизиты.Значение
И НоменклатураДополнительныеРеквизиты.Свойство = &СвойствоЯрлык
ГДЕ
НоменклатураДополнительныеРеквизиты.Ссылка ЕСТЬ NULL
Разберем этот запрос по шагам:
Справочник.Ярлыки.ЛЕВОЕ СОЕДИНЕНИЕ с табличной частью ДополнительныеРеквизиты справочника номенклатуры. Это позволяет сопоставить каждый ярлык с записями в номенклатуре, где данный ярлык выступает в качестве значения реквизита.И НоменклатураДополнительныеРеквизиты.Свойство = &СвойствоЯрлык. Это исключает ложные сопоставления. Если этого не сделать, а справочник Ярлыки используется как значение для других свойств базы (например, у договоров или контрагентов), запрос отработает некорректно и скроет нужные ярлыки.ГДЕ мы накладываем условие НоменклатураДополнительныеРеквизиты.Ссылка ЕСТЬ NULL. Это отсекает все успешно соединенные записи, оставляя в результате только те элементы справочника Ярлыки, для которых соответствие в номенклатуре отсутствует.В типовых конфигурациях (1С:Бухгалтерия 3.0, 1С:Управление торговлей 11, 1С:ERP) разработчики БСП уже предусмотрели готовый программный интерфейс для работы со свойствами. Настоятельно рекомендуется использовать функции общего модуля УправлениеСвойствами вместо написания собственных велосипедов.
1. Получение значения конкретного свойства для одного объекта:
Если нам нужно быстро узнать значение свойства у конкретной номенклатуры, используем метод:
ЗначениеРеквизита = УправлениеСвойствами.ЗначениеСвойства(СсылкаНаНоменклатуру, СсылкаНаСвойство);
2. Пакетное получение значений свойств (оптимально для списков):
Если перед нами стоит задача обработать массив номенклатуры, мы можем получить значения их свойств за один вызов, передав массив ссылок:
МассивНоменклатуры = Новый Массив;
// Заполняем массив ссылками...
ТаблицаЗначенийСвойств = УправлениеСвойствами.ЗначенияСвойств(МассивНоменклатуры, Истина, Ложь);
Этот метод возвращает таблицу значений со свойствами и их значениями для всех переданных объектов, что избавляет нас от необходимости писать тяжелые запросы вручную.
3. Безопасная запись дополнительных реквизитов (актуально при импорте данных):
При записи данных из Excel напрямую заполнять табличную часть объекта кодом не рекомендуется, так как это может обойти внутренние бизнес-правила БСП и нарушить ссылочную целостность. Используем безопасный метод записи:
ТаблицаСвойств = Новый ТаблицаЗначений;
ТаблицаСвойств.Колонки.Добавить("Свойство", Новый ОписаниеТипов("ПланВидовХарактеристикСсылка.ДополнительныеРеквизитыИСведения"));
ТаблицаСвойств.Колонки.Добавить("Значение");
НоваяСтрока = ТаблицаСвойств.Добавить();
НоваяСтрока.Свойство = СсылкаНаСвойствоЯрлык;
НоваяСтрока.Значение = СсылкаНаЯрлык;
УправлениеСвойствами.ЗаписатьСвойстваУОбъекта(СсылкаНаНоменклатуру, ТаблицаСвойств);
При работе с крупными базами данных запросы к табличным частям дополнительных реквизитов могут начать существенно замедляться. Это связано с тем, что СУБД по умолчанию не индексирует поле Значение в подчиненных таблицах 1С.
Чтобы решить эту проблему и ускорить поиск номенклатуры по дополнительным свойствам в десятки раз, необходимо настроить индексирование:
После сохранения этой настройки платформа автоматически создаст соответствующий индекс в базе данных SQL, что обеспечит мгновенное выполнение наших запросов даже при миллионных объемах записей.