Как в СКД вывести значение ресурса только в одной строке и обеспечить правильный расчет итогов

Программист 1С v8.3 (Управляемые формы)
← На главную

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

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

Метод 1. Соединение таблиц в запросе (подход из обсуждения)

Рассмотрим подробнее решение, предложенное в обсуждении. Суть его заключается в том, чтобы искусственно «привязать» значение ресурса только к одной строке из набора данных еще на уровне формирования таблиц в SQL-запросе. Выясним причину, по которой это работает: если мы соединим основную таблицу товаров с таблицей, где ресурс указан только для одной уникальной комбинации «Реализация + Номенклатура», то в остальных строках поле останется пустым (NULL), и стандартная функция СУММА() в ресурсах СКД отработает корректно.

Разберем по шагам, как это реализовать в конструкторе запроса:

  1. Создаем временную таблицу (ВТ_Данные), в которую выбираем все необходимые поля: Заказ, Реализация, Номенклатура и сам Ресурс.
  2. Создаем вторую временную таблицу (ВТ_ПервыеСтроки), в которой для каждой реализации определяем «строку-носитель» ресурса. Это можно сделать, выбрав минимальную номенклатуру или используя номер строки из документа.
  3. В основном запросе объединяем эти таблицы левым соединением.

Пример реализации логики в коде запроса:


ВЫБРАТЬ
    ТЧ.Ссылка КАК Реализация,
    МИНИМУМ(ТЧ.НомерСтроки) КАК НомерПервойСтроки
ПОМЕСТИТЬ ВТ_Индексы
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК ТЧ
ГРУППИРОВАТЬ ПО
    ТЧ.Ссылка;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    РеализацияТовары.Ссылка.ЗаказНаряд КАК Заказ,
    РеализацияТовары.Ссылка КАК Реализация,
    РеализацияТовары.Номенклатура КАК Номенклатура,
    ВЫБОР
        КОГДА РеализацияТовары.НомерСтроки = ВТ_Индексы.НомерПервойСтроки
            ТОГДА РеализацияТовары.Ссылка.ПроцентСкидки
        ИНАЧЕ 0
    КОНЕЦ КАК ПроцентДляВывода
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Индексы КАК ВТ_Индексы
        ПО РеализацияТовары.Ссылка = ВТ_Индексы.Реализация

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

Метод 2. Использование функции ВычислитьВыражениеСГруппировкойМассив

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

Посмотрим на пример выражения ресурса. Вместо простой функции Сумма(Процент), перейдем на закладку «Ресурсы» и напишем для поля Процент следующее выражение:

Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(Процент)", "Реализация"))

Разберем, как это работает:

Таким образом, если в реализации 5 строк номенклатуры, СКД не сложит процент 5 раз, а возьмет его единожды для этой реализации и прибавит к итогу по Заказу. Для визуального скрытия «дублей» в детальных строках этот метод можно дополнить условным оформлением, которое будет скрывать текст, если текущая строка не является первой в группировке.

Метод 3. Использование функции АвтономерЗаписи() и Вычисляемых полей

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

Рассмотрим алгоритм действий:

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

ВЫБОР КОГДА НомерСтроки = 1 ТОГДА Процент ИНАЧЕ 0 КОНЕЦ

Однако стоит помнить, что АВТОНОМЕРЗАПИСИ() работает глобально на весь отчет, а нам нужен номер внутри группы. Поэтому для реализации «номера внутри группы» на уровне запроса чаще всего используют соединение таблицы самой с собой по условию Т1.Ссылка = Т2.Ссылка И Т1.НомерСтроки > Т2.НомерСтроки.

Метод 4. Настройка ролей полей и игнорирование дублей

В СКД существует механизм управления итогами через закладку «Наборы данных» — «Роли». Для поля, по которому происходит дублирование (в нашем примере это Реализация), можно указать роль «Обязательное». Однако для решения задачи «вывода только в одной строке» этот механизм подходит меньше, чем предыдущие.

Интереснее выглядит использование агрегатной функции Максимум() вместо Сумма() в ресурсах. Если мы укажем:

Максимум(Процент)

...то в группировке по реализации мы увидим верное число. Но как только отчет дойдет до группировки «Заказ», Максимум выберет самый большой процент среди всех реализаций этого заказа, а не сложит их. Поэтому данный метод применим только в том случае, если итоговое суммирование по верхнему уровню не требуется.

Почему условное оформление — это не решение задачи?

Часто начинающие разработчики пытаются решить проблему через «Условное оформление», устанавливая белый цвет шрифта или текст « » для повторяющихся значений. Проанализируем, почему автор темы обоснованно отказался от этого пути:

Резюме

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

← На главную