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

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

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

Проблема простой группировки по периоду

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

Способ 1. Связи наборов данных и передача параметров

Это самый профессиональный и гибкий метод. Мы разделим отчет на два независимых набора данных. Рассмотрим этот процесс по шагам.

Шаг 1. Создание набора данных "Периоды"

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


ВЫБРАТЬ 0 КАК Цифра ПОМЕСТИТЬ ТабЦифр ОБЪЕДИНИТЬ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВЫБРАТЬ 3 
ОБЪЕДИНИТЬ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВЫБРАТЬ 9;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, т1.Цифра + 10 * т2.Цифра), МЕСЯЦ) КАК МесяцНачало,
    КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, т1.Цифра + 10 * т2.Цифра), МЕСЯЦ) КАК МесяцКонец
ИЗ
    ТабЦифр КАК т1,
    ТабЦифр КАК т2
ГДЕ
    ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, т1.Цифра + 10 * т2.Цифра) <= &ДатаОкончания

Шаг 2. Создание основного набора данных "Данные"

Во втором наборе данных пишем наш основной запрос. Главное условие: он должен принимать параметры &НачалоМесяца и &КонецМесяца в условиях ГДЕ или в параметрах виртуальных таблиц.

Шаг 3. Настройка связи наборов

Перейдем на вкладку Связи наборов данных. Проанализируем настройки:

  1. Источник связи: Периоды.
  2. Приемник связи: Данные.
  3. В колонке Параметры укажем связь: поле МесяцНачало передается в параметр НачалоМесяца, а МесяцКонец — в КонецМесяца.

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

Способ 2. Дополнение периодов средствами СКД

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

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

  1. Нажмите на многоточие в колонке Роль.
  2. Установите флажок Обязательное.
  3. В поле Тип дополнения выберите Месяц.
  4. Укажите параметры начала и конца периода (обычно это стандартные параметры отчета).

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

Способ 3. Использование периодичности виртуальных таблиц

Рассмотрим ситуацию, когда данные берутся из регистров накопления или бухгалтерии. Посмотрим на параметры виртуальных таблиц Обороты или ОстаткиИОбороты. Проанализируем параметр Периодичность.

Если установить значение Месяц, система автоматически добавит в выборку поле Период, которое всегда будет равно началу месяца. Это наиболее производительный способ, так как платформа сама оптимизирует запрос подневного или помесячного разбиения.

Пример обращения к такой таблице:


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

Как обеспечить правильную сортировку

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

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

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

← На главную