В процессе разработки универсальных алгоритмов, механизмов выгрузки данных или при создании гибких отчетов в 1С часто возникает задача: быстро и надежно определить, относится ли конкретный объект (ссылка, объект или само описание метаданных) к классу документов. Несмотря на кажущуюся простоту, существует несколько способов реализации этой проверки, каждый из которых имеет свои нюансы производительности и области применения. В этой статье мы подробно разберем все доступные методы, от классической проверки коллекций до высокопроизводительного анализа строк.
Наиболее универсальный и «чистый» с точки зрения архитектуры платформы способ — использование метода Содержит() у коллекции Метаданные.Документы. Этот метод принимает на вход объект метаданных и возвращает истину, если объект принадлежит к этой коллекции.
Рассмотрим пример кода, который позволяет проверить произвольный объект:
// Получаем метаданные объекта (ссылки или самого объекта)
МетаданныеОбъекта = СсылкаНаОбъект.Метаданные();
// Проверяем наличие объекта в коллекции документов
Если Метаданные.Документы.Содержит(МетаданныеОбъекта) Тогда
Сообщить("Это документ");
Иначе
Сообщить("Это другой тип объекта (справочник, регистр и т.д.)");
КонецЕсли;
Проанализируем преимущества этого подхода: он работает корректно как для объектов, созданных в памяти, так и для ссылок, уже записанных в базу данных. Однако стоит помнить, что вызов метода Метаданные() может быть относительно «дорогим» при массовой обработке тысяч объектов в цикле.
Если у нас есть описание типа (Тип) или мы работаем со ссылкой, можно использовать метод менеджера Документы.ТипВсеСсылки(). Этот метод возвращает описание типов, включающее все документы, определенные в конфигурации.
Разберем, как это работает на практике:
// Проверка через описание типов всех документов
Если Документы.ТипВсеСсылки().СодержитТип(ТипЗнч(ПроверяемоеЗначение)) Тогда
// Логика для документа
КонецЕсли;
Этот способ удобен тем, что нам не нужно обращаться к конкретному объекту метаданных. Мы работаем напрямую с типами платформы. Важный нюанс: этот метод эффективен, когда вам нужно проверить, является ли «тип данных» документальным, даже если самого объекта (ссылки) еще не существует или это пустая ссылка.
Когда важна максимальная скорость выполнения (например, в высоконагруженных циклах обработки данных), обращение к коллекциям метаданных может замедлять работу. В таких случаях мы рекомендуем использовать строковую проверку полного имени объекта. У любого объекта метаданных есть свойство ПолноеИмя(), которое для документов всегда начинается с префикса Документ..
Посмотрим на пример реализации:
МетаданныеОбъекта = ПроверяемыйОбъект.Метаданные();
Если СтрНачинаетсяС(МетаданныеОбъекта.ПолноеИмя(), "Документ.") Тогда
// Это точно документ
КонецЕсли;
Данный метод считается одним из самых быстрых, так как строковые операции в 1С оптимизированы. Мы просто проверяем начало строки, не заставляя платформу обходить дерево объектов или сравнивать сложные типы данных.
Если ваша конфигурация разработана на базе БСП (что справедливо для большинства современных решений, таких как ERP, УТ 11, БП 3.0), разработчики уже предусмотрели готовые инструменты в общем модуле ОбщегоНазначения. Функция ЭтоДокумент() инкапсулирует в себе оптимальные проверки.
Пример использования функции из состава БСП:
// Проверка через типовой функционал БСП
Если ОбщегоНазначения.ЭтоДокумент(МетаданныеОбъекта) Тогда
// Обработка документа
КонецЕсли;
Использование этого метода повышает читаемость кода и гарантирует, что проверка будет выполнена максимально корректно с учетом особенностей текущей версии платформы.
Существует еще один «хитрый» способ, упомянутый опытными разработчиками: проверка родителя в дереве метаданных. Хотя этот метод менее популярен, он наглядно показывает иерархию объектов в системе.
Если Ссылка.Метаданные().Родитель = Метаданные.Документы Тогда
// Объект является документом
КонецЕсли;
Однако будьте осторожны: этот метод может вести себя нестабильно в сложных ветках конфигурации, поэтому методы с использованием Содержит() или ПолноеИмя() являются более предпочтительными.
Давайте подведем итог и выясним, какой метод выбрать в зависимости от ситуации:
ПолноеИмя() с префиксом или заранее кэшируйте массив типов из Документы.ТипВсеСсылки().Типы() в повторно используемый модуль.Метаданные.Документы.Содержит() или функции БСП. Это делает код понятным для других разработчиков.XMLТипЗнч(). Для документов имя типа в XML часто содержит подстроку DocumentRef.Документы[ИмяОбъекта] <> Неопределено.Выяснив причину необходимости такой проверки, вы сможете выбрать наиболее производительный вариант. Помните, что работа с метаданными на сервере и клиенте может отличаться: старайтесь выполнять подобные проверки на стороне сервера, чтобы избежать лишних вызовов между уровнями системы.