Как правильно отобрать документы по иерархии складов в запросе 1С?

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

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

Анализ проблемы: почему оператор «В» не подходит для групп

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

Проанализируем основные причины возникновения ошибок при работе с иерархией:

  1. Неверный оператор в тексте запроса: Оператор В проверяет на точное соответствие значений из списка.
  2. Передача неверного типа данных: Попытка передать строку с наименованием или кодом вместо ссылки на объект.
  3. Ожидание автоматического раскрытия группы: Платформа не раскрывает группу до списка элементов автоматически, если не указана специальная инструкция.

Решение №1: Использование оператора «В ИЕРАРХИИ»

Самый простой и эффективный способ получить все склады, входящие в определенную группу (включая подгруппы любого уровня вложенности), — это использование оператора В ИЕРАРХИИ. Рассмотрим, как должен выглядеть фрагмент кода запроса:


// Фрагмент текста запроса
Запрос.Текст = 
"ВЫБРАТЬ
|   РеализацияТоваровУслуг.Ссылка КАК Документ,
|   РеализацияТоваровУслуг.Склад КАК Склад
|ИЗ
|   Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
|   РеализацияТоваровУслуг.Склад В ИЕРАРХИИ(&СписокСкладов)";

// Установка параметра (может быть как одна ссылка на группу, так и массив/список)
Запрос.УстановитьПараметр("СписокСкладов", ГруппаСкладовСсылка);

Важно понимать, что оператор В ИЕРАРХИИ универсален. Если вы передадите в него массив, содержащий и группы, и отдельные элементы, 1С корректно отработает оба варианта: для групп будут выбраны все подчиненные элементы, а для обычных ссылок — только они сами.

Решение №2: Программное «развертывание» иерархии в плоский список

Иногда возникает необходимость оставить в тексте запроса оператор В (например, если запрос строится динамически и оператор В ИЕРАРХИИ может замедлить работу на огромных объемах данных). В этом случае мы должны заранее подготовить СписокЗначений, содержащий только конечные элементы (склады).

Разберем, как программно получить все элементы группы:


Функция ПолучитьПлоскийСписокСкладов(ВыбраннаяГруппа)
    
    Список = Новый СписокЗначений;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ
    |   Склады.Ссылка КАК Ссылка
    |ИЗ
    |   Справочник.Склады КАК Склады
    |ГДЕ
    |   Склады.Ссылка В ИЕРАРХИИ(&ВыбраннаяГруппа)
    |   И НЕ Склады.ЭтоГруппа";
    
    Запрос.УстановитьПараметр("ВыбраннаяГруппа", ВыбраннаяГруппа);
    
    РезультатЗапроса = Запрос.Выполнить();
    Если Не РезультатЗапроса.Пустой() Тогда
        Список.ЗагрузитьЗначения(РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("Ссылка"));
    КонецЕсли;
    
    Возврат Список;
    
КонецФункции

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

Особенности передачи параметров через структуру отбора

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

Рассмотрим пример правильной модификации структуры перед выполнением запроса:


// Предположим, у нас есть структура отбора, полученная из формы
СтруктураОтбора = ПолучитьСтруктуруНакладные();

// Если на форме установлен флаг "Фильтровать по группе"
Если ТолькоОпределеннаяГруппа Тогда
    // Получаем ссылку на нужную группу (папку)
    НужнаяГруппа = Справочники.Склады.НайтиПоКоду("00001");
    
    // Вариант А: заменяем список на одну ссылку (если в запросе В ИЕРАРХИИ)
    СтруктураОтбора.СписокСкладов = НужнаяГруппа;
    
    // Вариант Б: разворачиваем иерархию (если в запросе просто В)
    // СтруктураОтбора.СписокСкладов = ПолучитьПлоскийСписокСкладов(НужнаяГруппа);
КонецЕсли;

// Передаем в итоговый запрос
Запрос.УстановитьПараметр("СписокСкладов", СтруктураОтбора.СписокСкладов);

Типичные ошибки при отладке

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

Для проверки всегда используйте точку останова перед вызовом Запрос.Выполнить(). Проверьте содержимое параметра СписокСкладов: он должен содержать ссылки (СправочникСсылка), а не текст или объекты.

Подведем итог: для корректной работы с иерархией складов в 1С наиболее правильным и современным способом является использование оператора В ИЕРАРХИИ в тексте запроса и передача в него ссылки на родительскую группу или массива ссылок. Это обеспечивает гибкость кода и правильность выборки данных независимо от структуры справочника.

← На главную