Как связать тип значения из запроса с объектом метаданных в 1С

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

В процессе разработки на платформе 1С:Предприятие 8 часто возникает задача анализа типов данных, которые возвращаются запросом. Типичный пример — получение списка типов документов, сформировавших движения в регистре накопления через поле Регистратор. Поскольку Регистратор является составным типом данных, нам бывает необходимо программно определить, относится ли конкретная запись к определенному объекту метаданных (например, к документу АвансовыйОтчет).

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

Постановка задачи и анализ исходных данных

Рассмотрим ситуацию: нам нужно получить перечень всех типов документов, которые совершили обороты по регистру за определенный период. Исходный запрос может выглядеть следующим образом:


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

Результатом выполнения этого запроса будет таблица значений, в единственной колонке которой содержатся объекты типа Тип. Проблема заключается в том, что объект Тип — это внутренний идентификатор платформы, и его нельзя просто сравнить со строкой "Авансовый отчет". Нам нужно найти способ «перевести» этот тип в объект метаданных или сравнить его с известным типом документа.

Решение 1: Использование метода НайтиПоТипу()

Наиболее универсальный и правильный с точки зрения архитектуры способ — это использование глобального метода Метаданные.НайтиПоТипу(). Этот метод принимает объект Тип и возвращает соответствующий ему объект метаданных (например, ОбъектМетаданных: Документ).

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


Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    // Получаем тип из текущей строки результата
    ТекущийТип = Выборка.ТипДокумента;
    
    // Находим объект метаданных, соответствующий этому типу
    МетаданныеОбъекта = Метаданные.НайтиПоТипу(ТекущийТип);
    
    // Теперь мы можем сравнивать его с конкретными метаданными
    Если МетаданныеОбъекта = Метаданные.Документы.АвансовыйОтчет Тогда
        Сообщить("В списке присутствует Авансовый отчет!");
    КонецЕсли;
    
    // Также можно получить имя или синоним документа
    ИмяДокумента = МетаданныеОбъекта.Имя;
    СинонимДокумента = МетаданныеОбъекта.Синоним;
КонецЦикла;

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

Решение 2: Сравнение через функцию Тип()

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

Рассмотрим, как это выглядит на практике:


НужныйТип = Тип("ДокументСсылка.АвансовыйОтчет");

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    Если Выборка.ТипДокумента = НужныйТип Тогда
        // Действие при совпадении типов
    КонецЕсли;
КонецЦикла;

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

Решение 3: Проверка типов внутри запроса (оператор ССЫЛКА)

Часто задачу можно решить еще на этапе выполнения запроса, не выгружая типы в код. Если цель — узнать, есть ли среди регистраторов определенный документ, мы можем использовать оператор ССЫЛКА. Это работает гораздо быстрее, так как фильтрация происходит на стороне СУБД.

Разберем пример модифицированного запроса:


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

В этом случае мы получим колонки с булевыми значениями. Однако, если список возможных документов велик, такой подход сделает запрос громоздким. В таких случаях лучше использовать ТИПЗНАЧЕНИЯ в условии ГДЕ или ВЫБРАТЬ, но помнить о производительности.

Решение 4: Работа через ОписаниеТипов

Иногда требуется проверить, входит ли полученный тип в некоторую группу (например, «все складские документы»). В этом случае удобно использовать объект ОписаниеТипов. У каждого объекта метаданных есть свойство Тип, которое по сути является описанием типа для ссылок на этот объект.

Проанализируем ситуацию:


// Получаем описание типов для конкретного документа
ОписаниеАвансовогоОтчета = Метаданные.Документы.АвансовыйОтчет.Тип;

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    // Метод СодержитТип позволяет проверить вхождение
    Если ОписаниеАвансовогоОтчета.СодержитТип(Выборка.ТипДокумента) Тогда
        // Тип соответствует Авансовому отчету
    КонецЕсли;
КонецЦикла;

Этот метод считается «хорошим тоном» при написании универсальных механизмов, так как он избавляет от жесткого кодирования строковых имен типов (как в случае с Тип("...")).

Нюансы производительности при работе с ТИПЗНАЧЕНИЯ

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

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

Резюме

Мы рассмотрели несколько способов связи программного типа из запроса с объектами метаданных конфигурации 1С:

  1. Метод Метаданные.НайтиПоТипу() — для получения полного доступа к свойствам объекта метаданных.
  2. Функция Тип() — для быстрого сравнения в коде по имени.
  3. Оператор ССЫЛКА в запросе — для фильтрации данных на уровне базы данных.
  4. Объект ОписаниеТипов — для проверки вхождения типа в заданный набор.

Выбор конкретного метода зависит от ваших задач: для простых проверок используйте Тип(), для сложной логики анализа структуры конфигурации — НайтиПоТипу().

← На главную