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