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

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

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

Метод 1: Использование языка запросов и виртуальных таблиц

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

Во-первых, мы можем воспользоваться функцией ДЕНЬНЕДЕЛИ(). В языке запросов 1С понедельник соответствует значению 1. Если нам нужно получить данные из регистра накопления (например, остатки долга) по дням, мы можем обратиться к виртуальной таблице ОстаткиИОбороты с периодичностью День.

Проанализируем пример запроса, который выбирает данные только за понедельники:


ВЫБРАТЬ
    ВзаиморасчетыОстаткиИОбороты.ТорговаяТочка КАК ТорговаяТочка,
    ВзаиморасчетыОстаткиИОбороты.Период КАК Период,
    ВзаиморасчетыОстаткиИОбороты.СуммаДолгаОстаток КАК СуммаДолга
ИЗ
    РегистрНакопления.Взаиморасчеты.ОстаткиИОбороты(&ДатаНач, &ДатаКон, День, , ) КАК ВзаиморасчетыОстаткиИОбороты
ГДЕ
    ДЕНЬНЕДЕЛИ(ВзаиморасчетыОстаткиИОбороты.Период) = 1

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

Метод 2: Программное формирование внешнего набора данных

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

Рассмотрим алгоритм формирования таблицы значений с понедельниками:

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

Пример программного кода для передачи данных:


Процедура ПриКомпоновкеРезультата(ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // 1. Генерируем таблицу данных (ТЗ_Данные)
    ТЗ_Данные = ПолучитьТаблицуДолговПоПонедельникам(); 
    
    // 2. Подготавливаем внешние наборы данных
    ВнешниеНаборыДанных = Новый Структура;
    ВнешниеНаборыДанных.Вставить("ТаблицаПонедельников", ТЗ_Данные);
    
    // 3. Выполняем стандартную компоновку
    СхемаКомпоновкиДанных = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();
    
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(Результат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
КонецПроцедуры

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

Настройка кросс-таблицы для вывода динамических колонок

Чтобы даты (понедельники) выводились в колонки, а не в строки, необходимо правильно настроить вкладку Настройки в консоли СКД. Выясним, как это сделать:

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

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

Расчет среднего значения по строке

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

Для корректного расчета среднего объема по горизонтали (между понедельниками) используем возможности вкладок Ресурсы. Вместо простого Среднее(СуммаПДЗ), мы можем применить функцию ВычислитьВыражениеСГруппировкойТаблица. Это позволит нам сначала просуммировать данные внутри каждого понедельника, а затем вычислить среднее среди этих сумм.

Пример выражения для ресурса "Средний объем ПДЗ":

Среднее(ВычислитьВыражениеСГруппировкойТаблица("Сумма(СуммаПДЗ)", "Период"))

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

Советы по оптимизации

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

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

← На главную