Как в СКД отсортировать строки кросс-таблицы по итоговому значению ресурса?

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

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

Разбор проблемы: почему стандартная сортировка «ломается»?

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

Для корректного упорядочивания нам нужно создать такое поле, которое будет содержать одинаковое значение для всех колонок внутри одной строки — общую сумму за весь период отчета. Рассмотрим два основных способа решения этой задачи.

Способ 1: Использование функции ВычислитьВыражение

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

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

Важный нюанс: при использовании ВычислитьВыражение с параметром "ОбщийИтог", система будет учитывать только те данные, которые попали в выборку после наложения всех отборов СКД. Это именно то, что нужно пользователю для получения актуальной картины.

Способ 2: Настройка области расчета ресурса («Рассчитывать по...»)

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

Рассмотрим пошагово этот алгоритм:

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

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

Продвинутый метод: ВычислитьВыражениеСГруппировкойМассив

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

Пример выражения для ресурса:

Сумма(ВычислитьВыражениеСГруппировкойМассив("Сумма(СуммаФакт)", "Контрагент"))

Этот метод позволяет корректно собирать суммы даже в тех случаях, когда стандартные итоги могут «разваливаться» из-за сложных отборов или специфических настроек иерархии группировок.

Практические советы по тонкой настройке

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

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

3. Влияние иерархии. Если у вас включена иерархия по строкам, помните, что сортировка по умолчанию применяется внутри каждого уровня. Если вы хотите, чтобы группы (папки) с наибольшими оборотами всегда были вверху, убедитесь, что ваше выражение для сортировки корректно рассчитывается и для родительских записей. В настройках сортировки группировки проверьте активность флага «Использовать в иерархии».

Оптимизация производительности

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

Разберем пример структуры такого запроса:


ВЫБРАТЬ
    Продажи.Контрагент КАК Контрагент,
    Продажи.Сумма КАК Сумма,
    СуммыПоКонтрагентам.ОбщийИтог КАК ОбщийИтогПоСтроке
ИЗ
    РегистрНакопления.Продажи КАК Продажи
ЛЕВОЕ СОЕДИНЕНИЕ (
    ВЫБРАТЬ
        Контрагент,
        СУММА(Сумма) КАК ОбщийИтог
    ИЗ
        РегистрНакопления.Продажи
    СГРУППИРОВАТЬ ПО Контрагент
) КАК СуммыПоКонтрагентам ПО Продажи.Контрагент = СуммыПоКонтрагентам.Контрагент

При таком подходе в СКД вам достаточно будет просто выбрать поле ОбщийИтогПоСтроке в качестве поля для упорядочивания в настройках группировки.

← На главную