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