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