Как вывести иерархический прайс-лист в СКД и настроить колонки

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Управленческий учет Торговля и дистрибуция
← На главную

При разработке отчетов в системе компоновки данных (СКД) 1С начинающие программисты часто сталкиваются с трудностями при попытке вывести данные с учетом иерархии справочников. Типичные симптомы этой проблемы — отображение только верхнего уровня папок, дублирование строк или ситуация, когда числовые показатели (например, цена или остаток) смещаются в одну колонку с наименованием номенклатуры и отображаются строкой ниже. В этой статье мы подробно разберем, как спроектировать правильный запрос для прайс-листа, настроить иерархический вывод в СКД и решить проблемы с некорректным отображением колонок.

Различие между группировкой в запросе и группировками в СКД

Прежде чем переходить к настройкам отчета, выясним ключевую причину, почему первоначальный запрос автора темы работал некорректно. Разберем разницу в подходах к группировке данных:

  1. Группировка в запросе (конструкция СГРУППИРОВАТЬ ПО): Этот механизм выполняется непосредственно на уровне СУБД. Его главная цель — свернуть дублирующиеся строки и рассчитать агрегатные функции (такие как сумма, максимум или количество). Если мы используем группировку в запросе без агрегатных функций, мы просто отсекаем детальные записи. Для СКД такой «свернутый» запрос вреден, поскольку компоновщик лишается возможности самостоятельно обходить детальные записи, строить по ним иерархию и правильно рассчитывать итоги на уровнях папок.
  2. Группировки в настройках компоновки данных (СКД): Механизм СКД представляет собой мощный аналитический процессор. Ему необходимо передать максимально плоскую и детальную выборку из базы данных. А уже на уровне настроек компоновщика мы указываем, по каким полям нужно сгруппировать данные визуально и как построить дерево иерархии.

Проанализируем типичный ошибочный запрос, в котором разработчик пытается вручную вытащить родительские группы номенклатуры:


ВЫБРАТЬ
    ЦеныНоменклатурыСрезПоследних.Номенклатура.Код КАК НоменклатураКод,
    ЦеныНоменклатурыСрезПоследних.ТипЦен КАК ТипЦен,
    ЦеныНоменклатурыСрезПоследних.Валюта КАК Валюта,
    ЦеныНоменклатурыСрезПоследних.Цена КАК Цена,
    ЦеныНоменклатурыСрезПоследних.Номенклатура.Наименование КАК НоменклатураНаименование,
    ЦеныНоменклатурыСрезПоследних.Номенклатура.Родитель.Наименование КАК НоменклатураРодительНаименование
ИЗ
    РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК ЦеныНоменклатурыСрезПоследних
СГРУППИРОВАТЬ ПО
    ЦеныНоменклатурыСрезПоследних.Номенклатура.Код,
    ЦеныНоменклатурыСрезПоследних.ТипЦен,
    ЦеныНоменклатурыСрезПоследних.Валюта,
    ЦеныНоменклатурыСрезПоследних.Цена,
    ЦеныНоменклатурыСрезПоследних.Номенклатура.Наименование,
    ЦеныНоменклатурыСрезПоследних.Номенклатура.Родитель.Наименование

Этот запрос выбирает данные только по тем элементам номенклатуры, для которых в регистре сведений ЦеныНоменклатуры установлена цена. При этом поле Номенклатура.Родитель.Наименование вернет наименование лишь непосредственного родителя (на один уровень вверх). Если у вас сложная структура с вложенностью в три-четыре уровня, данный запрос не сможет отобразить всю цепочку папок. Конструкция СГРУППИРОВАТЬ ПО здесь лишняя, так как в ней нет агрегатных функций.

Шаг 1. Создаем правильный плоский запрос для СКД

Для того чтобы СКД могла самостоятельно выстроить красивое дерево категорий, нам нужно передать ей ссылку на саму номенклатуру, а не строковое наименование ее родителя. Перепишем запрос, убрав из него все конструкции группировок СУБД:


ВЫБРАТЬ
    ЦеныНоменклатурыСрезПоследних.Номенклатура КАК Номенклатура,
    ЦеныНоменклатурыСрезПоследних.Номенклатура.Код КАК Код,
    ЦеныНоменклатурыСрезПоследних.ТипЦен КАК ТипЦен,
    ЦеныНоменклатурыСрезПоследних.Валюта КАК Валюта,
    ЦеныНоменклатурыСрезПоследних.Цена КАК Цена
ИЗ
    РегистрСведений.ЦеныНоменклатуры.SрезПоследних(&Период, ) КАК ЦеныНоменклатурыСрезПоследних

В этом запросе мы получаем поле Номенклатура, которое содержит ссылку на элемент справочника. Ссылочный тип критически важен, так как СКД обращается к метаданным справочника Номенклатура и автоматически определяет родительские связи для каждого элемента.

Шаг 2. Настройка иерархической группировки в компоновщике

Теперь перейдем в конструктор схемы компоновки данных на вкладку «Настройки». Выполним пошаговую настройку для вывода дерева категорий:

  1. В окне «Структура настроек» (левая верхняя панель) удалим стандартную группировку «Детальные записи», если она создана по умолчанию.
  2. Нажмем кнопку добавления новой группировки и выберем поле Номенклатура.
  3. Обратим внимание на тип создаваемой группировки. По умолчанию СКД создает группировку с типом «Без иерархии». Нам необходимо дважды кликнуть по созданной группировке или открыть ее свойства и изменить тип на «Иерархия». Именно эта настройка заставит СКД автоматически выстроить структуру папок любой вложенности, включая верхние и промежуточные уровни групп номенклатуры.

Шаг 3. Решаем проблему «Цена выводится ниже строкой в одной колонке»

После включения иерархического режима вы можете столкнуться со следующей проблемой: СКД выводит наименование папки или товара, а значение цены отображается в этой же колонке, но строчкой ниже. Это выглядит неэстетично и мешает анализировать прайс-лист. Разберем по шагам несколько эффективных способов решения этой проблемы.

Способ А. Настройка расположения реквизитов

По умолчанию СКД воспринимает поле Цена как дополнительный реквизит группировки Номенклатура. В системе компоновки установлено стандартное правило: выводить реквизиты вместе с владельцем в одной ячейке или под ней. Чтобы разделить их по разным колонкам, выполним следующие настройки:

  1. Перейдем на вкладку «Настройки» в конструкторе СКД.
  2. Выберем самый верхний уровень настроек — строку «Отчет».
  3. В правой нижней части экрана перейдем на вкладку «Другие настройки».
  4. Найдем параметр «Расположение реквизитов».
  5. Изменим его значение по умолчанию на «Отдельно».

После этого изменения все сопутствующие реквизиты номенклатуры (код, артикул, цена, валюта) автоматически распределятся по собственным индивидуальным колонкам справа от дерева иерархии.

Способ Б. Объявление поля «Цена» ресурсом СКД

В методологии построения отчетов 1С все числовые показатели, которые должны выводиться в итоговых таблицах или напротив группировок, принято делать ресурсами. Если поле объявлено ресурсом, СКД по умолчанию всегда резервирует под него отдельный столбец в правой части таблицы.

Выполним процедуру назначения ресурса:

  1. В конструкторе СКД перейдем на вкладку «Ресурсы».
  2. Перетащим поле Цена из левой колонки доступных полей в правую таблицу ресурсов.
  3. В колонке «Выражение» СКД автоматически предложит функцию Сумма(Цена). Однако суммировать цены по иерархическим папкам не имеет математического смысла. Нам необходимо изменить выражение.
  4. Зададим выражение как Максимум(Цена) или Среднее(Цена). Также можно оставить расчет ресурса только по детальным записям, указав в параметре «Рассчитывать по...» конкретное поле Номенклатура (без иерархии), чтобы на уровне папок цена не рассчитывалась вовсе и оставалась пустой.

Способ В. Проверка свойств горизонтального расположения групп

Иногда разработчики пытаются логически объединить поля (например, цену и валюту) в общую категорию на вкладке «Выбранные поля», создавая для этого папки групп. Если вы пошли этим путем, убедитесь в правильности настроек отображения папки:

  1. Перейдем на вкладку «Настройки», выберем группировку и откроем вкладку «Выбранные поля».
  2. Если вы создали пользовательскую группу полей, кликнем по ней правой кнопкой мыши и откроем ее свойства.
  3. Найдем свойство «Расположение». По умолчанию там может быть установлено значение Вертикально. При такой настройке все элементы внутри группы будут складываться друг под друга внутри одной колонки.
  4. Установим значение «Горизонтально» или «Вместе». В этом случае поля внутри группы будут аккуратно выстроены в ряд по горизонтали.

Шаг 4. Оптимизация запроса для красивого прайс-листа

При выводе прайс-листа напрямую из виртуальной таблицы СрезПоследних регистра сведений возникает логическая коллизия: в регистре хранятся записи только для конечных элементов справочника Номенклатура (для товаров). Пустые папки справочника, в которых нет товаров с установленными ценами, СКД попытается достроить сама, но структура дерева может получиться рваной или содержать лишние пустые группы.

Рассмотрим более профессиональный и чистый вариант построения запроса. Мы выберем всю структуру справочника номенклатуры, исключая группы на уровне СУБД, а цены подтянем с помощью левого соединения. Это позволит вывести только актуальные папки и элементы, имеющие иерархическую структуру:


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Номенклатура,
    Номенклатура.Код КАК Код,
    ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) КАК Цена,
    ЦеныНоменклатурыСрезПоследних.Валюта КАК Валюта,
    ЦеныНоменклатурыСрезПоследних.ТипЦен КАК ТипЦен
ИЗ
    Справочник.Номенклатура КАК Номенклатура
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ТипЦен = &ТипЦен) КАК ЦеныНоменклатурыСрезПоследних
        ПО ЦеныНоменклатурыСрезПоследних.Номенклатура = Номенклатура.Ссылка
ГДЕ
    НЕ Номенклатура.ЭтоГруппа
    И НЕ Номенклатура.ПометкаУдаления

Проанализируем преимущества этой схемы запроса:

Применяя описанные методики работы с компоновщиком данных и разделяя зоны ответственности между СУБД (выборка детальных данных) и СКД (структурирование, расчет иерархии и оформление), мы получаем гибкий, быстродействующий и визуально понятный прайс-лист для конечных пользователей системы 1С.

← На главную