Определяем, на что указывает ссылка в 1С: справочник, документ или что-то ещё

· 8 мин

Содержание

В коде тип ссылки в 1С проверяют сравнением ТипЗнч(Значение) = Тип("СправочникСсылка.Номенклатура"), а в запросе — оператором ССЫЛКА или функцией ТИПЗНАЧЕНИЯ(). Пользователю без конфигуратора достаточно открыть объект и нажать Shift+F11: в полученной навигационной ссылке вида e1cib/data/Документ.РеализацияТоваровУслуг?ref=… часть до знака вопроса и есть тип.

Способы ниже работают одинаково в любой конфигурации на платформе 8.3: Бухгалтерии, ЗУП, УТ, ERP. Различаются только имена объектов метаданных, а не приёмы.

Ссылка в 1С и её типы: что именно мы проверяем

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

Ссылочные типы в 1С 8.3:

  • 📁 СправочникСсылка.<Имя> — элементы справочников: контрагенты, номенклатура, договоры;
  • 📄 ДокументСсылка.<Имя> — документы: реализация, поступление, начисление зарплаты;
  • 🔢 ПеречислениеСсылка.<Имя> — значения перечислений: ставки НДС, виды операций;
  • 🧾 ПланСчетовСсылка.<Имя> — счета: в БП это ПланСчетовСсылка.Хозрасчетный;
  • 🧩 ПланВидовХарактеристикСсылка.<Имя> — виды субконто, дополнительные реквизиты;
  • 🧮 ПланВидовРасчетаСсылка.<Имя> — виды начислений и удержаний в зарплатных решениях;
  • 🔄 ПланОбменаСсылка.<Имя>, БизнесПроцессСсылка.<Имя>, ЗадачаСсылка.<Имя>.

Записи регистров ссылками не являются. У них нет GUID, их адресует набор измерений.

Вопрос «какой тип у ссылки» возникает там, где поле может хранить значения разных типов. Это реквизиты составного типа: Регистратор у регистров, Субконто1…3 в проводках, Основание у документов, поля с типом ЛюбаяСсылка или определяемым типом.

Узнать тип ссылки в интерфейсе 1С без конфигуратора

Пользователю тип чаще всего нужен, чтобы понять, откуда взялась строка в отчёте или что за объект стоит в поле.

Через навигационную ссылку

  1. Откройте объект двойным щелчком: из списка, отчёта или поля формы.
  2. Нажмите Shift+F11 или значок-цепочку в заголовке формы.
  3. Скопируйте текст ссылки. Он выглядит так:
e1cib/data/Справочник.Контрагенты?ref=9a3b00155d0a1f0111ee4c2b7d3e5f10

Фрагмент Справочник.Контрагенты — вид объекта и его имя в метаданных. Он не зависит от того, как объект назван на экране. В интерфейсе вы видите синоним вроде «Реализация (акт, накладная, УПД)», а в ссылке — техническое имя РеализацияТоваровУслуг.

Эту же ссылку можно отправить коллеге или программисту. Он откроет именно этот объект, а не будет искать его по номеру и дате.

Через поле составного типа

Если поле допускает несколько типов, при нажатии кнопки выбора 1С сначала откроет окно со списком типов. Этот список и показывает, что вообще может лежать в поле. Текущий тип видно по заголовку формы, которая открывается из этого поля.

Битая ссылка на экране

Если вместо значения в поле стоит <Объект не найден> (147:8f3a00155d0a1f01…), ссылка указывает на удалённую запись. Число до двоеточия — внутренний номер таблицы, по нему тип вручную не прочитать. Тип такой ссылки определяют программно, об этом ниже.

Проверка типа ссылки в конфигураторе и отладчике

Тип реквизита в свойствах

  1. Откройте ветку объекта в дереве конфигурации.
  2. Дважды щёлкните реквизит, откроется палитра свойств.
  3. Посмотрите поле «Тип». При отмеченном флажке «Составной тип данных» поле покажет весь перечень допустимых типов.

Если вместо списка стоит имя определяемого типа, откройте его в ветке Общие → Определяемые типы: там перечислены конкретные ссылочные типы.

Кто ссылается на объект

В контекстном меню объекта метаданных есть команда «Поиск ссылок на объект». Она показывает, в каких реквизитах, табличных частях и регистрах используется тип ссылки. Это быстрый способ понять, где искать составные поля, которые придётся проверять в коде.

Тип значения во время выполнения

В отладчике поставьте точку останова и откройте окно «Вычислить выражение» (Shift+F9). Введите имя переменной: в колонке «Тип» будет её текущий тип. Для составных полей можно сразу вычислить:

ТипЗнч(Движение.Регистратор)
Метаданные.НайтиПоТипу(ТипЗнч(Движение.Регистратор)).ПолноеИмя()

Программная проверка типа ссылки во встроенном языке

Проверка на один конкретный тип

Базовый приём — сравнить результат ТипЗнч() с типом, полученным через Тип():

Если ТипЗнч(Основание) = Тип("ДокументСсылка.ЗаказКлиента") Тогда
    ЗаполнитьПоЗаказу(Основание);
ИначеЕсли ТипЗнч(Основание) = Тип("ДокументСсылка.СчетНаОплатуПокупателю") Тогда
    ЗаполнитьПоСчету(Основание);
КонецЕсли;

Имя в Тип() — техническое, со словом Ссылка. Тип("Справочник.Номенклатура") в коде даст ошибку.

Проверка на несколько типов сразу

Когда допустимых типов три и больше, удобнее ОписаниеТипов:

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

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

Проверка вида объекта: «это вообще документ?»

Менеджеры коллекций умеют возвращать описание всех ссылочных типов своего вида:

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

То же есть у Перечисления, ПланыСчетов, ПланыВидовХарактеристик и других менеджеров.

Имя объекта по ссылке

Универсальный способ узнать вид и имя — через метаданные. Работает на сервере:

Функция ПолноеИмяПоСсылке(Ссылка) Экспорт
    МетаОбъект = Метаданные.НайтиПоТипу(ТипЗнч(Ссылка));
    Если МетаОбъект = Неопределено Тогда
        Возврат ""; // не ссылочный тип: Строка, Число, Неопределено
    КонецЕсли;
    Возврат МетаОбъект.ПолноеИмя(); // например, "Документ.РеализацияТоваровУслуг"
КонецФункции

Вид объекта достаётся из полного имени: СтрРазделить(ПолноеИмя, ".")[0] вернёт Документ или Справочник. У самой ссылки тоже есть метод Метаданные(), но если тип заранее неизвестен и значение может оказаться строкой, надёжнее Метаданные.НайтиПоТипу().

Готовые функции БСП

В конфигурациях на Библиотеке стандартных подсистем (БП 3.0, ЗУП 3.1, УТ 11, ERP) есть общий модуль ОбщегоНазначения:

ФункцияЧто делает
ОбщегоНазначения.ЭтоСсылка(Тип)Истина, если переданный тип ссылочный
ОбщегоНазначения.СсылкаСуществует(Ссылка)Истина, если запись по ссылке есть в базе
ОбщегоНазначения.ИмяТаблицыПоСсылке(Ссылка)Вернёт имя таблицы вида Справочник.Контрагенты

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

Тип ссылки в запросе: ССЫЛКА и ТИПЗНАЧЕНИЯ

В запросе тип пишется без кавычек и без слова Ссылка: Документ.РеализацияТоваровУслуг, а не "ДокументСсылка.РеализацияТоваровУслуг".

Отбор проводок только по документам реализации:

ВЫБРАТЬ
    Хозрасчетный.Период,
    Хозрасчетный.Регистратор,
    Хозрасчетный.Сумма
ИЗ
    РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
ГДЕ
    Хозрасчетный.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг

Тип как отдельная колонка и сравнение через ТИПЗНАЧЕНИЯ():

ВЫБРАТЬ
    Хозрасчетный.Регистратор,
    ТИПЗНАЧЕНИЯ(Хозрасчетный.Регистратор) КАК ТипРегистратора
ИЗ
    РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
ГДЕ
    ТИПЗНАЧЕНИЯ(Хозрасчетный.Регистратор) = ТИП(Документ.ПоступлениеТоваровУслуг)

Результат ТИПЗНАЧЕНИЯ() в коде сравнивают так же, как обычно: Выборка.ТипРегистратора = Тип("ДокументСсылка.ПоступлениеТоваровУслуг").

Чтобы обратиться к реквизиту, который есть только у одного из типов, поле приводят через ВЫРАЗИТЬ:

ВЫРАЗИТЬ(Хозрасчетный.Субконто1 КАК Справочник.Контрагенты).ИНН КАК ИНН

Для значений другого типа такое выражение вернёт NULL, ошибки не будет.

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

Составные поля и динамические списки: где тип заранее неизвестен

Под «динамическими» ссылками обычно понимают два случая: значение в поле составного типа и строку динамического списка на форме. В обоих тип узнают в момент работы, а не по описанию реквизита.

Текущая строка динамического списка

На клиенте доступны ТипЗнч() и Тип(), а глобальный контекст Метаданные в тонком клиенте недоступен. Проверку вида объекта по метаданным переносите в серверную процедуру:

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

Если список строится по журналу документов или произвольному запросу, в поле Ссылка могут оказаться документы разных видов. Сравнение по ТипЗнч здесь обязательно.

Пустая ссылка тоже имеет тип

ПустаяСсылка() справочника «Контрагенты» имеет тип СправочникСсылка.Контрагенты. Проверка типа пройдёт, а данных нет. Поэтому перед обращением к реквизитам добавляйте ЗначениеЗаполнено() или Значение.Пустая().

Битые ссылки

Ссылка на удалённый объект сохраняет и тип, и GUID. ТипЗнч() вернёт нормальный тип, но чтение реквизитов вернёт пустые значения. Существование проверяют на сервере функцией БСП СсылкаСуществует или запросом к таблице объекта.

Где проверка типа нужна на практике

Где вам нужно узнать тип ссылки?

Типовые задачи, которые решаются этими приёмами:

  • 📌 Заполнение на основании. В обработчике ОбработкаЗаполнения параметр ДанныеЗаполнения бывает ссылкой на заказ, счёт или структурой. Без проверки типа документ заполнится не тем.
  • 📌 Анализ проводок по субконто. В Субконто1 счёта 62 лежит контрагент, а у счёта 41 — номенклатура. Отчёт, который читает ИНН, должен сначала убедиться, что перед ним контрагент.
  • 📌 Групповая обработка. Обработка, принимающая массив ссылок из разных списков, раскладывает их по видам через Метаданные.НайтиПоТипу().
  • 📌 Поиск источника ошибки. Сообщение «Поле объекта не обнаружено» при обращении к реквизиту через точку часто значит, что в составном поле оказался не тот тип.

Частые ошибки при проверке типа ссылки

  • ⚠️ Сравнение по строке. Строка(ТипЗнч(Х)) = "Контрагенты" зависит от синонима. Переименовали объект или включили другой язык интерфейса — проверка сломалась. Сравнивайте с Тип().
  • ⚠️ Опечатка в имени типа. Тип("СправочникСсылка.Контрагент") при выполнении упадёт с ошибкой «Тип не определен». Синтаксический контроль её не ловит, имя берите копированием из дерева метаданных.
  • ⚠️ Синтаксис запроса в коде и наоборот. Тип(Справочник.Номенклатура) без кавычек — это язык запросов. Во встроенном языке нужны кавычки и слово Ссылка.
  • ⚠️ Обращение к Метаданные на клиенте. В тонком и веб-клиенте это ошибка. Выносите такую проверку в &НаСервере или &НаСервереБезКонтекста.
  • ⚠️ ПолучитьОбъект() ради типа. Метод читает объект целиком с табличными частями. Для проверки типа он не нужен: тип уже хранится в ссылке.
  • ⚠️ Реквизит через точку без проверки. Регистратор.Контрагент упадёт, если регистратором окажется документ без такого реквизита. Сначала проверка типа, потом обращение.

Частые вопросы

Чем ТипЗнч отличается от Тип?
ТипЗнч(Значение) возвращает тип переданного значения. Тип("ИмяТипа") создаёт тип по имени. Для проверки их сравнивают между собой.
Как получить тип ссылки в виде английского имени, например CatalogRef?
Функция XMLТипЗнч(Значение).ИмяТипа вернёт имя вида CatalogRef.Контрагенты или DocumentRef.РеализацияТоваровУслуг. Это пригодится при обмене данными и разборе XML.
Можно ли проверить тип ссылки в отчёте на СКД?
Да. В тексте запроса набора данных добавьте поле ТИПЗНАЧЕНИЯ(Поле) или отбор через ССЫЛКА. Дальше полем можно отбирать и группировать.
Почему проверка типа проходит, а реквизиты пустые?
Ссылка либо пустая, либо битая: объект удалён, а ссылка на него осталась. Проверьте ЗначениеЗаполнено() и существование объекта в базе.
Как проверить, что значение вообще ссылка, а не строка или число?
В конфигурациях на БСП вызовите ОбщегоНазначения.ЭтоСсылка(ТипЗнч(Значение)). Без БСП подойдёт проверка Метаданные.НайтиПоТипу(ТипЗнч(Значение)) <> Неопределено на сервере.