Как настроить сортировку строк по значениям в колонках периодов в отчете СКД

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

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

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

Почему стандартная сортировка не всегда работает в кросс-таблицах

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

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

Решение 1: Статическое разделение периодов в запросе

Если количество периодов заранее известно (например, отчет всегда строится за квартал или год), мы можем подготовить специальные поля для сортировки непосредственно в тексте запроса. Разберем этот пример на основе выручки по месяцам.

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


ВЫБРАТЬ
    Т.Период КАК Период,
    Т.Контрагент КАК Контрагент,
    Т.СтоимостьОборот КАК СтоимостьОборот,
    ВЫБОР КОГДА МЕСЯЦ(Т.Период) = 1 ТОГДА Т.СтоимостьОборот ИНАЧЕ 0 КОНЕЦ КАК СуммаМесяц1,
    ВЫБОР КОГДА МЕСЯЦ(Т.Период) = 2 ТОГДА Т.СтоимостьОборот ИНАЧЕ 0 КОНЕЦ КАК СуммаМесяц2,
    ВЫБОР КОГДА МЕСЯЦ(Т.Период) = 3 ТОГДА Т.СтоимостьОборот ИНАЧЕ 0 КОНЕЦ КАК СуммаМесяц3
ИЗ
    РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты(&НачалоПериода, &КонецПериода, Месяц, ) КАК Т

После этого в СКД необходимо выполнить следующие действия:

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

В этом случае система сначала выстроит партнеров по продажам января. Если у нескольких партнеров продажи в январе одинаковы (или равны нулю), они будут отсортированы по продажам февраля.

Решение 2: Использование математического индекса в вычисляемых полях

Первый способ неудобен, если периодов много или они постоянно меняются. Рассмотрим более универсальный метод — создание "синтетического" поля упорядочивания. Суть метода заключается в том, чтобы присвоить каждому факту продажи "вес", зависящий от даты.

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


РАЗНОСТЬДАТ(ВыручкаИСебестоимостьПродажОбороты.Период, &КонецПериода, МЕСЯЦ) + 
СУММА(ЕСТЬNULL(ВыручкаИСебестоимостьПродажОбороты.СуммаВыручкиОборот, 0)) / 1000000000

Рассмотрим, как это работает по шагам:

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

Важный момент: использование ЕСТЬNULL критически важно, чтобы отсутствие данных не привело к пустому результату всего выражения, что нарушит логику сортировки.

Решение 3: Строковый метод формирования веса (универсальный)

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

Создадим вычисляемое поле ПолеУпорядочивания со следующим выражением:


ВЫБОР 
    КОГДА ЕСТЬNULL(Сумма, 0) <> 0 
    ТОГДА Формат(Период, "ДФ=yyyyMMdd") 
    ИНАЧЕ "00000000" 
КОНЕЦ + Формат(Сумма, "ЧЦ=20; ЧВН=; ЧГ=0")

Разберем логику этого решения:

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

Решение 4: Программная подготовка данных (Набор данных Объект)

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

Посмотрим на алгоритм реализации:

  1. Выполняем запрос к данным программно в коде модуля отчета.
  2. Выгружаем результат в ТаблицаЗначений.
  3. В этой таблице создаем колонку ИндексСортировки и заполняем её по любому сложному алгоритму на языке 1С.
  4. Сортируем таблицу значений методами ТаблицаЗначений.Сортировать().
  5. Передаем готовую таблицу в СКД через Набор данных - объект.

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

Рекомендации по тонкой настройке

Проанализируем еще несколько важных технических моментов, которые помогут избежать ошибок:

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

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

3. Использование "Значений группировок" в настройках:
В последних версиях платформы 8.3 в окне настроек сортировки для группировки строк можно нажать кнопку выбора и указать конкретное значение из группировки колонок. Например, выбрать "Выручка" и в параметрах указать конкретную дату. Это работает, если вы хотите жестко отсортировать весь отчет только по одному конкретному месяцу (например, текущему).

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

← На главную