Как правильно составить запрос в 1С 7.7 для выборки элементов справочника из группы

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

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

Базовый синтаксис запроса по группе справочника

Рассмотрим стандартный пример построения запроса для получения элементов справочника Номенклатура, принадлежащих выбранной группе ВыбНоменклатура:


Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса = "
|Спр = Справочник.Номенклатура.ТекущийЭлемент;
|Группировка Спр;
|Условие(Спр В ВыбНоменклатура);
|";

Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
    Пока Запрос.Группировка(1) = 1 Цикл
        Сообщить("Элемент: " + Запрос.Спр);
    КонецЦикла;
КонецЕсли;

Проанализируем ключевые элементы данного запроса:

  1. Оператор В в блоке Условие проверяет иерархическую принадлежность элемента к указанной группе, включая все вложенные уровни иерархии.
  2. Переменная ВыбНоменклатура обязательно должна быть доступна в области видимости модуля в момент вызова метода Запрос.Выполнить().
  3. Если директива Обрабатывать не задана явно, запрос по умолчанию выбирает только элементы, не помеченные на удаление. Если требуется получить все позиции, добавляется строка |Обрабатывать Все;.

Особенности использования группировок: исключение папок и упорядочивание

Выясним, какие модификаторы можно применять в строке Группировка:

  1. Исключение самих групп: Если в итоговой выборке нужны только конечные элементы без папок-родителей, используем модификатор Без Групп: |Группировка Спр Без Групп;
  2. Сортировка: Для изменения порядка обхода используется конструкция Упорядочить По.
  3. Прямая выгрузка в таблицу: Результат запроса можно не обходить в цикле, а сразу выгрузить в объект ТаблицаЗначений методом Запрос.Выгрузить(ТабЗнач, 0, 0).

Динамическое формирование условий и защита от пустых значений

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


ТекстЗапроса = "
|Спр = Справочник.Номенклатура.ТекущийЭлемент;
|Группировка Спр Без Групп;
|";

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

Обратите внимание: перенос каждой новой строки через символ пайпа | внутри строковых литералов обеспечивает корректную читаемость текста запроса при отладке.

Фильтрация по списку значений

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


Если ВыбСписокНоменклатуры.РазмерСписка() > 0 Тогда
    ТекстЗапроса = ТекстЗапроса + "
    |Условие (Спр В ВыбСписокНоменклатуры);";
КонецЕсли;

Важное ограничение: передача слишком больших списков (сотни и тысячи значений) может приводить к снижению скорости работы внутреннего генератора запросов платформы и повышенной нагрузке на временные файлы в каталоге %TEMP%.

Альтернатива: выборка через методы объекта Справочник

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

Рассмотрим вариант рекурсивной выборки элементов группы с помощью метода ИспользоватьРодителя:


Спр = СоздатьОбъект("Справочник.Номенклатура");
// Второй параметр 1 указывает системе выбирать элементы с учетом всех подпапок
Спр.ИспользоватьРодителя(ВыбНоменклатура, 1);
Спр.ВыбратьЭлементы();

Пока Спр.ПолучитьЭлемент() = 1 Цикл
    Если Спр.ЭтоГруппа() = 0 Тогда
        Сообщить("Найден элемент: " + Спр.ТекущийЭлемент());
    КонецЕсли;
КонецЦикла;

При линейном обходе справочника принадлежность конкретной позиции к группе произвольной глубины вложенности можно также проверить методом Спр.ПринадлежитГруппе(ВыбНоменклатура).

← На главную