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