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

Программист 1С v7.7 Управленческий учет
← На главную

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

Проблема: Почему оператор «равно» не работает для групп?

Рассмотрим исходную ситуацию. В коде используется стандартный синтаксис условия:

|Условие(Контр = ВыбКонтр);

Проанализируем, как система воспринимает эту строку. Когда в переменной ВыбКонтр находится конкретный элемент справочника, запрос сравнивает идентификаторы и находит соответствие. Однако, если ВыбКонтр — это группа, прямое сравнение Контр = ВыбКонтр будет искать документы, где в поле «Контрагент» указана сама папка. Поскольку в типовых конфигурациях в документах обычно выбираются только элементы, запрос не находит совпадений и возвращает пустую таблицу.

Решение 1: Универсальный оператор «В»

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

Изменим текст запроса следующим образом:


// Было:
|Условие(Контр = ВыбКонтр);

// Стало:
|Условие(Контр В ВыбКонтр);

Выясним, почему это работает. Оператор В (или IN) в 1С 7.7 является интеллектуальным. Его поведение зависит от типа передаваемого значения:

  1. Если передана группа: Запрос автоматически выбирает все элементы, входящие в эту группу, а также во все её дочерние подгруппы (рекурсивно).
  2. Если передан элемент: Запрос сработает аналогично оператору =, выбрав данные только по этому элементу.
  3. Если передан список значений: Запрос выберет все данные, соответствующие объектам, находящимся в списке.

Таким образом, замена всего одного символа делает ваш запрос универсальным для любого типа выбора пользователя.

Решение 2: Динамическое формирование текста запроса

Иногда программисту требуется более жесткий контроль над логикой выполнения. Рассмотрим вариант, при котором текст запроса формируется динамически в зависимости от того, что выбрал пользователь. Это может быть полезно, если вы хотите применить разную логику для групп и элементов (хотя в большинстве случаев достаточно первого решения).

Разберем пример кода:


ТекстЗапроса = 
"//{{ЗАПРОС(ОбработкаДок)
|Период с ВыбНачПериода по ВыбКонПериода;
|Контр = Документ.РеализацияУслуг.Контрагент;
|СуммаРеал = Документ.РеализацияУслуг.Сумма;
|Группировка Контр;";

Если ВыбКонтр.ЭтоГруппа() = 1 Тогда
    ТекстЗапроса = ТекстЗапроса + "
    |Условие(Контр В ВыбКонтр);";
Иначе
    ТекстЗапроса = ТекстЗапроса + "
    |Условие(Контр = ВыбКонтр);";
КонецЕсли;

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

Важный нюанс: Обработка пустого выбора

Проанализируем критическую ошибку, которую часто допускают новички. Что произойдет, если пользователь не выбрал контрагента (переменная ВыбКонтр пустая), а в запросе стоит условие В? В некоторых версиях платформы и типах баз (особенно SQL) пустое условие может быть проигнорировано, и запрос выдаст данные по всей базе. Это может привести к зависанию системы на длительное время.

Чтобы избежать этой ситуации, рекомендуется использовать проверку перед запуском запроса или специальную конструкцию в условии. Посмотрим на надежный вариант реализации:


Если ВыбКонтр.Выбран() = 0 Тогда
    // Если ничего не выбрано, можно либо прервать выполнение, 
    // либо подготовить условие, которое ничего не вернет.
    СписокКонтр = СоздатьОбъект("СписокЗначений"); 
    // Список пустой, значит условие "В Список" ничего не найдет
Иначе
    СписокКонтр = ВыбКонтр;
КонецЕсли;

// В тексте запроса:
|Условие(Контр В СписокКонтр);

Также стоит рассмотреть совет профессионалов: если переменная ВыбКонтр пустая, лучше использовать явное равенство пустому значению, чтобы запрос гарантированно вернул пустой результат, а не все данные мира:

|Условие(Контр = ВыбКонтр); // Если ВыбКонтр пустое, запрос вернет пустоту

Оптимизация вывода: Группировка «Без групп»

Когда мы выбираем данные по группе контрагентов, нам часто не нужны промежуточные итоги по самим папкам внутри отчета, а нужны только детальные данные по конечным элементам (клиентам). Посмотрим, как настроить группировку в запросе, чтобы избавиться от лишних строк:

|Группировка Контр Без Групп;

Использование ключевых слов Без Групп позволяет игнорировать иерархические уровни в результирующей выборке запроса, даже если в условии В участвовала папка. Это значительно упрощает последующий обход результата методом Запрос.Группировка(1) и вывод в таблицу 1С.

Технические особенности для SQL и DBF

Стоит упомянуть, как платформа 7.7 обрабатывает оператор В на уровне базы данных:

Если вы замечаете серьезные тормоза при использовании иерархических условий, возможно, стоит задуматься о «прямых запросах» через внешние компоненты, но для 99% повседневных задач стандартного оператора В будет более чем достаточно.

Подведем итог: для корректной работы запроса с группами контрагентов в 1С 7.7 всегда используйте Условие(Реквизит В Значение). Это универсальное правило, которое экономит время разработчика и обеспечивает корректность данных в отчетах.

← На главную