Разработка и Конфигурация · 11 мин
Как проверить тип документа в 1С
Как проверить тип документа в 1С: ТипЗнч, Тип(), Метаданные(), сравнение в запросе и на форме. Примеры кода, типичные ошибки и ответы на вопросы.
Проверка типа документа — одна из самых частых задач при доработке конфигураций 1С: она нужна в обработчиках проведения, подписках на события, при заполнении печатных форм и в произвольных алгоритмах. Ошибка в определении типа приводит к тому, что код выполняется не для тех объектов или падает с ошибкой обращения к несуществующему реквизиту.
В платформе 1С:Предприятие 8 есть несколько способов узнать тип документа: функции ТипЗнч() и Тип(), объект метаданных, сравнение по имени типа и проверка через запрос. Каждый способ имеет свои ограничения: один работает только с конкретным значением, другой позволяет сравнить типы без обращения к данным, третий удобен в запросах.
Ниже разобраны рабочие приёмы с примерами кода, различия для ссылок и объектов, а также типичные ошибки, из-за которых проверка «вроде бы написана правильно», но не срабатывает.
Как устроены типы документов в 1С
Для каждого вида документов платформа автоматически создаёт набор типов: ДокументСсылка (ссылка на запись в базе), ДокументОбъект (объект в памяти с доступом к реквизитам и методам), ДокументВыборка и ДокументСписок. Когда вы пишете проверку типа, важно понимать, с чем работает код — со ссылкой или с объектом, потому что это разные типы.
Например, переменная, полученная через Документы.РеализацияТоваровУслуг.НайтиПоНомеру(), содержит тип ДокументСсылка.РеализацияТоваровУслуг. А после вызова метода ПолучитьОбъект() та же переменная будет содержать ДокументОбъект.РеализацияТоваровУслуг. Проверка «на ссылку» для объекта вернёт Ложь, и наоборот — это самая частая причина «неработающей» проверки.
Имя типа строится по шаблону: категория («ДокументСсылка» или «ДокументОбъект»), точка и имя вида документа, как оно задано в конфигураторе. Если вид документа называется «ПоступлениеТоваровУслуг», полное имя типа ссылки — «ДокументСсылка.ПоступлениеТоваровУслуг».
Проверка типа через ТипЗнч() и Тип()
Классическая конструкция выглядит так:
Если ТипЗнч(ДокументСсылка) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
// код для реализации
КонецЕсли;
Функция ТипЗнч() принимает любое значение и возвращает его тип. Функция Тип() создаёт объект типа по строковому имени. Сравнение двух объектов «Тип» выполняется строго: совпадают и категория, и имя вида.
У этого способа есть важная особенность: если в конфигурации нет документа с указанным именем (например, код писался под другую конфигурацию или документ переименовали), вызов Тип("ДокументСсылка.Несуществующий") вызовет исключение в момент выполнения. Поэтому в универсальных модулях, которые должны работать в разных конфигурациях, такой вызов оборачивают в Попытка...Исключение или заменяют проверкой через метаданные.
Проверка через метаданные объекта
У ссылок и объектов есть метод Метаданные(), который возвращает описание объекта конфигурации. Через него можно получить имя вида документа и сравнить со строкой:
Если ДокументСсылка.Метаданные().Имя = "РеализацияТоваровУслуг" Тогда
// код
КонецЕсли;
Такой подход удобен в подписках на события, где источником может быть любой документ: сначала проверяют, что источник вообще документ, затем — его вид. Для проверки принадлежности к категории используют Метаданные.Документы.Содержит():
Если Метаданные.Документы.Содержит(Источник.Метаданные()) Тогда
// источник — документ
КонецЕсли;
Преимущество способа — безопасность: строковое сравнение имён не вызывает исключения, если вида документа нет в конфигурации. Недостаток — сравнение строк чуть медленнее сравнения типов и подвержено ошибкам в написании имени, которые компилятор не отловит.
Проверка в подписках на события
В подписке на событие «ПриЗаписи» или «ОбработкаПроведения» источник — это ДокументОбъект. Типичный шаблон проверки:
Если ТипЗнч(Источник) <> Тип("ДокументОбъект.ЗаказПокупателя") Тогда
Возврат;
КонецЕсли;
Однако правильнее ограничивать состав подписки в конфигураторе, отметив только нужные виды документов в свойстве «Источник». Тогда проверка в коде не нужна вовсе, а обработчик не будет вызываться лишний раз. Программная проверка оправдана, когда логика внутри обработчика разветвляется по видам документов.
Проверка типа в запросе
Когда тип нужно проверить при выборке данных, используют язык запросов. Есть два инструмента: оператор ССЫЛКА для проверки вида документа и функция ТИПЗНАЧЕНИЯ() для сравнения с конкретным типом.
ВЫБРАТЬ
Состав.Документ
ИЗ
РегистрСведений.СоставГруппы КАК Состав
ГДЕ
Состав.Документ ССЫЛКА Документ.РеализацияТоваровУслуг
Условие ССЫЛКА работает только для полей ссылочного типа и проверяет принадлежность к конкретному виду. Если поле составного типа (например, документ-основание может быть разных видов), это самый чистый способ отфильтровать записи на стороне СУБД без выборки лишних данных.
Функция ТИПЗНАЧЕНИЯ(Поле) возвращает тип значения, её сравнивают с ТИП(Документ.РеализацияТоваровУслуг). На практике для ссылок оператор ССЫЛКА читается проще и обычно предпочтительнее.
Сравнение вариантов
Подходит для точной проверки в коде. Ограничение: падает с ошибкой, если вида документа нет в конфигурации.
Подходит для универсальных модулей и подписок. Ограничение: сравнение строк, опечатку не отловит компилятор.
Подходит для фильтрации выборок. Ограничение: работает только со ссылочными полями.
Подходит для проверки «это вообще документ?». Не различает вид документа.
Как узнать тип значения в отладчике и на форме
Во время разработки быстрее всего узнать тип переменной в отладчике: установите точку останова, остановитесь на нужной строке и посмотрите значение в табло — платформа покажет тип рядом со значением. Альтернатива — временно вывести тип в сообщение:
Сообщить(ТипЗнч(МояПеременная));
На управляемой форме документа тип объекта доступен через реквизит формы: если основной реквизит называется «Объект», то Объект.Ссылка — это ссылка документа, и к ней применимы все описанные проверки. В обработчиках формы, привязанных к конкретному виду документа, отдельная проверка типа обычно не нужна — форма и так открывается только для своего вида.
- 1Определите, что содержит переменная: ссылку или объект (посмотрите в отладчике).
- 2Выберите способ: ТипЗнч() для точной проверки, Метаданные().Имя для универсального кода, ССЫЛКА для запроса.
- 3Напишите проверку с учётом категории типа: ДокументСсылка или ДокументОбъект.
- 4Протестируйте на документе нужного вида и на документе другого вида — оба случая.
- 5Проверьте поведение при пустой ссылке и значении Неопределено.
Особые случаи и ограничения
Проверка типа не защищает от пустых значений. Если переменная содержит Неопределено или пустую ссылку другого вида, ТипЗнч() честно вернёт соответствующий тип, и сравнение даст Ложь. Но если дальше по коду вы обращаетесь к реквизитам через точку, предварительно стоит проверить ЗначениеЗаполнено().
В составных типах (когда реквизит может хранить ссылки на несколько видов документов) проверку типа делают перед обращением к специфичным реквизитам. Например, у документа-основания реквизит «Склад» есть не во всех видах — без проверки типа обращение вызовет ошибку «Поле объекта не обнаружено».
Внешние компоненты, расширения и код, выполняемый в разных конфигурациях, требуют осторожности с Тип("..."): вызов с несуществующим именем прерывает выполнение. В таких случаях используют сравнение имён через метаданные или оборачивают код в попытку.
Типичные ошибки при проверке типа
Первая и самая распространённая ошибка — путаница между ссылкой и объектом. Код пишут под ДокументСсылка, а в переменной оказывается ДокументОбъект (или наоборот). Проверка молча возвращает Ложь, и ветка кода просто не выполняется — без какой-либо ошибки. Диагностируется выводом ТипЗнч() в отладчике.
Вторая ошибка — опечатка в строковом имени типа при проверке через Метаданные().Имя. Платформа не проверяет такие строки при компиляции модуля, поэтому ошибка всплывает только в рантайме и только когда выполнится нужная ветка. Снижает риск вынос имён в константы модуля.
Третья ошибка — использование Тип("ДокументСсылка....") в коде, который должен работать в конфигурациях без этого документа. Исключение возникает в момент вызова Тип(), даже если сама проверка должна была вернуть Ложь.
Как проверить результат
Код выполняется для целевого вида
Код не выполняется — вероятно, несовпадение ссылка/объект
Проверка возвращает Ложь, ошибок нет
Исключение или ложное срабатывание
Код корректно пропускает такие значения
Ошибка обращения к метаданным или реквизитам
FAQ
Чем отличается ДокументСсылка от ДокументОбъект?
Ссылка — это лёгкий указатель на запись в базе, через неё доступны только стандартные реквизиты (номер, дата) и данные, получаемые обращением через точку с обращением к БД. Объект — это полная копия документа в памяти с возможностью изменения и записи. Это разные типы, и проверка ТипЗнч() их различает.
Как проверить, что значение — вообще любой документ?
Используйте Метаданные.Документы.Содержит(Значение.Метаданные()) — вернёт Истина для ссылок и объектов любого вида документов. Предварительно убедитесь, что значение не Неопределено и имеет метод Метаданные().
Почему ТипЗнч() = Тип("...") выдаёт ошибку?
Если ошибка возникает в момент вызова Тип(), значит, в конфигурации нет документа с таким именем — проверьте написание и наличие вида документа в конфигураторе. Для кода, работающего в разных конфигурациях, замените проверку на сравнение Метаданные().Имя со строкой.
Как проверить тип документа в запросе с составным полем?
Используйте условие «Поле ССЫЛКА Документ.ИмяВида» — оно отфильтрует записи, где поле содержит ссылку нужного вида. Для сравнения типов есть также функция ТИПЗНАЧЕНИЯ(Поле) = ТИП(Документ.ИмяВида), но ССЫЛКА обычно читабельнее.
Нужно ли проверять тип в обработчике формы документа?
Как правило, нет: форма привязана к конкретному виду документа и открывается только для него. Проверка типа нужна в общих модулях, подписках на события и универсальных обработках, куда значение может прийти из разных источников.
Что быстрее: сравнение типов или сравнение имён через метаданные?
Сравнение объектов «Тип» выполняется быстрее, чем получение метаданных и сравнение строк, но в типовых задачах разница незаметна. Выбирайте способ по надёжности и читаемости кода, а не по производительности.
Что важно запомнить
Для проверки типа документа используйте ТипЗнч() в паре с Тип() для точной проверки, Метаданные().Имя — для универсального кода, оператор ССЫЛКА — в запросах. Всегда учитывайте разницу между ДокументСсылка и ДокументОбъект и тестируйте проверку на документах разных видов, включая пустые значения.