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

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

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

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

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

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

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

Что нужно понимать о типах документов в 1С

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

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

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

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

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

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

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

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

// логика для поступления

КонецЕсли;

Функция ТипЗнч() возвращает значение типа «Тип», описывающее переданное значение, а Тип() формирует эталон для сравнения. Сравнение выполняется по равенству — это быстрая операция, не обращающаяся к базе данных, поэтому такой способ безопасно использовать в циклах по большим выборкам.

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

bsl
Если ТипЗнч(ПараметрДокумент) = Тип("ДокументСсылка.СчетФактураВыданный") Тогда
    Сообщить("Это счёт-фактура");
КонецЕсли;

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

Проверка через метаданные: когда видов документов много

Когда ветвлений больше двух-трёх, цепочка ТипЗнч() становится громоздкой. Удобнее получить имя вида документа через метаданные и сравнивать строки или использовать структуру соответствий:

ИмяВида = Документ.Метаданные().Имя;

Если ИмяВида = "РеализацияТоваровУслуг" Тогда

// ...

КонецЕсли;

Метод Метаданные() работает и для ссылки, и для объекта, поэтому такой код универсален — он не зависит от того, в каком виде передан документ. Это основной аргумент в пользу метаданных при написании универсальных процедур в общих модулях.

Обратная сторона: обращение к метаданным чуть медленнее, чем сравнение типов, и сравнение строк не защищено от опечаток — ошибку в строке «РеализацияТоваровУслуг» платформа не заметит. Практический компромисс: для одной-двух проверок использовать ТипЗнч(), для массового ветвления — метаданные или Соответствие, где ключом служит тип.

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

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

Быстро и надёжно для 1–3 видов документов. Ограничение: различает ссылку и объект, нужно знать, что именно передаётся.

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

Универсально для ссылки и объекта, удобно при множестве видов. Ограничение: сравнение строк, опечатку платформа не отловит.

Соответствие типов

Оптимально для обхода больших выборок с десятками видов: тип проверяется один раз через Соответствие.Получить(). Требует инициализации заранее.

Проверка типа документа в запросе

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

ВЫБРАТЬ

Журнал.Ссылка

ИЗ

ЖурналДокументов.ЖурналОпераций КАК Журнал

ГДЕ

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

Условие ССЫЛКА фильтрует записи прямо на сервере СУБД и возвращает только документы нужного вида. Это предпочтительный способ, когда нужно отобрать документы определённого типа из составного поля или журнала.

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

Как определить тип документа на форме и в интерфейсе

Разработчику часто нужно просто посмотреть, документ какого вида он держит в руках, без написания кода. Самый быстрый способ в пользовательском режиме — вывести техническую информацию об объекте: в типовых конфигурациях на управляемых формах доступна команда «Ещё → Вывести список» для списков, а для отдельного объекта помогает стандартная обработка «Групповое изменение реквизитов» или внешние инструменты разработчика.

В коде формы тип текущего документа определяется через реквизит объекта:

ИмяВида = Объект.Ссылка.Метаданные().Имя;

// или для управляемой формы без обращения к данным:

ТипДокумента = ТипЗнч(Объект.Ссылка);

Обращение Объект.Ссылка.Метаданные() на управляемой форме безопасно: метаданные доступны по ссылке без загрузки всего документа из базы. А вот обращение к реквизитам через точку от ссылки (Объект.Ссылка.Номер) на тонком клиенте вызовет отдельное обращение к серверу — в циклах так делать нельзя.

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

Как убедиться, что проверка работает правильно

После написания проверки протестируйте её минимум на трёх наборах данных: документе целевого вида, документе другого вида и пустой/незаполненной ссылке. Пустая ссылка имеет тот же тип, что и заполненная: ТипЗнч(Документы.РеализацияТоваровУслуг.ПустаяСсылка()) вернёт «ДокументСсылка.РеализацияТоваровУслуг», поэтому проверка типа не заменяет проверку на пустоту через ЗначениеЗаполнено() или Ссылка.Пустая().

Для отладки удобно временно вывести тип через Сообщить():

Сообщить(ТипЗнч(ВходящийДокумент));

Сообщить(ВходящийДокумент.Метаданные().Имя);

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

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

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

Проверка на целевом документе
Норма

Условие срабатывает, ветка выполняется

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

Условие молчит — возможно, передан объект, а проверяется ссылка

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

Ветка не выполняется

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

Ложное срабатывание — проверьте имя типа в строке Тип()

Пустая ссылка
Норма

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

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

Логика считает пустую ссылку отсутствием документа нужного вида

Типичные ошибки и ограничения

Самая распространённая ошибка — сравнение ссылки со строкой: Если Документ = "РеализацияТоваровУслуг". Ссылка никогда не равна строке, такая проверка всегда даёт Ложь и молча ломает логику. Вторая частая проблема — путаница между именем документа и синонимом: пользователь видит «Реализация (акты, накладные)», а в метаданных имя другое.

Третья группа ошибок связана с контекстом исполнения. В модуле формы обычной формы доступен РеквизитФормы «ДокументОбъект», в управляемой — «Объект»; прямое копирование кода между ними ломает проверки. В серверных общих модулях с признаком «Вызов сервера» недоступен контекст формы, и тип нужно передавать параметром.

Наконец, помните про ограничение безопасного режима: если код выполняется в расширении или внешней обработке в безопасном режиме, обращение к метаданным работает, но динамическое обращение к документам по строковому имени через Документы[Имя] может быть ограничено настройками профиля безопасности кластера.

Типичные ошибки
01
Сравнение ссылки со строкой имени документа — условие всегда ложно, логика молча не работает
02
Проверка Тип("ДокументСсылка...") для значения, которое пришло как ДокументОбъект, — проверка не срабатывает в обработчиках записи
03
Опечатка в имени типа внутри Тип() — ошибка проявляется только при выполнении, а не при сохранении модуля
04
Использование ТИПЗНАЧЕНИЯ в условии запроса вместо ССЫЛКА на больших таблицах — лишние затраты производительности
05
Отсутствие отдельной проверки на пустую ссылку — пустая ссылка проходит проверку типа и ломает дальнейшую логику

Практические рекомендации по выбору способа

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

Если проверка типа повторяется в нескольких местах конфигурации, вынесите её в функцию общего модуля, например ЭтоДокументРеализации(Документ). Это централизует имя типа в одном месте: при переименовании документа в метаданных править придётся одну функцию, а не разбросанные по модулям строки.

Маршрут решения

Как выбрать действие

Нужно проверить один-два вида документов в кодеИспользуйте ТипЗнч(Значение) = Тип("ДокументСсылка.Имя")
Переменная может быть и ссылкой, и объектомСравнивайте Значение.Метаданные().Имя со строкой имени
Нужно отобрать документы вида из журнала или составного поляИспользуйте в запросе условие ССЫЛКА Документ.Имя
Проверка выполняется в цикле по большой выборке для многих видовЗаранее постройте Соответствие типов и ищите через Найти/Получить
Код работает в подписке на событие для разных объектовСначала проверьте Метаданные.Документы.Содержит(), затем конкретный вид

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

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

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

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

Это разные типы. Ссылка — идентификатор записи в базе, объект — загруженные данные с возможностью изменения. Проверка на «ДокументСсылка.Имя» не сработает для объекта и наоборот. Универсальная проверка — через Метаданные().Имя, она одинаково работает для обоих.

Как проверить, что переменная вообще содержит документ, а не справочник?

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

Почему ТипЗнч возвращает тип, но сравнение с Тип() даёт Ложь?

Чаще всего причина в несовпадении имени в строке Тип() с реальным именем метаданных или в том, что проверяется объект, а эталон задан как ссылка. Выведите ТипЗнч(Значение) через Сообщить() и сравните с тем, что ожидаете.

Как проверить тип документа в динамическом списке на форме?

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

Можно ли проверить тип по имени, полученному строкой?

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

Влияет ли проверка типа на производительность?

Сравнение ТипЗнч() с Тип() — очень быстрая операция в памяти. Замедление возможно в запросах при использовании ТИПЗНАЧЕНИЯ в условии по большим таблицам и при обращении к реквизитам ссылки через точку в цикле — это порождает отдельные обращения к базе.

Итог

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

Проверка типа документа строится на трёх приёмах: ТипЗнч() с Тип() для пары видов, Метаданные().Имя для универсального кода и ССЫЛКА в запросах. Различайте ссылку и объект, проверяйте пустоту отдельно и тестируйте условие на документах каждого ожидаемого вида.