При разработке отчетов в 1С часто возникает задача: есть простой запрос к реквизитам объектов, например, справочника Контрагенты. К этим объектам привязаны дополнительные свойства, хранящиеся в регистре сведений ДополнительныеСведения или в табличной части ДополнительныеРеквизиты. Нам нужно вывести эти свойства вместе с остальными реквизитами так, чтобы названия свойств стали колонками (в шапке таблицы), а их значения отображались в строках для каждого контрагента. Разберем по шагам, как правильно реализовать такой вывод с помощью Системы компоновки данных (СКД).
Самый правильный и производительный способ решения этой задачи — использование специального механизма СКД. В запросе СКД есть закладка Характеристики (в визуальном конструкторе схемы компоновки данных). Если настроить связи там, платформа сама сгенерирует нужный код. Рассмотрим подробнее, как это выглядит на уровне языка запросов СКД с использованием конструкции {ХАРАКТЕРИСТИКИ ...}.
В современных конфигурациях (на базе БСП, например Бухгалтерия 3.0) свойства делятся на две сущности:
Справочник.Контрагенты.ДополнительныеРеквизиты).ДополнительныеСведения.Чтобы в отчете были доступны оба вида, проанализируем следующий пример кода, который нужно добавить к основному тексту запроса СКД:
ВЫБРАТЬ
Контрагенты.Ссылка,
Контрагенты.Код,
Контрагенты.ИНН
ИЗ
Справочник.Контрагенты КАК Контрагенты
{ХАРАКТЕРИСТИКИ
ТИП(Справочник.Контрагенты)
ВИДЫХАРАКТЕРИСТИК (ВЫБРАТЬ
ДополнительныеРеквизитыИСведения.Ссылка,
ДополнительныеРеквизитыИСведения.Наименование,
ДополнительныеРеквизитыИСведения.ТипЗначения
ИЗ
ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения КАК ДополнительныеРеквизитыИСведения
ГДЕ
ДополнительныеРеквизитыИСведения.НаборСвойств = ЗНАЧЕНИЕ(Справочник.НаборыДополнительныхРеквизитовИСведений.Справочник_Контрагенты)
И ДополнительныеРеквизитыИСведения.Доступен
И НЕ ДополнительныеРеквизитыИСведения.ЭтоДополнительноеСведение
И НЕ ДополнительныеРеквизитыИСведения.ПометкаУдаления)
ПОЛЕКЛЮЧА Ссылка
ПОЛЕИМЕНИ Наименование
ПОЛЕТИПАЗНАЧЕНИЯ ТипЗначения
ЗНАЧЕНИЯХАРАКТЕРИСТИК (ВЫБРАТЬ
КонтрагентыДополнительныеРеквизиты.Ссылка,
КонтрагентыДополнительныеРеквизиты.Свойство,
КонтрагентыДополнительныеРеквизиты.Значение
ИЗ
Справочник.Контрагенты.ДополнительныеРеквизиты КАК КонтрагентыДополнительныеРеквизиты)
ПОЛЕОБЪЕКТА Ссылка
ПОЛЕВИДА Свойство
ПОЛЕЗНАЧЕНИЯ Значение }
{ХАРАКТЕРИСТИКИ
ТИП(Справочник.Контрагенты)
ВИДЫХАРАКТЕРИСТИК (ВЫБРАТЬ
ДополнительныеРеквизитыИСведения.Ссылка,
ДополнительныеРеквизитыИСведения.Наименование,
ДополнительныеРеквизитыИСведения.ТипЗначения
ИЗ
ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения КАК ДополнительныеРеквизитыИСведения
ГДЕ
ДополнительныеРеквизитыИСведения.НаборСвойств = ЗНАЧЕНИЕ(Справочник.НаборыДополнительныхРеквизитовИСведений.Справочник_Контрагенты)
И ДополнительныеРеквизитыИСведения.Доступен
И ДополнительныеРеквизитыИСведения.ЭтоДополнительноеСведение
И НЕ ДополнительныеРеквизитыИСведения.ПометкаУдаления)
ПОЛЕКЛЮЧА Ссылка
ПОЛЕИМЕНИ Наименование
ПОЛЕТИПАЗНАЧЕНИЯ ТипЗначения
ЗНАЧЕНИЯХАРАКТЕРИСТИК РегистрСведений.ДополнительныеСведения
ПОЛЕОБЪЕКТА Объект
ПОЛЕВИДА Свойство
ПОЛЕЗНАЧЕНИЯ Значение }
Почему этот подход лучше всего? Данный метод работает по принципу динамической компоновки. 1С добавит неявное левое соединение к регистру сведений к итоговому SQL-запросу СУБД только в том случае, если пользователь в пользовательском режиме действительно добавит конкретное доп. свойство в группировки, отборы или выбранные поля отчета. Это значительно экономит ресурсы системы.
Иногда разработчики пытаются решить задачу "в лоб" через классическое соединение таблиц. Посмотрим на пример такого запроса:
ВЫБРАТЬ
Контрагенты.Ссылка КАК Контрагент,
ВидыСвойствОбъектов.ВидСвойства,
ЗначенияСвойствОбъектов.Свойство
ИЗ Справочник.Контрагенты КАК Контрагенты
ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ РАЗЛИЧНЫЕ
ЗначенияСвойствОбъектов.Свойство.Наименование КАК ВидСвойства
ИЗ
РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойствОбъектов) КАК ВидыСвойствОбъектов
ПО (1 = 1)
ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ РАЗЛИЧНЫЕ
ЗначенияСвойствОбъектов.Объект КАК Контрагент,
ЗначенияСвойствОбъектов.Свойство.Наименование КАК ВидСвойства,
ЗначенияСвойствОбъектов.Значение КАК Свойство
ИЗ
РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойствОбъектов) КАК ЗначенияСвойствОбъектов
ПО (ЗначенияСвойствОбъектов.Контрагент = Контрагенты.Ссылка)
И (ВидыСвойствОбъектов.ВидСвойства = ЗначенияСвойствОбъектов.ВидСвойства)
ГДЕ
НЕ Контрагенты.ЭтоГруппа
Чтобы такой запрос корректно отобразился в виде кросс-таблицы (где свойства уходят в колонки), в настройках СКД потребуется:
ВидСвойства.Свойство с выражением Свойство (или Максимум(Свойство)).Внимание: Этот подход считается плохим тоном для СКД. Такое соединение будет выполняться всегда, даже если пользователю свойства не нужны, что замедлит работу базы при больших объемах данных. Мы настоятельно рекомендуем использовать первый вариант.
Бывают ситуации, когда бизнес-задача требует вывести дополнительные свойства не в виде динамической "шапки таблицы" с колонками, а собрать их в единое текстовое описание (например, в одной колонке). В таких случаях мы можем оставить простое соединение с регистром сведений, а на вкладке «Ресурсы» в СКД применить специальную функцию агрегации.
Используйте следующее выражение в ресурсе:
СоединитьСтроки(Массив(Представление(Свойство) + " - " + Представление(Значение)), ", ")
Это позволит сгруппировать свойства контрагента в компактный вид. В результате в отчете получится удобная строка: "Категория - VIP, Регион - Запад". Данная функция появилась в современных версиях платформы 1С и отлично справляется со склеиванием детальных записей в одну сводную ячейку.