При работе с кросс-таблицами в системе компоновки данных (СКД) разработчики часто сталкиваются с задачей упорядочивания строк. Типичная ситуация: в строках у нас находятся разрезы аналитики (например, Статья, Номенклатура, Контрагент), а в колонках — Период. Стандартная сортировка по ресурсу часто работает некорректно, так как СКД пытается сортировать строки по значениям в конкретных колонках периодов, а не по общему итогу строки. В этой статье мы подробно разберем, как добиться правильного поведения отчета и отсортировать данные по итоговой сумме за все периоды.
Давайте проанализируем ситуацию. Когда мы создаем кросс-таблицу, СКД рассчитывает ресурс для каждого пересечения строки и колонки. Если мы просто укажем в настройках группировки Контрагент сортировку по полю СуммаФакт, система может вести себя непредсказуемо. Она может отсортировать данные по первому периоду, по последнему или вовсе выдать случайный порядок. Это происходит потому, что для одной строки (одного контрагента) существует множество значений ресурса — по одному на каждый период.
Для корректного упорядочивания нам нужно создать такое поле, которое будет содержать одинаковое значение для всех колонок внутри одной строки — общую сумму за весь период отчета. Рассмотрим два основных способа решения этой задачи.
Функция ВычислитьВыражение — это мощный инструмент СКД, позволяющий получать значения из других уровней группировок или итогов. Чтобы получить общую сумму по строке для использования в сортировке, выполним следующие шаги:
СуммаДляСортировки.СуммаДляСортировки в список ресурсов.
ВычислитьВыражение("Сумма(СуммаФакт)", "ПериодПланирования", "ОбщийИтог")
Здесь мы указываем системе, что нужно просуммировать СуммаФакт по всей группировке ПериодПланирования (наши колонки), используя контекст общего итога.СуммаДляСортировки.Важный нюанс: при использовании ВычислитьВыражение с параметром "ОбщийИтог", система будет учитывать только те данные, которые попали в выборку после наложения всех отборов СКД. Это именно то, что нужно пользователю для получения актуальной картины.
Выясним причину, по которой этот способ часто оказывается проще и надежнее. В СКД на вкладке Ресурсы есть колонка Рассчитывать по.... По умолчанию ресурсы рассчитываются по всем доступным группировкам, включая колонки кросс-таблицы. Но мы можем это изменить.
Рассмотрим пошагово этот алгоритм:
СуммаФакт.СуммаФакт.Что это дает? Теперь для группировки Контрагент значение ресурса в каждой ячейке (даже внутри колонок периодов) будет равно итогу по этому контрагенту за все время. Поскольку значение теперь константно в рамках строки, сортировка СКД отработает безупречно.
В современных версиях платформы 1С (начиная с 8.3.14) мы можем использовать еще более гибкий метод. Если структура отчета сложная и включает иерархию, лучше применить агрегатную функцию над массивом:
Пример выражения для ресурса:
Сумма(ВычислитьВыражениеСГруппировкойМассив("Сумма(СуммаФакт)", "Контрагент"))
Этот метод позволяет корректно собирать суммы даже в тех случаях, когда стандартные итоги могут «разваливаться» из-за сложных отборов или специфических настроек иерархии группировок.
1. Вторая сортировка для стабильности. Проанализируем ситуацию: у двух контрагентов абсолютно одинаковые суммы. В этом случае СКД может перемешивать их при каждом формировании отчета. Чтобы этого избежать, всегда добавляйте второе поле в сортировку (например, Наименование или Ссылка). Это обеспечит стабильный и предсказуемый результат.
2. Скрытые поля. Если вы не хотите, чтобы служебное поле СуммаДляСортировки отображалось в отчете и путало пользователя, просто не добавляйте его в «Выбранные поля» в настройках. СКД все равно выполнит расчет этого ресурса, так как он задействован в механизме упорядочивания.
3. Влияние иерархии. Если у вас включена иерархия по строкам, помните, что сортировка по умолчанию применяется внутри каждого уровня. Если вы хотите, чтобы группы (папки) с наибольшими оборотами всегда были вверху, убедитесь, что ваше выражение для сортировки корректно рассчитывается и для родительских записей. В настройках сортировки группировки проверьте активность флага «Использовать в иерархии».
Важно помнить, что использование функций ВычислитьВыражение в ресурсах на очень больших объемах данных (десятки тысяч строк и сотни колонок) может замедлить формирование отчета. Если вы заметили существенные задержки, рассмотрим вариант переноса расчета итогов на уровень запроса. С помощью оконных функций SQL (в 1С это можно реализовать через дополнительные временные таблицы и соединения) можно заранее рассчитать итог по строке. В СКД вы получите уже готовое число, по которому сортировка будет выполняться мгновенно.
Разберем пример структуры такого запроса:
ВЫБРАТЬ
Продажи.Контрагент КАК Контрагент,
Продажи.Сумма КАК Сумма,
СуммыПоКонтрагентам.ОбщийИтог КАК ОбщийИтогПоСтроке
ИЗ
РегистрНакопления.Продажи КАК Продажи
ЛЕВОЕ СОЕДИНЕНИЕ (
ВЫБРАТЬ
Контрагент,
СУММА(Сумма) КАК ОбщийИтог
ИЗ
РегистрНакопления.Продажи
СГРУППИРОВАТЬ ПО Контрагент
) КАК СуммыПоКонтрагентам ПО Продажи.Контрагент = СуммыПоКонтрагентам.Контрагент
При таком подходе в СКД вам достаточно будет просто выбрать поле ОбщийИтогПоСтроке в качестве поля для упорядочивания в настройках группировки.