Как в запросе 1С получить все значения перечисления, зная только часть их наименования

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

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

В этом материале разберем особенности работы с перечислениями в языке запросов 1С, выясним причины ограничений оператора ПОДОБНО и рассмотрим правильные варианты решения данной задачи.

Почему нельзя применить оператор ПОДОБНО прямо в запросе

Попытка использовать конструкции вида ПРЕДСТАВЛЕНИЕ(Состояние) ПОДОБНО "%Отпуск%" прямо в секции ГДЕ языка запросов 1С приведет к ошибке. Разберем основные причины этого ограничения:

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

Способ 1. Программное формирование массива перед выполнением запроса

Наиболее надежный и быстродействующий способ — найти нужные значения перечисления на стороне программного кода 1С до выполнения запроса, собрать их в массив и передать в запрос через параметр.

Рассмотрим пошагово алгоритм решения:

  1. Обратимся к коллекции метаданных нужного перечисления.
  2. Объединим обход элементов с проверкой синонима или наименования на вхождение искомой подстроки.
  3. Заполним массив найденными ссылками.
  4. Передадим массив в запрос и применим условие В (&МассивЗначений).

Проанализируем пример кода 1С:


// Создаем массив для хранения найденных ссылок перечисления
МассивОтпусков = Новый Массив;

// Получаем метаданные перечисления
МетаданныеПеречисления = Метаданные.Перечисления.СостоянияСотрудников;

// Проходим по всем значениям перечисления в метаданных
Для Каждого ЗначениеМетаданных Из МетаданныеПеречисления.ЗначенияПеречисления Цикл
    
    // Получаем синоним или имя значения
    ТекстЗначения = ЗначениеМетаданных.Синоним;
    Если ПустаяСтрока(ТекстЗначения) Тогда
        ТекстЗначения = ЗначениеМетаданных.Имя;
    КонецЕсли;
    
    // Проверяем наличие подстроки "отпуск" (без учета регистра)
    Если СтрНайти(НСтр(ТекстЗначения), "отпуск") > 0 
       Или СтрНайти(НСтр(ЗначениеМетаданных.Имя), "отпуск") > 0 Тогда
        
        // Формируем ссылку на значение перечисления и добавляем в массив
        СсылкаЗначения = Перечисления.СостоянияСотрудников[ЗначениеМетаданных.Имя];
        МассивОтпусков.Добавить(СсылкаЗначения);
        
    КонецЕсли;
    
КонецЦикла;

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

Запрос.УстановитьПараметр("МассивОтпусков", МассивОтпусков);
РезультатЗапроса = Запрос.Выполнить();

Способ 2. Передача таблицы представлений во временную таблицу запроса

Если требуется выполнить всю логику фильтрации внутри пакета запросов, можно заранее сформировать ТаблицаЗначений со всеми ссылками и их строковыми представлениями, передать её в запрос и выполнить отбор с помощью оператора ПОДОБНО.

Посмотрим, как реализовать этот подход:


// Создаем и заполняем таблицу представлений перечисления
ТЗПредставления = Новый ТаблицаЗначений;
ТЗПредставления.Колонки.Добавить("Ссылка", Новый ОписаниеТипов("ПеречислениеСсылка.СостоянияСотрудников"));
ТЗПредставления.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка"));

Для Каждого ЗначениеИзПеречисления Из Перечисления.СостоянияСотрудников Цикл
    НоваяСтрока = ТЗПредставления.Добавить();
    НоваяСтрока.Ссылка = ЗначениеИзПеречисления;
    НоваяСтрока.Представление = Строка(ЗначениеИзПеречисления);
КонецЦикла;

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

Запрос.УстановитьПараметр("ТЗПредставления", ТЗПредставления);
Запрос.УстановитьПараметр("ШаблонПоиска", "%Отпуск%");

РезультатЗапроса = Запрос.Выполнить();

Способ 3. Использование механизма СКД

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

← На главную