При разработке отчетов по продажам или иным оборотам в системе компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда в выбранном периоде за некоторые месяцы нет данных. По умолчанию 1С не выводит пустые строки, что может исказить восприятие динамики или привести к некрасивому виду отчета. Рассмотрим подробно, как заставить систему отображать абсолютно все месяцы в заданном интервале, независимо от наличия в них выручки.
Это самый эффективный и «чистый» способ, который не требует написания громоздких запросов. Система компоновки данных сама умеет генерировать недостающие строки, если мы правильно укажем ей параметры дополнения. Разберем этот процесс по шагам.
Во-первых, проанализируем настройки группировок. Перейдем на закладку «Настройки» в схеме компоновки данных. Выберем нашу группировку по месяцу (например, поле ПериодМесяц). В нижней части экрана найдем вкладку «Дополнительные настройки» или «Иерархия группировки». Здесь нас интересуют следующие свойства:
Месяц. Это скажет системе, что если в данных есть пропуск, его нужно заполнить объектами этого типа.&НачалоПериода.&КонецПериода.Важный нюанс: Если не указать границы дополнения через параметры, СКД выполнит дополнение только внутри диапазона имеющихся данных. То есть, если первая продажа была в марте, а последняя в октябре, то январь и февраль не появятся, даже если в параметрах отчета стоит начало года. Именно поэтому привязка к параметрам &НачалоПериода и &КонецПериода критически важна.
Чтобы механизм дополнения работал корректно, система должна понимать природу поля. Выясним, как правильно настроить роли. На закладке «Наборы данных» найдем поле периода.
В колонке «Роль» нажмем на кнопку редактирования. В открывшемся окне укажем:
Месяц.Проанализируем ситуацию: после этих настроек СКД будет автоматически «дорисовывать» недостающие месяцы. Однако в колонках с суммами мы увидим пустоту (значения NULL).
Для того чтобы отчет выглядел профессионально, вместо пустых ячеек в месяцах без продаж должны стоять нули. Посмотрим на два варианта реализации этой задачи.
Вариант через запрос. В тексте запроса набора данных мы можем обернуть суммовые поля функцией ЕСТЬNULL. Посмотрим на пример:
ВЫБРАТЬ
ПродажиОбороты.ПериодМесяц КАК ПериодМесяц,
ЕСТЬNULL(ПродажиОбороты.СуммаОборот, 0) КАК Выручка
ИЗ
РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, Авто, ) КАК ПродажиОбороты
Вариант через ресурсы СКД. Рассмотрим более гибкий путь — настройку на вкладке «Ресурсы». Для поля «Выручка» в колонке «Выражение» напишем следующую конструкцию:
ЕстьNull(Сумма(Выручка), 0)
Это гарантирует, что даже если во временной строке, созданной механизмом дополнения, нет никаких записей, система подставит ноль при расчете итогов.
Если штатный механизм дополнения по какой-то причине не подходит (например, при сложных соединениях нескольких наборов данных), можно применить метод построения таблицы периодов в самом запросе. Выясним причину, почему это иногда необходимо: если виртуальная таблица Обороты возвращает абсолютно пустой результат (за весь период не было ни одной продажи), СКД иногда «не за что зацепиться» для начала дополнения.
Рассмотрим, как сгенерировать таблицу всех месяцев периода без использования реальных физических таблиц календаря. Мы можем использовать соединение системных таблиц с малым количеством записей, чтобы получить нужное число строк. Посмотрим на пример кода запроса:
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(&НачалоПериода, МЕСЯЦ, Цифры.Номер) КАК МесяцПериода
ПОМЕСТИТЬ ВТ_Календарь
ИЗ
(ВЫБРАТЬ
0 КАК Номер
ОБЪЕДИНИТЬ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВЫБРАТЬ 3
ОБЪЕДИНИТЬ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВЫБРАТЬ 6
ОБЪЕДИНИТЬ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВЫБРАТЬ 9
ОБЪЕДИНИТЬ ВЫБРАТЬ 10 ОБЪЕДИНИТЬ ВЫБРАТЬ 11) КАК Цифры
ГДЕ
ДОБАВИТЬКДАТЕ(&НачалоПериода, МЕСЯЦ, Цифры.Номер) <= &КонецПериода
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_Календарь.МесяцПериода КАК ПериодМесяц,
ЕСТЬNULL(ПродажиОбороты.СуммаОборот, 0) КАК Выручка
ИЗ
ВТ_Календарь КАК ВТ_Календарь
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, Месяц, ) КАК ПродажиОбороты
ПО ВТ_Календарь.МесяцПериода = ПродажиОбороты.ПериодМесяц
В данном примере мы создаем временную таблицу ВТ_Календарь, которая содержит все даты начала месяцев в выбранном диапазоне. Затем мы используем ЛЕВОЕ СОЕДИНЕНИЕ, где календарь стоит слева. Это гарантирует, что каждая запись календаря попадет в финальный отчет, а данные о продажах подтянутся только там, где они существуют.
Проанализируем ситуацию, когда отчет строится в виде таблицы, где месяцы расположены в колонках. В настройках СКД на уровне структуры отчета (вкладка «Настройки») для группировки колонок также доступна опция «С распределением по периодам». При ее включении система автоматически создаст столбцы для всех периодов, даже если данных по ним нет, что обеспечит единообразную «сетку» отчета. Для настройки периодических группировок в колонках можно использовать пример формирования шапки отчета по неделям и месяцам в СКД.
Подведем итог. Для новичка в 1С самым простым и рекомендуемым способом будет Способ 1 (настройка дополнения в группировке) в сочетании со Способом 2 (настройка роли поля периода). Это минимизирует объем кода и использует мощь встроенных алгоритмов платформы 8.3.