Как вывести склады без остатков в отчете СКД и исправить ошибку с полем «Период»?

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

При разработке управленческих отчетов в системе «1С:Предприятие» программисты часто сталкиваются с требованием руководства выводить полную структуру компании. Например, начальнику необходимо видеть общую картину движения товаров, включая те склады, на которых в данный момент нет никаких остатков (чтобы отображались нули или прочерки). Это позволяет оценить всю «цепочку событий» и не упустить из виду временно простаивающие или новые филиалы.

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

Почему пустые склады «исчезают» из отчетов?

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

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

Способ 1. Использование ЛЕВОГО СОЕДИНЕНИЯ в запросе

Проанализируем классический вариант решения задачи с помощью левого соединения. Нам необходимо выбрать все элементы из справочника Склады и левым соединением присоединить к ним остатки из регистра. Таким образом, даже если по складу нет остатков, сам склад все равно останется в результирующей таблице, а поля с количеством примут значение NULL.

Посмотрим на пример правильного построения такого запроса:


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

Важное предупреждение (Ловушка Левого Соединения): Очень часто разработчики совершают ошибку, накладывая последующие отборы (например, по номенклатуре) в секции ГДЕ. Если написать так:


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

то СУБД при выполнении запроса автоматически преобразует ваше ЛЕВОЕ соединение во ВНУТРЕННЕЕ. Все пустые склады, у которых поле номенклатуры равно NULL, будут отсечены этим условием, и они снова пропадут из отчета. Чтобы этого избежать, любые отборы по соединяемой таблице остатков необходимо накладывать строго внутри параметров самой виртуальной таблицы:


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

Почему ПОЛНОЕ СОЕДИНЕНИЕ — это плохая практика?

В процессе обсуждения этой проблемы иногда звучат предложения использовать ПОЛНОЕ СОЕДИНЕНИЕ (как в Сообщении 6). Разберем, почему делать этого не стоит:

Разбор ошибок: Не найдено поле «Период» и сбои в общем модуле

При изменении запросов в СКД разработчики часто сталкиваются с ошибками инициализации формы отчета (как в Сообщениях 7 и 10). Выясним причину их возникновения и способы устранения.

1. Ошибка «Поле объекта не обнаружено (Период)» в модуле `ТиповыеОтчеты`:
Эта ошибка характерна для старых типовых конфигураций (например, УТ 10.3, УПП 1.3), работающих на обычных формах. Стандартный механизм инициализации формы отчета ожидает увидеть в настройках СКД параметр с именем Период. Если вы переименовали этот параметр, удалили его или сняли галочку «Автозаполнение» в конструкторе запроса, код формы не находит нужный элемент управления и выдает ошибку. Чтобы исправить это, убедитесь, что в схеме компоновки данных на вкладке «Параметры» присутствует параметр с именем Период.

2. Ошибка «Поле не найдено "ТоварыНаСкладахОстатки.Период"»:
Данная ошибка возникает при попытке выбрать поле периода через точку от виртуальной таблицы остатков (например, ТоварыНаСкладахОстатки.Период). Помните, что в виртуальной таблице Остатки поля Период в списке выбора нет и быть не может (в отличие от таблицы оборотов). В таблице остатков период — это исключительно внешний параметр, который передается в скобках при обращении к таблице:

РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, )

Попытки вытащить его в секцию ВЫБРАТЬ приведут к ошибке синтаксиса СУБД.

Способ 2. Альтернативное решение через связи наборов данных в СКД

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

Выполним следующие шаги по настройке:

  1. Создадим НаборДанных1 (запрос): Назовем его «Склады». В тексте запроса выберем только список складов:
    
    ВЫБРАТЬ
        Склады.Ссылка КАК Склад
    ИЗ
        Справочник.Склады КАК Склады
    
  2. Создадим НаборДанных2 (запрос): Назовем его «Остатки». Здесь мы получаем остатки товаров:
    
    ВЫБРАТЬ
        ТоварыНаСкладахОстатки.Склад КАК Склад,
        ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура,
        ТоварыНаСкладахОстатки.КоличествоОстаток КАК КоличествоОстаток
    ИЗ
        РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК ТоварыНаСкладахОстатки
    
  3. Настроим связи наборов данных: Перейдем на вкладку «Связи наборов данных» и добавим новую строку:
    • Источник связи: НаборДанных1
    • Приемник связи: НаборДанных2
    • Условие связи: Склад = Склад
    • Параметры: В колонке «Параметры связи» укажем имя параметра Склад (это позволит платформе передавать конкретный склад в приемник для оптимизации запросов к СУБД).

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

Правильная настройка отображения нулей и прочерков в СКД

В сообщениях форума часто предлагают использовать конструкцию ЕСТЬNULL(Поле1, "-") или ЕСТЬNULL(Поле1, "0") прямо в запросе. Рассмотрим подробнее, почему так делать не рекомендуется.

Функция ЕСТЬNULL, возвращающая текстовую строку вроде "-" или "0", неявно преобразует тип всего числового поля в строковый тип (или создает составной тип данных). В результате этого система компоновки данных больше не сможет рассчитывать итоги (ресурсы) по этому полю. Попытка просуммировать строки вызовет ошибку, либо итоги просто останутся пустыми.

Правильный и профессиональный способ настройки отображения пустых значений заключается в использовании механизмов оформления самой СКД:

  1. В запросе всегда возвращайте числовые значения или значение NULL (не заменяйте их строками).
  2. На вкладке «Ресурсы» определите ваше числовое поле (например, КоличествоОстаток) с выражением Сумма(КоличествоОстаток).
  3. Нажмите на вкладку «Настройки», выберите отчет в целом или конкретную группировку и перейдите на вкладку «Условное оформление» (или откройте свойства нужного поля на вкладке «Наборы данных»).
  4. Добавьте новый элемент оформления и выберите свойство «Формат».
  5. В появившемся окне конструктора форматной строки настройте параметры:
    • Дробная часть: укажите точность (например, 2 или 3 знака).
    • Формат нуля (параметр ЧН): впишите туда символ прочерка - или цифру 0. Это значение будет выводиться на экран всякий раз, когда остаток равен нулю или отсутствует (значение NULL).

Этот способ позволяет полностью сохранить тип данных «Число» для всех математических расчетов в итогах отчета, но при этом гарантирует аккуратный и красивый внешний вид таблицы для конечного пользователя и руководства.

← На главную