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

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

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

Проблема стандартного подхода

Рассмотрим ситуацию: у нас есть группировка ФизЛицо, а внутри нее — РасчетныйДокумент. Если мы просто установим отбор в настройках группировки ФизЛицо с условием СуммаКонечныйОстаток <> 0, система скроет заголовок группировки, но может оставить «висеть» в отчете детальные записи (документы), так как условие отбора проверяется для каждой строки отдельно. Нам же нужно, чтобы фильтр действовал иерархически: если «родитель» не прошел ценз, «дети» также не должны попадать в отчет.

Проанализируем основные способы решения этой задачи, от оптимизации запроса до тонкой настройки вычисляемых полей компоновки.

Способ 1. Предварительная фильтрация во временных таблицах

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

Разберем по шагам алгоритм реализации в тексте запроса:

  1. Создадим первый запрос в пакете, который выбирает данные в разрезе нашей основной группировки (например, ФизЛицо) и рассчитывает итоговый остаток.
  2. Поместим этот результат во временную таблицу, наложив условие ГДЕ СуммаОстатка <> 0.
  3. Во втором (основном) запросе выберем детальные данные (документы), соединив их внутренним соединением с нашей временной таблицей по полю ФизЛицо.

Посмотрим на пример структуры такого запроса:


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

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

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

Способ 2. Использование функции ВычислитьВыражение в вычисляемых полях

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

Рассмотрим подробнее этот механизм:

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

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

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

Способ 3. Передача ресурса в отбор вложенной группировки

Еще один вариант, который часто обсуждается разработчиками: установка отбора непосредственно по ресурсу. Разберем ситуацию: у нас есть ресурс СуммаОстаток.

В настройках СКД на вкладке Настройки выберем группировку ФизЛицо. Перейдем на ее личную вкладку Отбор и добавим условие СуммаОстаток <> 0. Важно понимать, что для того, чтобы документы тоже скрылись, этот же отбор нужно продублировать и для вложенной группировки РасчетныйДокумент.

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

Проблема «исчезающих» полей и Автозаполнение

При реализации сложных отборов в запросах программисты часто сталкиваются с тем, что СКД «режет» текст запроса. Вы прописываете поле в ВЫБРАТЬ, но в отчете его нет. Выясним причину этого поведения.

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

Визуальное скрытие через Условное оформление

Если расчеты очень сложные и отборы не срабатывают так, как нужно, проанализируем «визуальный» метод. Он не удаляет данные из выборки, но делает их невидимыми для пользователя.

Посмотрим на алгоритм настройки:

  1. В настройках отчета перейдем на вкладку Условное оформление.
  2. Добавим новое условие оформления. В качестве оформления выберем параметр Видимость = Ложь.
  3. В условии укажем: СуммаОстаток = 0.
  4. В области использования укажем те группировки, которые нужно скрыть.

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

Итоги и рекомендации

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

1. Если отчет строится по большим таблицам (регистры бухгалтерии, крупные регистры накопления) — используйте Способ 1 (Временные таблицы). Это обеспечит максимальную скорость работы.

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

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

Совместное использование этих техник позволит вам создавать профессиональные и удобные отчеты, в которых пользователь будет видеть только значимую информацию без «нулевого» шума.

← На главную