Как вывести независимые строки для каждой колонки в отчете СКД (Рейтинг по периодам)

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

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

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

В чем заключается основная сложность?

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

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

Способ 1. Использование «Искусственного номера строки» в запросе

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

Если ваша база данных и платформа (8.3.20+) поддерживают оконные функции, запрос будет выглядеть максимально лаконично. Рассмотрим пример логики запроса:


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

Если же вы работаете на более старых версиях платформы, где прямая поддержка оконных функций в языке запросов отсутствует, придется использовать соединение таблицы самой с собой. Мы выясним причину, почему это работает: сравнивая таблицу Т1 с таблицей Т2 по условию Т1.Сумма <= Т2.Сумма внутри одного месяца, мы можем посчитать количество записей, которые «лучше» текущей, и таким образом получить порядковый номер.

Настройка структуры СКД для этого метода:

  1. В поле «Группировки строк» добавьте созданное поле Рейтинг (или НомерСтроки).
  2. В поле «Группировки колонок» добавьте Месяц.
  3. Поля Контрагент и Сумма обязательно добавьте в Ресурсы.
  4. Для ресурса Контрагент в выражении укажите Максимум(Контрагент). Это позволит вывести текстовое название клиента в ячейку на пересечении рейтинга и месяца.

Способ 2. Программная подготовка данных через Таблицу Значений

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

Разберем по шагам, как это сделать в коде:

  1. Выгружаем результат обычного запроса по продажам в ТаблицуЗначений.
  2. Добавляем в таблицу колонку ПорядокСортировки (тип Число).
  3. Сортируем таблицу: сначала по периоду (возрастание), затем по сумме (убывание).
  4. Запускаем цикл и присваиваем индекс каждой строке, обнуляя счетчик при смене месяца.

Посмотрим на пример кода:


ТаблицаДанных.Сортировать("Период Возр, Сумма Убыв");

ТекущийМесяц = Неопределено;
Счетчик = 0;

Для Каждого Строка Из ТаблицаДанных Цикл
    Если Строка.Период <> ТекущийМесяц Тогда
        ТекущийМесяц = Строка.Период;
        Счетчик = 1;
    Иначе
        Счетчик = Счетчик + 1;
    КонецЕсли;
    Строка.ПорядокСортировки = Счетчик;
КонецЦикла;

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

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

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

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

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

Важные визуальные настройки и ограничения

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

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

Резюме

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

← На главную