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