Как вывести всю номенклатуру, включая позиции без остатков, в отчете СКД

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

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

Причина возникновения проблемы

Прежде чем переходить к решениям, выясним причину, по которой «пропадают» пустые позиции. Виртуальная таблица Остатки регистра накопления по своей природе содержит записи только о тех ресурсах, по которым в базе данных есть движения. Если вы строите отчет только по этой таблице, СКД просто не «знает» о существовании номенклатуры, по которой не было записей в регистре. Чтобы получить полный список, нам необходимо сделать справочник Номенклатура «ведущей» таблицей.

Решение 1. Использование левого соединения в запросе

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


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Номенклатура,
    ЕСТЬNULL(ТоварыНаСкладахОстатки.В наличииОстаток, 0) КАК Остаток
ИЗ
    Справочник.Номенклатура КАК Номенклатура
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК ТоварыНаСкладахОстатки
        ПО Номенклатура.Ссылка = ТоварыНаСкладахОстатки.Номенклатура
ГДЕ
    НЕ Номенклатура.ЭтоГруппа

Важные моменты этого подхода:

  1. Левое соединение: Мы используем именно ЛЕВОЕ СОЕДИНЕНИЕ, чтобы сохранить все записи из левой таблицы (справочника) и дополнить их данными из правой (регистра).
  2. Фильтрация групп: В условии ГДЕ мы отсекаем группы номенклатуры (НЕ Номенклатура.ЭтоГруппа), так как остатки обычно хранятся только по элементам.
  3. Функция ЕСТЬNULL: Для позиций без остатка регистр вернет значение NULL. Чтобы в отчете красиво отображался «0», мы используем функцию ЕСТЬNULL.

Решение 2. Обход ошибки «Недопустимая связь»

Часто при попытке соединить физическую таблицу справочника с виртуальной таблицей остатков напрямую в конструкторе, система выдает ошибку о недопустимой связи. Проанализируем ситуацию: это происходит из-за того, что конструктор 1С накладывает определенные ограничения на индексацию и оптимизацию запросов к виртуальным таблицам.

Чтобы решить эту проблему, воспользуемся механизмом временных таблиц. Разберем по шагам:

  1. Сначала создадим первый запрос (пакет запроса), который выбирает данные только из регистра и помещает их во временную таблицу (например, ВТ_Остатки).
  2. Во втором запросе пакета выберем данные из Справочник.Номенклатура.
  3. Выполним левое соединение справочника с нашей временной таблицей ВТ_Остатки.

Такой подход гарантирует, что 1С корректно обработает связи, и ошибка «Недопустимая связь» исчезнет.

Решение 3. Механизм связей наборов данных в СКД

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

Рассмотрим алгоритм настройки:

  1. Создадим НаборДанных1 (Запрос). В нем выберем просто ссылку из справочника номенклатуры.
  2. Создадим НаборДанных2 (Запрос). В нем опишем выборку остатков из регистра.
  3. Перейдем на закладку «Связи наборов данных».
  4. Установим связь:
    • Источник связи: НаборДанных1 (Справочник)
    • Приемник связи: НаборДанных2 (Остатки)
    • Условие связи: Номенклатура = Номенклатура

В этом случае СКД сама выполнит аналог левого соединения. Все элементы из первого набора (справочника) будут выведены в отчет, а если для них найдутся данные во втором наборе — они будут подтянуты в соответствующие колонки.

Типичная ловушка: Фильтрация в секции ГДЕ

Проанализируем распространенную ошибку, из-за которой левое соединение перестает работать. Если мы хотим отфильтровать отчет по конкретному складу, новички часто пишут так:


ГДЕ
    ТоварыНаСкладахОстатки.Склад = &Склад

Внимание: Как только вы добавляете условие на поле из «правой» таблицы (регистра) в секцию ГДЕ, ваше левое соединение фактически превращается во внутреннее. Записи, где склад равен NULL (а это все записи без остатков), будут отсечены этим фильтром.

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


ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &НужныйСклад) КАК ТоварыНаСкладахОстатки

Дополнительная настройка: Тип дополнения

Если ваша задача — вывести иерархию номенклатуры или обеспечить наличие всех элементов даже при использовании сложных отборов, можно воспользоваться настройками группировки в СКД. В настройках отчета, выбрав группировку Номенклатура, перейдите на вкладку «Иерархия группировки» (или «Детальные записи») и установите «Тип дополнения». Это заставит систему принудительно дополнить результат значениями из справочника, даже если их нет в итоговой выборке данных.

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

← На главную