При разработке отчетов и обработок часто возникает задача: пользователь задает произвольный интервал дат (например, с 15 января по 10 марта), а данные необходимо сгруппировать или обработать поотдельности за каждый календарный месяц, входящий в этот диапазон. Рассмотрим подробнее, как решить эту задачу различными инструментами платформы 1С: с помощью языка запросов, системы компоновки данных (СКД) и программного кода.
Рассмотрим ситуацию, когда пользователь указывает интервал, не совпадающий со строгими границами месяцев. В этом случае корректное разбиение должно учитывать неполные месяцы:
Выясним, какие механизмы платформы позволяют автоматизировать или описать этот процесс.
Платформа 1С содержит встроенный инструмент генерации временных интервалов. В секции итогов запроса можно применить конструкцию ПЕРИОДАМИ.
Рассмотрим пример построения запроса:
ВЫБРАТЬ
Продажи.Период КАК Период,
Продажи.Сумма КАК Сумма
ИЗ
РегистрНакопления.Продажи КАК Продажи
ГДЕ
Продажи.Период МЕЖДУ &ДатаНач И &ДатаКон
ИТОГИ
СУММА(Сумма)
ПО
Период ПЕРИОДАМИ(МЕСЯЦ, &ДатаНач, &ДатаКон)
При использовании конструкции ПЕРИОДАМИ(МЕСЯЦ, &ДатаНач, &ДатаКон) система автоматически сформирует помесячные интервалы от начальной до конечной даты, даже если за отдельные месяцы в базе данных отсутствуют движения.
Важное ограничение: метод Запрос.Выполнить().Выгрузить() не сохраняет дополненные пустые периоды при прямой выгрузке в таблицу значений. Чтобы получить все месяцы (включая периоды без данных), необходимо использовать иерархический обход выборки через Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам, "Период", "ВСЕ").
Если требуется объединить данные с календарем без использования группировок итогов, разберем два варианта:
НАЧАЛОПЕРИОДА(ТаблицаКалендаря.Дата, "МЕСЯЦ") и отбирая уникальные значения за указанный диапазон.ОБЪЕДИНИТЬ ВСЕ) и прибавить полученное количество месяцев к начальной дате функцией ДОБАВИТЬКДАТЕ(&ДатаНач, МЕСЯЦ, Индекс). Количество итераций рассчитывается с помощью функции РАЗНОСТЬДАТ(&ДатаНач, &ДатаКон, МЕСЯЦ).Если задача решается в рамках отчета на Системе компоновки данных (СКД), писать сложные запросы или код не требуется. Платформа предоставляет штатный механизм дополнения периодов.
Разберем настройки СКД по шагам:
НАЧАЛОПЕРИОДА(Дата, "МЕСЯЦ").&ДатаНач и &ДатаКон).СКД автоматически сформирует за каждый месяц строки или колонки, даже если реальных записей в этот период не было. Для практической реализации подобной структуры группировки подойдёт пример настройки шапки отчета по месяцам и неделям в СКД.
Проанализируем задачу, когда периоды нужно получить в виде массива или таблицы значений в коде модуля без выполнения сложных запросов. Для этого организуем цикл по месяцам.
Посмотрим на пример алгоритма:
МассивПериодов = Новый Массив;
ТекущаяДата = НачалоДня(ДатаНач);
ДатаОкончания = КонецДня(ДатаКон);
Пока ТекущаяДата <= ДатаОкончания Цикл
// Определяем начало и конец текущего месяца в интервале
НачалоМесяцаИнтервала = Макс(ТекущаяДата, НачалоМесяца(ТекущаяДата));
КонецМесяцаИнтервала = Мин(ДатаОкончания, КонецМесяца(ТекущаяДата));
// Фиксируем полученный интервал
СтруктураПериода = Новый Структура;
СтруктураПериода.Вставить("ДатаНачала", НачалоМесяцаИнтервала);
СтруктураПериода.Вставить("ДатаОкончания", КонецМесяцаИнтервала);
МассивПериодов.Добавить(СтруктураПериода);
// Переходим к следующему месяцу
ТекущаяДата = НачалоМесяца(ДобавитьМесяц(ТекущаяДата, 1));
КонецЦикла;
Данный алгоритм корректно обрабатывает как полные, так и граничные неполные месяцы, добавляя в массив структуры с точными датами начала и окончания каждого интервала.
При работе с виртуальными таблицами регистров (например, РегистрНакопления.Продажи.Обороты) передача параметра периодичности Месяц возвращает данные только по тем периодам, в которых совершались реальные движения. Месяцы с нулевыми оборотами не попадут в выборку. Для получения полной картины без пропусков рекомендуем использовать механизмы дополнения периодов СКД или объединение результатов с таблицей календаря. Для генерации последовательности периодов в запросе можно использовать варианты построения выборки диапазона дат и чисел.