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

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

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

Способ 1. Проверка через метод СодержитТип объекта ОписаниеТипов

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

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

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


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

    Если Значение = Неопределено Тогда
        Возврат Ложь;
    КонецЕсли;

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

    Если Справочники.ТипВсеСсылки().СодержитТип(ТипЗначения)
        Или Документы.ТипВсеСсылки().СодержитТип(ТипЗначения) Тогда
        Возврат Истина;
    КонецЕсли;

    Возврат Ложь;

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

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

Способ 2. Использование готовых функций Библиотеки стандартных подсистем (БСП)

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

Рассмотрим вызов стандартной функции:


Если ОбщегоНазначенияКлиентСервер.ЭтоСсылка(ПроверяемоеЗначение) Тогда
    // Выполняем действия со ссылочным объектом
КонецЕсли;

Преимущество этого подхода заключается в том, что функция ЭтоСсылка() корректно обрабатывает все ссылочные типы (включая перечисления, планы счетов, планы обмена, бизнес-процессы и задачи), проверяет входное значение на Неопределено и доступна в общем контексте тонкого клиента и сервера.

Способ 3. Определение через функцию XMLТип

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

Разберем механизм: для ссылочных данных сериализатор платформы формирует XML-тип с суффиксом Ref (например, CatalogRef.Номенклатура или DocumentRef.РеализацияТоваровУслуг). Если значение не относится к ссылочным типам, суффикс будет отсутствовать либо функция вернет Неопределено.

Посмотрим на реализацию проверки:


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

    ТипXML = XMLТип(ТипЗнч(Значение));
    Если ТипXML = Неопределено Тогда
        Возврат Ложь;
    КонецЕсли;

    Возврат Прав(ТипXML.ИмяТипа, 3) = "Ref";

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

Ошибочные и неоптимальные подходы: чего следует избегать

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

  1. Обращение через свойство «Ссылка» в конструкции Попытка — Исключение: конструкция вида Значение.Ссылка = Значение крайне неэффективна. При обращении через точку к свойству объектной сущности или битой ссылке платформа может инициировать неявный запрос к базе данных для считывания полей, что создает неоправданную нагрузку на СУБД.
  2. Прямой вызов Метаданные() без проверки типа: конструкция вида Значение.Метаданные() вызовет фатальную ошибку времени выполнения, если в переменную передано примитивное значение (число, строка, дата), Неопределено или системная коллекция (структура, массив, таблица значений).
  3. Поиск через Метаданные.НайтиПоТипу(): данный метод вернет объект метаданных не только для ссылок (СправочникСсылка), но и для объектных типов (СправочникОбъект), а также для выборок. Это не позволяет разграничить ссылку в базе данных и объект, находящийся в оперативной памяти.
  4. Контекстные ограничения: вызовы Справочники.ТипВсеСсылки() и обращение к объекту Метаданные доступны только на стороне сервера, во внешнем соединении или в толстом клиенте. Для тонкого клиента следует применять клиентские функции БСП либо передавать проверку на сервер.
← На главную