В практике разработчика 1С часто возникает задача получить не просто ссылку на объект, а его строковое имя (например, "ПриходнаяНакладная" или "Номенклатура") непосредственно в результате выполнения запроса. Это особенно актуально, когда данные из запроса используются для динамического создания объектов в коде через конструкцию Документы[ИмяОбъекта].СоздатьДокумент() или при обмене данными между идентичными конфигурациями. Рассмотрим подробнее, почему штатных средств для этого не предусмотрено и какими обходными путями мы можем воспользоваться.
Для начала проанализируем ситуацию с точки зрения архитектуры 1С. Платформа строго разделяет типы данных и их строковые представления в метаданных. В языке запросов 1С функция ТИПЗНАЧЕНИЯ() возвращает объект типа Тип, который на уровне базы данных SQL представляет собой уникальный идентификатор таблицы, а не строку. Поэтому прямого метода вроде Ссылка.Метаданные().Имя в запросе не существует. Тем не менее, существует несколько проверенных способов решения этой задачи.
Если ваша конфигурация построена на базе Библиотеки стандартных подсистем (БСП), это самый правильный и «цивилизованный» метод. В системе существует справочник ИдентификаторыОбъектовМетаданных, который хранит соответствие между типами объектов и их именами.
Разберем по шагам, как построить такой запрос. Нам необходимо соединить таблицу наших данных со справочником идентификаторов по условию равенства типов. Посмотрим на пример:
ВЫБРАТЬ
ТвояТаблица.Ссылка КАК Ссылка,
Идентификаторы.Имя КАК ИмяМетаданных,
Идентификаторы.ПолноеИмя КАК ПолноеИмяМетаданных
ИЗ
Документ.ПриобретениеТоваровУслуг КАК ТвояТаблица
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ИдентификаторыОбъектовМетаданных КАК Идентификаторы
ПО ТИПЗНАЧЕНИЯ(ТвояТаблица.Ссылка) = ТИПЗНАЧЕНИЯ(Идентификаторы.ЗначениеПустойСсылки)
Важный нюанс: соединение по ТИПЗНАЧЕНИЯ является достаточно ресурсоемким для SQL-сервера. Платформа транслирует это условие в громоздкий CASE. Если в вашей выборке тысячи записей разных типов, производительность может снизиться. Однако для небольших выборок это решение работает идеально.
Начиная с версии платформы 8.3.10, мы можем передавать Таблицу Значений в качестве параметра запроса. Это позволяет нам подготовить список имен заранее в коде 1С и «подклеить» его к результатам запроса. Этот метод считается наиболее производительным и гибким.
Рассмотрим, как это реализовать программно, используя возможности, которые предоставляет Консоль запросов для управляемых форм (удобно через универсальная консоль запросов и кода для 1С):
// 1. Создаем таблицу соответствия типов и имен
ТЗ_Имена = Новый ТаблицаЗначений;
ТЗ_Имена.Колонки.Добавить("ТипОбъекта", Новый ОписаниеТипов("Тип"));
ТЗ_Имена.Колонки.Добавить("ИмяМетаданных", Новый ОписаниеТипов("Строка"));
// Заполняем её нужными нам типами
НоваяСтрока = ТЗ_Имена.Добавить();
НоваяСтрока.ТипОбъекта = Тип("ДокументСсылка.ПриходныйКассовыйОрдер");
НоваяСтрока.ИмяМетаданных = "ПриходныйКассовыйОрдер";
// 2. Передаем таблицу в запрос
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Имена ИЗ &ТаблицаИмен КАК ТаблицаИмен;
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ОсновнаяТаблица.Ссылка,
| ВТ_Имена.ИмяМетаданных
|ИЗ
| Документ.ПлатежноеПоручение КАК ОсновнаяТаблица
| ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Имена КАК ВТ_Имена
| ПО ТИПЗНАЧЕНИЯ(ОсновнаяТаблица.Ссылка) = ВТ_Имена.ТипОбъекта";
Запрос.УстановитьПараметр("ТаблицаИмен", ТЗ_Имена);
Результат = Запрос.Выполнить();
Проанализируем ситуацию: этот способ хорош для быстрого анализа данных, так как мы полностью контролируем список типов и не зависим от наличия или заполненности справочников БСП.
Если нам нужно получить имена для большого количества разнородных объектов, мы можем собрать текст запроса динамически. Суть метода заключается в создании временной таблицы через ОБЪЕДИНИТЬ ВСЕ, где для каждого типа будет жестко прописана строка с его именем.
Выясним, как это выглядит в коде:
ТекстЗапросаИмен = "";
СписокТипов = Новый Массив;
СписокТипов.Добавить("Справочник.Номенклатура");
СписокТипов.Добавить("Справочник.Контрагенты");
Для Каждого ПолноеИмя Из СписокТипов Цикл
Если ТекстЗапросаИмен <> "" Тогда
ТекстЗапросаИмен = ТекстЗапросаИмен + " ОБЪЕДИНИТЬ ВСЕ ";
КонецЕсли;
ИмяОбъекта = Метаданные.НайтиПоПолномуИмени(ПолноеИмя).Имя;
ТекстЗапросаИмен = ТекстЗапросаИмен +
"ВЫБРАТЬ ТИП(" + ПолноеИмя + ") КАК ТипОбъекта, """ + ИмяОбъекта + """ КАК ИмяСтрокой";
КонецЦикла;
// Теперь этот фрагмент можно использовать как подзапрос или ВТ
ОбщийТекстЗапроса = "ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_СоответствиеТипов ИЗ (" + ТекстЗапросаИмен + ") КАК Т; ...";
Такой подход избавляет систему от необходимости обращаться к таблицам базы данных для поиска имен, так как все значения передаются прямо в тексте SQL-команды.
Этот метод подходит для случаев, когда количество типов ограничено и неизменно (2-3 типа). Несмотря на свою простоту, он крайне неудобен в поддержке, если список объектов начнет расти. Посмотрим на пример реализации:
ВЫБРАТЬ
ВЫБОР
КОГДА ТвояТаблица.Ссылка ССЫЛКА Справочник.Номенклатура
ТОГДА "Номенклатура"
КОГДА ТвояТаблица.Ссылка ССЫЛКА Справочник.Склады
ТОГДА "Склады"
ИНАЧЕ "НеизвестныйТип"
КОНЕЦ КАК ИмяОбъекта
ИЗ
РегистрСведений.ЦеныНоменклатуры КАК ТвояТаблица
Внимание: используйте этот метод только в исключительных случаях, так как он делает код "хрупким" и сложным для чтения.
Если задача получения имени метаданных в запросе стоит очень остро и выполняется часто (например, в высоконагруженных отчетах), можно рассмотреть вариант добавления общего реквизита (или просто реквизита) с типом Строка. В этот реквизит при записи объекта (в событии ПередЗаписью) будет сохраняться имя его метаданных.
В этом случае запрос становится максимально простым, а подготовить его поможет Консоль кода с ИИ-помощником:
ВЫБРАТЬ
ТвояТаблица.Ссылка,
ТвояТаблица.ИмяТипаОбъекта // Обращаемся к обычному строковому полю
ИЗ
Документ.РеализацияТоваровУслуг КАК ТвояТаблица
Хотя этот метод требует изменения структуры конфигурации, он обеспечивает самую высокую скорость выполнения запроса, так как исключает любые соединения и проверки типов на стороне SQL-сервера.
Мы проанализировали пять различных подходов к получению имени метаданных. Подведем итоги их применимости:
Выбор конкретного метода зависит от архитектуры вашей базы данных и требований к производительности. В большинстве случаев мы рекомендуем использовать передачу Таблицы Значений через параметры, так как это сочетает в себе чистоту кода и высокую скорость работы.