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

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

Как проверить тип документа в 1С

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

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

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

Ниже разобраны рабочие приёмы с примерами кода, различия для ссылок и объектов, а также типичные ошибки, из-за которых проверка «вроде бы написана правильно», но не срабатывает.

Как устроены типы документов в 1С

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

Например, переменная, полученная через Документы.РеализацияТоваровУслуг.НайтиПоНомеру(), содержит тип ДокументСсылка.РеализацияТоваровУслуг. А после вызова метода ПолучитьОбъект() та же переменная будет содержать ДокументОбъект.РеализацияТоваровУслуг. Проверка «на ссылку» для объекта вернёт Ложь, и наоборот — это самая частая причина «неработающей» проверки.

Имя типа строится по шаблону: категория («ДокументСсылка» или «ДокументОбъект»), точка и имя вида документа, как оно задано в конфигураторе. Если вид документа называется «ПоступлениеТоваровУслуг», полное имя типа ссылки — «ДокументСсылка.ПоступлениеТоваровУслуг».

Проверка типа через ТипЗнч() и Тип()

Классическая конструкция выглядит так:

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

// код для реализации

КонецЕсли;

Функция ТипЗнч() принимает любое значение и возвращает его тип. Функция Тип() создаёт объект типа по строковому имени. Сравнение двух объектов «Тип» выполняется строго: совпадают и категория, и имя вида.

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

Проверка через метаданные объекта

У ссылок и объектов есть метод Метаданные(), который возвращает описание объекта конфигурации. Через него можно получить имя вида документа и сравнить со строкой:

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

// код

КонецЕсли;

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

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

// источник — документ

КонецЕсли;

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

Проверка в подписках на события

В подписке на событие «ПриЗаписи» или «ОбработкаПроведения» источник — это ДокументОбъект. Типичный шаблон проверки:

Если ТипЗнч(Источник) <> Тип("ДокументОбъект.ЗаказПокупателя") Тогда

Возврат;

КонецЕсли;

Однако правильнее ограничивать состав подписки в конфигураторе, отметив только нужные виды документов в свойстве «Источник». Тогда проверка в коде не нужна вовсе, а обработчик не будет вызываться лишний раз. Программная проверка оправдана, когда логика внутри обработчика разветвляется по видам документов.

Проверка типа в запросе

Когда тип нужно проверить при выборке данных, используют язык запросов. Есть два инструмента: оператор ССЫЛКА для проверки вида документа и функция ТИПЗНАЧЕНИЯ() для сравнения с конкретным типом.

ВЫБРАТЬ

Состав.Документ

ИЗ

РегистрСведений.СоставГруппы КАК Состав

ГДЕ

Состав.Документ ССЫЛКА Документ.РеализацияТоваровУслуг

Условие ССЫЛКА работает только для полей ссылочного типа и проверяет принадлежность к конкретному виду. Если поле составного типа (например, документ-основание может быть разных видов), это самый чистый способ отфильтровать записи на стороне СУБД без выборки лишних данных.

Функция ТИПЗНАЧЕНИЯ(Поле) возвращает тип значения, её сравнивают с ТИП(Документ.РеализацияТоваровУслуг). На практике для ссылок оператор ССЫЛКА читается проще и обычно предпочтительнее.

Сравнение вариантов

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

Подходит для точной проверки в коде. Ограничение: падает с ошибкой, если вида документа нет в конфигурации.

Метаданные().Имя

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

ССЫЛКА в запросе

Подходит для фильтрации выборок. Ограничение: работает только со ссылочными полями.

Метаданные.Документы.Содержит()

Подходит для проверки «это вообще документ?». Не различает вид документа.

Как узнать тип значения в отладчике и на форме

Во время разработки быстрее всего узнать тип переменной в отладчике: установите точку останова, остановитесь на нужной строке и посмотрите значение в табло — платформа покажет тип рядом со значением. Альтернатива — временно вывести тип в сообщение:

Сообщить(ТипЗнч(МояПеременная));

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

Порядок действий при написании проверки
  1. 1
    Определите, что содержит переменная: ссылку или объект (посмотрите в отладчике).
  2. 2
    Выберите способ: ТипЗнч() для точной проверки, Метаданные().Имя для универсального кода, ССЫЛКА для запроса.
  3. 3
    Напишите проверку с учётом категории типа: ДокументСсылка или ДокументОбъект.
  4. 4
    Протестируйте на документе нужного вида и на документе другого вида — оба случая.
  5. 5
    Проверьте поведение при пустой ссылке и значении Неопределено.

Особые случаи и ограничения

Проверка типа не защищает от пустых значений. Если переменная содержит Неопределено или пустую ссылку другого вида, ТипЗнч() честно вернёт соответствующий тип, и сравнение даст Ложь. Но если дальше по коду вы обращаетесь к реквизитам через точку, предварительно стоит проверить ЗначениеЗаполнено().

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

Внешние компоненты, расширения и код, выполняемый в разных конфигурациях, требуют осторожности с Тип("..."): вызов с несуществующим именем прерывает выполнение. В таких случаях используют сравнение имён через метаданные или оборачивают код в попытку.

Типичные ошибки при проверке типа

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

Вторая ошибка — опечатка в строковом имени типа при проверке через Метаданные().Имя. Платформа не проверяет такие строки при компиляции модуля, поэтому ошибка всплывает только в рантайме и только когда выполнится нужная ветка. Снижает риск вынос имён в константы модуля.

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

Типичные ошибки
01
Сравнение с ДокументСсылка, когда в переменной ДокументОбъект — ветка кода молча не выполняется.
02
Опечатка в имени при сравнении Метаданные().Имя — ошибка не видна до выполнения кода.
03
Вызов Тип() с именем документа, отсутствующего в конфигурации, — исключение вместо Ложь.
04
Отсутствие проверки на Неопределено перед обращением к Метаданные() — ошибка «Значение не является значением объектного типа».
Контрольные точки

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

Ветка кода для нужного вида документа
Норма

Код выполняется для целевого вида

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

Код не выполняется — вероятно, несовпадение ссылка/объект

Документ другого вида
Норма

Проверка возвращает Ложь, ошибок нет

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

Исключение или ложное срабатывание

Пустое значение / Неопределено
Норма

Код корректно пропускает такие значения

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

Ошибка обращения к метаданным или реквизитам

FAQ

Чем отличается ДокументСсылка от ДокументОбъект?

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

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

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

Почему ТипЗнч() = Тип("...") выдаёт ошибку?

Если ошибка возникает в момент вызова Тип(), значит, в конфигурации нет документа с таким именем — проверьте написание и наличие вида документа в конфигураторе. Для кода, работающего в разных конфигурациях, замените проверку на сравнение Метаданные().Имя со строкой.

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

Используйте условие «Поле ССЫЛКА Документ.ИмяВида» — оно отфильтрует записи, где поле содержит ссылку нужного вида. Для сравнения типов есть также функция ТИПЗНАЧЕНИЯ(Поле) = ТИП(Документ.ИмяВида), но ССЫЛКА обычно читабельнее.

Нужно ли проверять тип в обработчике формы документа?

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

Что быстрее: сравнение типов или сравнение имён через метаданные?

Сравнение объектов «Тип» выполняется быстрее, чем получение метаданных и сравнение строк, но в типовых задачах разница незаметна. Выбирайте способ по надёжности и читаемости кода, а не по производительности.

Итог

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

Для проверки типа документа используйте ТипЗнч() в паре с Тип() для точной проверки, Метаданные().Имя — для универсального кода, оператор ССЫЛКА — в запросах. Всегда учитывайте разницу между ДокументСсылка и ДокументОбъект и тестируйте проверку на документах разных видов, включая пустые значения.