При разработке отчетов в системе компоновки данных (СКД) разработчики часто сталкиваются с двумя характерными задачами: необходимостью отображения всех объектов справочника (включая те, по которым не было движений или оборотов) и правильным выводом интервала дат в шапке произвольного макета. Рассмотрим подробно, почему при наложении отборов могут «пропадать» пустые строки и как корректно выводить период отчета.
Рассмотрим стандартную ситуацию: требуется сформировать отчет, в котором должны присутствовать все элементы справочника (например, Номенклатура или СтатьиДвиженияДенежныхСредств), даже если по ним отсутствуют записи в регистрах. Обычно для этого используется соединение справочника с таблицей регистра с помощью соединения ЛЕВОЕ СОЕДИНЕНИЕ.
Однако при добавлении отбора (например, по периоду или подразделению) пустые строки с нулевыми показателями часто исчезают. Происходит это потому, что отбор СКД по умолчанию накладывается на итоговую выборку в секции ГДЕ. Когда для элементов без движений значения полей регистра равны NULL, любое условие сравнения вида Регистр.Период = &Период возвращает Ложь, и строки с NULL отсекаются из результата.
Первый вариант решения, предложенный на форуме, заключается в явной проверке значений на NULL в секции отбора запроса или в настройках отборов СКД.
Проанализируем пример конструкции условия в запросе:
ВЫБРАТЬ
СправочникНоменклатура.Ссылка КАК Номенклатура,
ЕСТЬNULL(ПродажиОбороты.КоличествоОборот, 0) КАК Количество
ИЗ
Справочник.Номенклатура КАК СправочникНоменклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Продажи.Обороты КАК ПродажиОбороты
ПО СправочникНоменклатура.Ссылка = ПродажиОбороты.Номенклатура
ГДЕ
(ПродажиОбороты.Период = &Период ИЛИ ПродажиОбороты.Период ЕСТЬ NULL)
Такой подход позволяет сохранить строки, не имеющие движений в регистре. Однако стоит учитывать важный нюанс: использование условий с логическим оператором ИЛИ и проверкой ЕСТЬ NULL в секции ГДЕ может негативно сказаться на производительности СУБД, так как оптимизатор запросов не всегда может эффективно использовать индексы.
Более эффективным и архитектурно правильным решением в 1С является передача условий фильтрации непосредственно в параметры виртуальной таблицы регистра. В этом случае фильтрация происходит до выполнения соединения с ведущим справочником.
Разберем структуру такого запроса на примере:
ВЫБРАТЬ
СправочникНоменклатура.Ссылка КАК Номенклатура,
ЕСТЬNULL(ПродажиОбороты.КоличествоОборот, 0) КАК Количество
ИЗ
Справочник.Номенклатура КАК СправочникНоменклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Продажи.Обороты(
&НачалоПериода,
&КонецПериода,
Авто,
Организация = &Организация
) КАК ПродажиОбороты
ПО СправочникНоменклатура.Ссылка = ПродажиОбороты.Номенклатура
При таком подходе из регистра выбираются только данные, соответствующие заданным параметрам. Последующее ЛЕВОЕ СОЕДИНЕНИЕ гарантирует сохранение всех элементов справочника Номенклатура, а функция ЕСТЬNULL() заменяет отсутствующие значения на «0».
Чтобы отборы, задаваемые пользователем в настройках СКД, попадали в параметры виртуальной таблицы, а не в блок ГДЕ, используйте специальный синтаксис условий СКД во вложенных описаниях или задавайте параметры виртуальных таблиц через параметры компоновки данных.
Если задача заключается в том, чтобы вывести непрерывный временной ряд (например, все дни месяца), включая даты без движений, создавать объединения или таблицы дат в запросе не требуется. В СКД предусмотрен встроенный механизм дополнения.
Рассмотрим по шагам настройку дополнения периодов:
ПериодДень).Период.&НачалоПериода и &КонецПериода).СКД автоматически сгенерирует все недостающие даты в указанном диапазоне и выведет строки с нулевыми значениями ресурсов.
При оформлении отчетов с использованием собственных макетов часто требуется вывести фразу вида: «За период с 01.01.2024 по 31.01.2024». Рассмотрим способы реализации этой задачи.
Платформа 1С содержит встроенную функцию для получения корректной строковой формулировки периода:
ПредставлениеПериодаОтчета.
ПредставлениеПериода(&НачалоПериода, &КонецПериода, "Л=ru")
Данная функция автоматически сформирует готовый текст (например, «Январь 2024 г.» или «с 01.01.2024 по 31.01.2024» в зависимости от введенных границ).
Если в отчете используется индивидуальный макет заголовка, оформить вывод периода можно напрямую через свойства ячейки макета:
Шаблон.За период с [ДатаНачала] по [ДатаОкончания].Для ДатаНачала: Формат(&НачалоПериода, "ДФ=dd.MM.yyyy")
Для ДатаОкончания: Формат(&КонецПериода, "ДФ=dd.MM.yyyy")
Если пользователь задает интервал через один параметр типа СтандартныйПериод, дата окончания периода может принимать системное значение 31.12.3999 23:59:59, когда верхняя граница не ограничена.
Чтобы избежать вывода неограниченной даты в шапке, проанализируем выражение проверки:
ВЫБОР
КОГДА ЗначениеЗаполнено(&КонецПериода) И &КонецПериода < ДАТАВРЕМЯ(3999, 12, 31)
ТОГДА Формат(&КонецПериода, "ДФ=dd.MM.yyyy")
ИНАЧЕ "по н.в."
КОНЕЦ
Использование этого выражения в параметрах макета позволит сформировать корректный и понятный заголовок отчета при любых вводных данных пользователя.