При разработке отчетов в системе компоновки данных (СКД) часто возникает ситуация, когда необходимо вывести остатки товаров на конец каждого месяца в заданном интервале. Однако стандартная виртуальная таблица Остатки возвращает данные только по тем позициям номенклатуры, по которым физически есть остаток на указанную дату. Если на конец определенного месяца остаток обнулился, строка с этой номенклатурой просто исчезает из отчета, что мешает наглядному анализу динамики. Рассмотрим, как заставить СКД показывать такие строки с нулевыми значениями, не перегружая при этом отчет лишними данными из справочника номенклатуры.
Проанализируем ситуацию: когда мы используем виртуальную таблицу Остатки с передачей параметра &Период, платформа обращается к итогам регистра накопления. Если на конкретную дату (например, на конец месяца) итоговая запись по паре «Номенклатура — Склад» равна нулю, и по ней не было движений, таблица может не вернуть строку вовсе. При использовании соединения наборов данных, если в «ведущем» наборе нет записи на эту дату, то и в итоговый результат она не попадет. Наша задача — создать структуру, которая гарантирует наличие строки периода для каждой значимой единицы номенклатуры.
Это наиболее правильный «штатный» способ решения проблемы внутри системы компоновки данных. СКД обладает встроенным механизмом генерации недостающих периодов (дополнения). Разберем по шагам, как его активировать:
ПериодДляВывода или Дата).Месяц, День или Год в зависимости от требуемой детализации).&НачалоПериода и &КонецПериода.Благодаря этим настройкам СКД самостоятельно проанализирует выборку и, если для какой-то группировки пропущен месяц внутри интервала, она программно добавит строку с этой датой и нулевыми ресурсами.
Если мы не хотим выводить абсолютно всю номенклатуру из справочника (что привело бы к огромному количеству пустых строк), но нам нужны те позиции, которые «оживали» в выбранном периоде, применим метод предварительного отбора. Рассмотрим пример запроса, который собирает «скелет» данных:
ВЫБРАТЬ РАЗЛИЧНЫЕ
Обороты.Номенклатура КАК Номенклатура
ПОМЕСТИТЬ ВТ_НужнаяНоменклатура
ИЗ
РегистрНакопления.ПартииТоваровНаСкладах.Обороты(&НачалоПериода, &КонецПериода, Авто, ) КАК Обороты
ОБЪЕДИНИТЬ
ВЫБРАТЬ РАЗЛИЧНЫЕ
Остатки.Номенклатура
ИЗ
РегистрНакопления.ПартииТоваровНаСкладах.Остатки(&НачалоПериода, ) КАК Остатки
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_НужнаяНоменклатура.Номенклатура,
&Период КАК ПериодДляВывода,
ЕСТЬNULL(ПартииОстатки.КоличествоОстаток, 0) КАК КоличествоОстаток
ИЗ
ВТ_НужнаяНоменклатура КАК ВТ_НужнаяНоменклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваровНаСкладах.Остатки(&Период, ) КАК ПартииОстатки
ПО ВТ_НужнаяНоменклатура.Номенклатура = ПартииОстатки.Номенклатура
В данном примере мы сначала получаем список только той номенклатуры, по которой либо были обороты внутри периода, либо уже был остаток на начало. Это позволяет ограничить выборку только актуальными данными, но при этом сохранить строки с нулевым конечным остатком.
Вместо ручного соединения таблиц остатков на разные даты, мы можем использовать виртуальную таблицу ОстаткиИОбороты. Проанализируем её параметры: у неё есть возможность настройки метода дополнения периодов. Если в настройках виртуальной таблицы указать периодичность (например, Месяц) и метод дополнения ДвиженияИГраницыПериода, система сама вернет записи на границы периодов, даже если остаток стал нулевым.
При этом в СКД важно правильно настроить ресурсы. Чтобы вместо пустого значения отображался ноль, используем выражение в поле ресурса:
ЕСТЬNULL(СУММА(КоличествоОстаток), 0)
Рассмотрим ситуацию, когда периоды генерируются отдельным набором данных (например, таблицей значений или запросом к производственному календарю), а остатки получаются другим набором. Выясним причину, по которой могут пропадать строки: если связь настроена некорректно, СКД может отсекать строки без соответствий.
Чтобы этого избежать, выполним следующие действия:
&Период.Период Набора2.Это гарантирует, что для каждой даты из первого списка будет предпринята попытка получить остаток. Если остатка нет, СКД выведет NULL, который мы заменим на 0 через настройки ресурсов или условное оформление.
Подведем итог: для вывода нулевых остатков в СКД не нужно добавлять в запрос весь справочник номенклатуры. Проанализировав задачу, мы увидели, что наиболее эффективными методами являются использование ролей полей для автоматического дополнения периодов и работа с виртуальной таблицей ОстаткиИОбороты. Если же требуется сложная логика, оптимальным будет предварительный сбор «активной» номенклатуры во временную таблицу с последующим левым соединением таблиц остатков.