К статье
Практический материал

Разработка и Конфигурация · 13 мин

1С: как определить ссылочный тип объекта

Как определить ссылочный тип в 1С: функция ТипЗнч, Тип(), метаданные, проверка видов документов и справочников. Примеры кода на встроенном языке.

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

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

Ниже разобраны практические способы определения ссылочного типа с примерами кода, типичные ошибки и рекомендации по выбору метода в зависимости от задачи.

Что такое ссылочный тип в 1С и чем он отличается от примитивных

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

Каждый ссылочный тип имеет два «представления»: СправочникСсылка.Номенклатура (сам указатель) и СправочникОбъект.Номенклатура (объект с загруженными данными, доступный для изменения). В параметрах процедур и реквизитах составного типа чаще всего хранится именно ссылка.

Понимание этой разницы важно на практике: если проверять тип загруженного объекта, полученного через Ссылка.ПолучитьОбъект(), то ТипЗнч() вернёт СправочникОбъект, а не СправочникСсылка, и сравнение с ожидаемым ссылочным типом не сработает.

Определение типа значения через ТипЗнч и Тип

Базовый инструмент — функция ТипЗнч(Значение). Она возвращает значение типа Тип, которое можно сравнить с конкретным типом, полученным функцией Тип("ИмяТипа").

Если ТипЗнч(Параметр) = Тип("СправочникСсылка.Номенклатура") Тогда

// работаем с номенклатурой

ИначеЕсли ТипЗнч(Параметр) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда

// работаем с документом

КонецЕсли;

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

Дополнительная тонкость: имя типа в строке для функции Тип() задаётся как "СправочникСсылка.ИмяСправочника" — с точным именем объекта метаданных, а не синонимом. Опечатка в имени вызовет ошибку исполнения, поэтому такой код желательно тестировать сразу после написания.

Универсальная проверка «является ли значение ссылкой»

Когда нужно просто отличить ссылку от примитивного значения, удобнее использовать методы менеджеров объектов: Справочники.ТипВсеСсылки(), Документы.ТипВсеСсылки(), Перечисления.ТипВсеСсылки(), ПланыВидовХарактеристик.ТипВсеСсылки(), ПланыСчетов.ТипВсеСсылки(), ПланыВидовРасчета.ТипВсеСсылки(), БизнесПроцессы.ТипВсеСсылки(), Задачи.ТипВсеСсылки(), ПланыОбмена.ТипВсеСсылки(). Каждый из них возвращает ОписаниеТипов, у которого есть метод СодержитТип().

Функция ЭтоСсылка(Значение) Экспорт

ТипЗначения = ТипЗнч(Значение);

Возврат Справочники.ТипВсеСсылки().СодержитТип(ТипЗначения)

Или Документы.ТипВсеСсылки().СодержитТип(ТипЗначения)

Или Перечисления.ТипВсеСсылки().СодержитТип(ТипЗначения)

Или ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(ТипЗначения)

Или ПланыСчетов.ТипВсеСсылки().СодержитТип(ТипЗначения)

Или ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(ТипЗначения)

Или БизнесПроцессы.ТипВсеСсылки().СодержитТип(ТипЗначения)

Или Задачи.ТипВсеСсылки().СодержитТип(ТипЗначения)

Или ПланыОбмена.ТипВсеСсылки().СодержитТип(ТипЗначения);

КонецФункции

В типовых конфигурациях на базе БСП есть готовая функция ОбщегоНазначения.ЭтоСсылка(ТипЗначения) — если конфигурация включает эту библиотеку, писать собственную реализацию не нужно. Проверьте наличие общего модуля ОбщегоНазначения в дереве конфигурации.

Определение вида объекта через метаданные

Если нужно узнать не просто «ссылка или нет», а конкретный вид объекта — например, какой именно документ пришёл в параметр, — удобнее всего использовать метод Метаданные() самого значения. Он доступен у любой ссылки.

МетаданныеЗначения = Значение.Метаданные();

ИмяВида = МетаданныеЗначения.Имя; // например, "РеализацияТоваровУслуг"

ПолноеИмя = МетаданныеЗначения.ПолноеИмя(); // "Документ.РеализацияТоваровУслуг"

Строка вида "Документ.РеализацияТоваровУслуг" универсальна: по ней можно построить тип через Тип("ДокументСсылка." + ИмяВида), получить менеджер объекта или передать имя в механизмы обмена. Определить семейство объекта (документ, справочник и т.д.) можно анализом полного имени или через проверку принадлежности коллекции метаданных.

Если Метаданные.Документы.Содержит(МетаданныеЗначения) Тогда

// это документ

ИначеЕсли Метаданные.Справочники.Содержит(МетаданныеЗначения) Тогда

// это справочник

КонецЕсли;

bsl
ПолноеИмя = Значение.Метаданные().ПолноеИмя();
Семейство = СтрРазделить(ПолноеИмя, ".")[0]; // "Документ", "Справочник" и т.д.
ИмяВида  = СтрРазделить(ПолноеИмя, ".")[1];

Определение типа реквизита составного типа

Отдельная задача — узнать, какие типы допускает реквизит составного типа (например, «Контрагент» в документе может быть и справочником «Контрагенты», и «Организации»). Здесь работает не анализ значения, а анализ метаданных реквизита.

РеквизитМета = Метаданные.Документы.РеализацияТоваровУслуг.Реквизиты.Контрагент;

Для Каждого ТипРеквизита Из РеквизитМета.Тип.Типы() Цикл

Сообщить(ТипРеквизита);

КонецЦикла;

Тот же приём применяется к измерениям и ресурсам регистров, реквизитам планов видов характеристик и типам параметров в запросах. Это полезно при построении универсальных форм выбора и при валидации данных перед записью.

Для характеристик типа ОпределяемыйТип (в конфигурациях на БСП) аналогично анализируется свойство Тип объекта метаданных Метаданные.ОпределяемыеТипы.ИмяТипа.

Сравнение способов

ТипЗнч() + Тип()

Быстро и точно для заранее известных типов. Не подходит для универсальных проверок по всем видам объектов.

ТипВсеСсылки().СодержитТип()

Универсальная проверка принадлежности к семейству (все справочники, все документы). Не говорит, какой именно вид объекта.

Значение.Метаданные()

Даёт точный вид объекта и его имя. Работает только для ссылочных значений — у примитивов метода нет.

Метаданные конфигурации

Позволяет анализировать типы реквизитов без значения. Требует знания структуры конфигурации.

Проверка на пустую и битую ссылку

Определив, что значение является ссылкой, часто требуется проверить её состояние. Пустая ссылка проверяется методом Пустая() или функцией ЗначениеЗаполнено(). Тип пустой ссылки определяется так же, как и заполненной, — ТипЗнч() корректно вернёт, например, СправочникСсылка.Номенклатура.

«Битая» ссылка — ссылка на удалённый объект — определяется иначе: попытка обращения к реквизиту даст значение Неопределено или строку вида «<Объект не найден>». Надёжный способ проверки — запрос:

Запрос = Новый Запрос("ВЫБРАТЬ Таблица.Ссылка ИЗ Справочник.Номенклатура КАК Таблица ГДЕ Таблица.Ссылка = &Ссылка");

Запрос.УстановитьПараметр("Ссылка", ПроверяемаяСсылка);

СсылкаСуществует = Не Запрос.Выполнить().Пустой();

Типичные ошибки при определении ссылочного типа

Первая распространённая ошибка — сравнение типа объекта со ссылочным типом. После Объект = Ссылка.ПолучитьОбъект() функция ТипЗнч(Объект) вернёт СправочникОбъект.Имя, и условие = Тип("СправочникСсылка.Имя") никогда не выполнится. Проверяйте тип до получения объекта или сравнивайте с объектным типом.

Вторая ошибка — вызов Значение.Метаданные() без предварительной проверки, что значение ссылочное. У строки или числа такого метода нет, и код упадёт с ошибкой. Всегда сначала проверяйте ЭтоСсылка() или конкретный тип.

Третья ошибка — использование строкового представления значения для определения типа. Строка «Номенклатура» или представление документа зависит от настроек и локализации и не является надёжным идентификатором типа.

Типичные ошибки
01
Сравнение ТипЗнч(Объект) со ссылочным типом после ПолучитьОбъект() — условие никогда не срабатывает, логика молча не выполняется.
02
Вызов Значение.Метаданные() у примитивного значения — ошибка исполнения в рабочей базе.
03
Определение типа по строковому представлению — ломается при смене синонимов и настроек отображения.
04
Забытые перечисления в проверке ЭтоСсылка — код пытается получить объект перечисления и падает.
05
Опечатка в имени типа внутри Тип("...") — ошибка обнаруживается только при выполнении ветки кода.

Проверка результата и отладка

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

Программно для диагностики удобно выводить полное имя метаданных и тип в журнал регистрации или сообщение:

Если ЭтоСсылка(Значение) Тогда

Сообщить("Тип: " + ТипЗнч(Значение) + ", вид: " + Значение.Метаданные().ПолноеИмя());

Иначе

Сообщить("Примитивный тип: " + ТипЗнч(Значение));

КонецЕсли;

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

Контрольные точки

Как проверить результат

Тип значения в отладчике
Норма

Отображается ожидаемый тип, например СправочникСсылка.Номенклатура

Тревожный признак

Тип отличается от ожидаемого или значение имеет тип Неопределено

Поведение на пустой ссылке
Норма

Тип определяется корректно, Пустая() возвращает Истина

Тревожный признак

Код падает или ошибочно считает пустую ссылку примитивом

Поведение на битой ссылке
Норма

Тип определяется, запрос на существование возвращает пустой результат

Тревожный признак

Обращение к реквизитам приводит к непредусмотренным значениям

Универсальность функции
Норма

Работает для всех видов ссылок и примитивов без исключений

Тревожный признак

Падает на перечислениях, планах обмена или характеристиках

Часто задаваемые вопросы

Как определить тип значения в запросе 1С?

В языке запросов используется оператор ВЫРАЗИТЬ(Поле КАК Справочник.Номенклатура) для приведения типа и функция ТИПЗНАЧЕНИЯ(Поле) вместе с ТИП() в условии: ГДЕ ТИПЗНАЧЕНИЯ(Поле) = ТИП(Справочник.Номенклатура). Также доступна проверка Поле ССЫЛКА Справочник.Номенклатура.

Чем отличается ТипЗнч от Тип в 1С?

ТипЗнч(Значение) возвращает тип конкретного значения-переменной. Тип("ИмяТипа") создаёт значение типа Тип по строковому имени. Обычно они используются в паре: первое получает тип значения, второе формирует тип для сравнения.

Как проверить, что переменная — документ любого вида?

Используйте Документы.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)). Проверка вернёт Истина для ссылки на документ любого вида, присутствующего в конфигурации, и не потребует перечислять все виды вручную.

Почему ТипЗнч возвращает СправочникОбъект вместо СправочникСсылка?

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

Как узнать тип реквизита, не имея значения?

Через метаданные: Метаданные.Документы.ИмяДокумента.Реквизиты.ИмяРеквизита.Тип вернёт описание типов, метод Типы() которого перечислит все допустимые типы реквизита, включая составные.

Является ли Неопределено ссылочным типом?

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

Итог

Что важно запомнить

Для точного сравнения типа используйте ТипЗнч() + Тип(), для универсальной проверки ссылочности — методы ТипВсеСсылки() менеджеров объектов, для определения вида объекта — Значение.Метаданные().ПолноеИмя(). Не путайте ссылочный и объектный типы, проверяйте значение до вызова Метаданные() и помните, что перечисления тоже ссылочные.