Как настроить вывод группировки в СКД по условию с сохранением всех подчиненных элементов?

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

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

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

---

Почему стандартный отбор работает неправильно?

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

Рассмотрим детально три надежных метода решения этой проблемы.

---

Способ 1. Настройка отбора на уровне конкретной группировки в СКД

Это самый быстрый и гибкий способ, который не требует изменения текста запроса и позволяет сохранить возможность пользовательской настройки отчета. Вся магия кроется в свойствах применения отбора для конкретной ветки группировки.

Разберем этот метод по шагам:

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

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

---

Способ 2. Оптимизация на уровне SQL-запроса (для высоконагруженных систем)

Если отчет строится по регистру с миллионами записей, первый способ может вызвать просадку производительности. СКД будет вынуждена тянуть из базы данных огромный объем информации, выполнять группировку в оперативной памяти сервера приложений и лишь затем отбрасывать ненужные ветки. Чтобы оптимизировать этот процесс, перенесем логику фильтрации на уровень СУБД с помощью пакета запросов. При работе с такими масштабами данных в 1С:ERP также можно выполнить многопоточную свёртку базы для сокращения исторических записей и ускорения системы.

Рассмотрим пример запроса, который решает задачу наиболее эффективно:


// ШАГ 1. Отбираем только те типы договоров, по которым есть расхождения ресурсов.
// Результат сохраняем во временную таблицу.
ВЫБРАТЬ
    Договоры.ТипДоговора КАК ТипДоговора
ПОМЕСТИТЬ ВТ_ПроблемныеТипы
ИЗ
    РегистрНакопления.Взаиморасчеты КАК Договоры
СГРУППИРОВАТЬ ПО
    Договоры.ТипДоговора
ИМЕЮЩИЕ
    СУММА(Договоры.СуммаУтверждено) <> СУММА(Договоры.СуммаВыполнено);

////////////////////////////////////////////////////////////////////////////////
// ШАГ 2. Выбираем ВСЕ детальные записи только по тем типам, которые попали в ВТ.
ВЫБРАТЬ
    Договоры.ТипДоговора КАК ТипДоговора,
    Договоры.Договор КАК Договор,
    Договоры.СуммаУтверждено КАК Утверждено,
    Договоры.СуммаВыполнено КАК Выполнено
ИЗ
    РегистрНакопления.Взаиморасчеты КАК Договоры
    // Внутреннее соединение гарантирует, что в выборку попадут только нужные группы,
    // но со всеми своими детальными записями без ограничений.
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ПроблемныеТипы КАК ПроблемныеТипы
        ПО Договоры.ТипДоговора = ПроблемныеТипы.ТипДоговора

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

---

Способ 3. Использование признака (флага) расхождения в запросе

Еще один красивый вариант реализации — добавление вычисляемого признака непосредственно в текст основного запроса. Этот метод хорош тем, что позволяет легко управлять выводом группировок через стандартный интерфейс настроек ресурсов.

Добавим в текст запроса вычисляемое поле:


ВЫБРАТЬ
    Договоры.ТипДоговора КАК ТипДоговора,
    Договоры.Договор КАК Договор,
    Договоры.СуммаУтверждено КАК Утверждено,
    Договоры.СуммаВыполнено КАК Выполнено,
    ВЫБОР
        КОГДА Договоры.СуммаУтверждено <> Договоры.СуммаВыполнено ТОГДА 1
        ИНАЧЕ 0
    КОНЕЦ КАК ЕстьРасхождение
ИЗ
    РегистрНакопления.Взаиморасчеты КАК Договоры

Теперь выполним следующие действия в конструкторе СКД:

  1. Перейдем на вкладку «Ресурсы» и добавим поле ЕстьРасхождение со стандартным выражением агрегации Сумма(ЕстьРасхождение).
  2. В настройках структуры отчета для группировки ТипДоговора добавим отбор по условию: ЕстьРасхождение > 0.

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

---

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

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

Схема реализации выглядит следующим образом:

  1. Перейдите на вкладку «Вычисляемые поля» схемы СКД.
  2. Добавьте новое поле с именем ГруппаТребуетВнимания.
  3. В колонку «Выражение» вставьте следующую конструкцию:
    
    ВычислитьВыражениеСГруппировкойМассив(
        "Максимум(Выбор Когда Утверждено <> Выполнено Тогда Истина Иначе Ложь Конец)", 
        "ТипДоговора"
    )
    
  4. Обязательно укажите для этого вычисляемого поля назначение — «Для отбора» в свойствах поля.
  5. В настройках группировки установите отбор: ГруппаТребуетВнимания Равно Истина.

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

---

Дополнительный кейс: Как скрыть детальные записи, но сохранить полные суммы в итогах?

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

Для реализации этого сценария воспользуемся механизмом Условного оформления СКД:

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

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

← На главную