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

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

В практике разработчика 1С часто возникает задача получить не просто ссылку на объект, а его строковое имя (например, "ПриходнаяНакладная" или "Номенклатура") непосредственно в результате выполнения запроса. Это особенно актуально, когда данные из запроса используются для динамического создания объектов в коде через конструкцию Документы[ИмяОбъекта].СоздатьДокумент() или при обмене данными между идентичными конфигурациями. Рассмотрим подробнее, почему штатных средств для этого не предусмотрено и какими обходными путями мы можем воспользоваться.

Причина ограничения платформы

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

Способ 1. Использование справочника «Идентификаторы объектов метаданных» (БСП)

Если ваша конфигурация построена на базе Библиотеки стандартных подсистем (БСП), это самый правильный и «цивилизованный» метод. В системе существует справочник ИдентификаторыОбъектовМетаданных, который хранит соответствие между типами объектов и их именами.

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


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

Важный нюанс: соединение по ТИПЗНАЧЕНИЯ является достаточно ресурсоемким для SQL-сервера. Платформа транслирует это условие в громоздкий CASE. Если в вашей выборке тысячи записей разных типов, производительность может снизиться. Однако для небольших выборок это решение работает идеально.

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

Начиная с версии платформы 8.3.10, мы можем передавать Таблицу Значений в качестве параметра запроса. Это позволяет нам подготовить список имен заранее в коде 1С и «подклеить» его к результатам запроса. Этот метод считается наиболее производительным и гибким.

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


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

// Заполняем её нужными нам типами
НоваяСтрока = ТЗ_Имена.Добавить();
НоваяСтрока.ТипОбъекта = Тип("ДокументСсылка.ПриходныйКассовыйОрдер");
НоваяСтрока.ИмяМетаданных = "ПриходныйКассовыйОрдер";

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

Запрос.УстановитьПараметр("ТаблицаИмен", ТЗ_Имена);
Результат = Запрос.Выполнить();

Проанализируем ситуацию: этот способ хорош для быстрого анализа данных, так как мы полностью контролируем список типов и не зависим от наличия или заполненности справочников БСП.

Способ 3. Программная сборка текста запроса (Цикл по метаданным)

Если нам нужно получить имена для большого количества разнородных объектов, мы можем собрать текст запроса динамически. Суть метода заключается в создании временной таблицы через ОБЪЕДИНИТЬ ВСЕ, где для каждого типа будет жестко прописана строка с его именем.

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


ТекстЗапросаИмен = "";
СписокТипов = Новый Массив;
СписокТипов.Добавить("Справочник.Номенклатура");
СписокТипов.Добавить("Справочник.Контрагенты");

Для Каждого ПолноеИмя Из СписокТипов Цикл
    Если ТекстЗапросаИмен <> "" Тогда
        ТекстЗапросаИмен = ТекстЗапросаИмен + " ОБЪЕДИНИТЬ ВСЕ ";
    КонецЕсли;
    
    ИмяОбъекта = Метаданные.НайтиПоПолномуИмени(ПолноеИмя).Имя;
    ТекстЗапросаИмен = ТекстЗапросаИмен + 
        "ВЫБРАТЬ ТИП(" + ПолноеИмя + ") КАК ТипОбъекта, """ + ИмяОбъекта + """ КАК ИмяСтрокой";
КонецЦикла;

// Теперь этот фрагмент можно использовать как подзапрос или ВТ
ОбщийТекстЗапроса = "ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_СоответствиеТипов ИЗ (" + ТекстЗапросаИмен + ") КАК Т; ...";

Такой подход избавляет систему от необходимости обращаться к таблицам базы данных для поиска имен, так как все значения передаются прямо в тексте SQL-команды.

Способ 4. Использование конструкции ВЫБРАТЬ КОГДА (Жесткое кодирование)

Этот метод подходит для случаев, когда количество типов ограничено и неизменно (2-3 типа). Несмотря на свою простоту, он крайне неудобен в поддержке, если список объектов начнет расти. Посмотрим на пример реализации:


ВЫБРАТЬ
    ВЫБОР
        КОГДА ТвояТаблица.Ссылка ССЫЛКА Справочник.Номенклатура 
            ТОГДА "Номенклатура"
        КОГДА ТвояТаблица.Ссылка ССЫЛКА Справочник.Склады 
            ТОГДА "Склады"
        ИНАЧЕ "НеизвестныйТип"
    КОНЕЦ КАК ИмяОбъекта
ИЗ
    РегистрСведений.ЦеныНоменклатуры КАК ТвояТаблица

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

Способ 5. Архитектурное решение через общий реквизит

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

В этом случае запрос становится максимально простым, а подготовить его поможет Консоль кода с ИИ-помощником:


ВЫБРАТЬ
    ТвояТаблица.Ссылка,
    ТвояТаблица.ИмяТипаОбъекта // Обращаемся к обычному строковому полю
ИЗ
    Документ.РеализацияТоваровУслуг КАК ТвояТаблица

Хотя этот метод требует изменения структуры конфигурации, он обеспечивает самую высокую скорость выполнения запроса, так как исключает любые соединения и проверки типов на стороне SQL-сервера.

Подведение итогов

Мы проанализировали пять различных подходов к получению имени метаданных. Подведем итоги их применимости:

  1. Справочник Идентификаторы объектов метаданных: Оптимально для систем на БСП, когда не хочется писать много лишнего кода.
  2. Передача Таблицы Значений: Самый сбалансированный метод для современных конфигураций на платформе 8.3.10+.
  3. Программная сборка запроса: Подходит для универсальных обработок, которые должны работать в любой базе.
  4. Конструкция ВЫБОР: Допустима только для разовых задач с 2-3 условиями.
  5. Общий реквизит: Экстремальный метод для систем, где критична скорость работы тяжелых запросов.

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

← На главную