К статье
Практический материал

Разработка и Конфигурация · 9 мин

1С: как проверить, существует ли реквизит у объекта

Как в 1С проверить существование реквизита объекта через метаданные: метод Найти, проверка табличных частей, типовые ошибки и готовые примеры кода.

Проверка существования реквизита — типовая задача при написании универсального кода в 1С: обработок, работающих с разными конфигурациями, обменов данными, расширений. Если обратиться к несуществующему реквизиту напрямую, платформа выдаст ошибку «Поле объекта не обнаружено», и выполнение прервётся.

Правильный способ — проверить наличие реквизита через коллекцию метаданных объекта до обращения к нему. Метод Найти() возвращает описание реквизита или Неопределено, если такого реквизита нет. Это безопасно и работает на любой конфигурации.

Ниже разобраны основные сценарии: проверка реквизита справочника и документа, реквизитов табличных частей, работа с расширениями конфигурации, а также типичные ошибки, из-за которых проверка ведёт себя неожиданно.

Базовый способ: метод Найти() коллекции метаданных

У любого объекта конфигурации (справочника, документа, регистра) есть метод Метаданные(), возвращающий его описание в метаданных. Коллекция Реквизиты содержит все дополнительные реквизиты объекта, а метод Найти() ищет реквизит по имени.

Если Объект.Метаданные().Реквизиты.Найти("КомментарийДляКлиента") <> Неопределено Тогда

ЗначениеРеквизита = Объект.КомментарийДляКлиента;

Иначе

ЗначениеРеквизита = "";

КонецЕсли;

Метод Найти() возвращает объект описания метаданного реквизита либо Неопределено. Сравнение с Неопределено — единственно корректная проверка результата. Не используйте сравнение с пустой строкой или булевым значением.

Проверка стандартных реквизитов

Стандартные реквизиты платформа создаёт автоматически: у справочников это «Ссылка», «Код», «Наименование», «Владелец», «Родитель», у документов — «Ссылка», «Дата», «Номер», «Проведен». Состав зависит от настроек объекта: например, реквизит «Владелец» есть только если у справочника заданы владельцы.

Для проверки стандартного реквизита используйте коллекцию СтандартныеРеквизиты:

МетаданныеОбъекта = Справочники.Номенклатура.ПустаяСсылка().Метаданные();

Если МетаданныеОбъекта.СтандартныеРеквизиты.Найти("Владелец") <> Неопределено Тогда

// у справочника есть владелец

КонецЕсли;

Если нужно проверить реквизит независимо от его вида — стандартный или дополнительный — выполните поиск в обеих коллекциях последовательно.

Проверка реквизита табличной части

Реквизиты табличных частей находятся на два уровня глубже: сначала проверяется существование самой табличной части, затем — реквизита внутри неё. Пропуск первого шага приведёт к ошибке, если табличной части нет в объекте.

МетаданныеОбъекта = Объект.Метаданные();

ТабличнаяЧасть = МетаданныеОбъекта.ТабличныеЧасти.Найти("Товары");

Если ТабличнаяЧасть <> Неопределено Тогда

Если ТабличнаяЧасть.Реквизиты.Найти("Серия") <> Неопределено Тогда

// реквизит «Серия» существует в табличной части «Товары»

КонецЕсли;

КонецЕсли;

Такой двухуровневый поиск особенно важен в обработках обмена, где структура документов в базе-источнике и базе-приёмнике может отличаться.

Порядок действий
  1. 1
    Получите описание метаданных: Объект.Метаданные()
  2. 2
    Найдите нужную коллекцию: Реквизиты, СтандартныеРеквизиты или ТабличныеЧасти
  3. 3
    Вызовите Найти("ИмяРеквизита")
  4. 4
    Сравните результат с Неопределено
  5. 5
    Только после успешной проверки обращайтесь к реквизиту объекта

Проверка по имени объекта, когда объекта нет под рукой

Иногда нужно проверить реквизит, не имея экземпляра объекта — только имя вида объекта. В этом случае метаданные получают через глобальную коллекцию Метаданные:

МетаданныеДокумента = Метаданные.Документы.Найти("РеализацияТоваровУслуг");

Если МетаданныеДокумента <> Неопределено Тогда

Если МетаданныеДокумента.Реквизиты.Найти("Соглашение") <> Неопределено Тогда

// реквизит существует

КонецЕсли;

КонецЕсли;

Обратите внимание: сначала проверяется существование самого вида документа через Метаданные.Документы.Найти(). Это критично для кода, который должен работать в разных конфигурациях, где нужный объект может отсутствовать целиком.

Альтернатива — обращение через менеджер объекта: Документы.РеализацияТоваровУслуг.ПустаяСсылка().Метаданные(). Но этот вариант безопасен, только если вид объекта гарантированно существует, иначе возникнет ошибка компиляции или выполнения.

Маршрут решения

Как выбрать способ проверки

Есть экземпляр объекта (ссылка или объект)Используйте Объект.Метаданные().Реквизиты.Найти()
Известно только имя вида объектаИспользуйте Метаданные.Документы.Найти() с проверкой на Неопределено
Реквизит стандартный (Владелец, Родитель)Ищите в коллекции СтандартныеРеквизиты
Реквизит в табличной частиСначала найдите табличную часть, затем реквизит внутри неё

Особенности при работе с расширениями и дополнительными реквизитами

Реквизиты, добавленные через расширение конфигурации, видны в коллекции Реквизиты наравне с основными, если расширение подключено в текущем сеансе. Однако код, рассчитанный на такой реквизит, сломается при отключении расширения — поэтому проверка через Найти() обязательна.

Отдельный случай — дополнительные реквизиты и сведения (механизм БСП). Они не являются реквизитами объекта и не находятся через метаданные. Их наличие проверяется запросом к табличной части «ДополнительныеРеквизиты» объекта и к справочнику наборов дополнительных реквизитов. Путать эти механизмы — частая причина «не находится» существующий на форме реквизит.

Типичные ошибки и как их избежать

Первая ошибка — обращение к реквизиту до проверки. Даже если в текущей конфигурации реквизит есть, перенос обработки в другую базу приведёт к падению кода. Проверка должна стоять непосредственно перед обращением.

Вторая ошибка — поиск стандартного реквизита в коллекции Реквизиты. Например, «Владелец» там не найдётся, и код ошибочно решит, что реквизита нет. Всегда уточняйте, к какой коллекции относится реквизит: это видно в конфигураторе на закладке «Данные» объекта.

Третья ошибка — опечатка в имени реквизита. Имя передаётся строкой, и платформа не проверяет его при компиляции. Рекомендуется выносить имена в переменные или константы модуля, чтобы опечатка была видна в одном месте.

Типичные ошибки
01
Поиск стандартного реквизита в коллекции Реквизиты — результат всегда Неопределено
02
Обращение к реквизиту табличной части без проверки самой табличной части — ошибка выполнения
03
Сравнение результата Найти() с пустой строкой вместо Неопределено — условие работает неверно
04
Ожидание, что дополнительные реквизиты БСП видны в метаданных — их там нет

Проверка результата и отладка

Чтобы убедиться, что проверка работает правильно, выведите состав коллекции реквизитов в отладке. Цикл по МетаданныеОбъекта.Реквизиты с выводом имён покажет реальный список доступных реквизитов:

Для Каждого Реквизит Из Объект.Метаданные().Реквизиты Цикл

Сообщить(Реквизит.Имя);

КонецЦикла;

Если ожидаемого имени в списке нет, проверьте: не является ли реквизит стандартным, не находится ли он в табличной части, не добавлен ли он расширением, которое в текущем сеансе отключено, и не является ли он дополнительным реквизитом механизма БСП.

Контрольные точки

Как проверить результат

Результат Найти()
Норма

Возвращён объект описания метаданного

Тревожный признак

Неопределено — реквизита нет или ищется не в той коллекции

Обращение к реквизиту после проверки
Норма

Значение читается без ошибок

Тревожный признак

Ошибка «Поле объекта не обнаружено» — проверка пропущена или неверна

Вывод списка реквизитов циклом
Норма

Имя присутствует в списке

Тревожный признак

Имени нет — реквизит стандартный, дополнительный или в табличной части

Частые вопросы

Можно ли проверить реквизит через Попытка/Исключение?

Технически да, но это плохая практика: исключение перехватывает любые ошибки, а не только отсутствие реквизита, и работает медленнее. Проверка через метаданные — правильный и более быстрый способ.

Почему Найти() не находит реквизит, который виден на форме?

Скорее всего, это дополнительный реквизит механизма БСП или реквизит формы, а не объекта. Они не входят в метаданные объекта. Дополнительные реквизиты хранятся в табличной части «ДополнительныеРеквизиты» и проверяются запросом.

Как проверить реквизит у регистра сведений или накопления?

У регистров вместо реквизитов есть измерения, ресурсы и реквизиты — три отдельные коллекции метаданных: Измерения, Ресурсы, Реквизиты. Проверяйте нужную коллекцию методом Найти() аналогично.

Работает ли проверка в тонком клиенте и на сервере?

Метод Метаданные() и коллекции метаданных доступны на сервере и в толстом клиенте. В тонком и веб-клиенте обращение к метаданным ограничено — проверку следует выполнять в серверной процедуре.

Как проверить реквизит, если имя объекта приходит строкой?

Используйте Метаданные.НайтиПоПолномуИмени(\"Документ.РеализацияТоваровУслуг\") — метод вернёт описание метаданного или Неопределено. Далее работайте с коллекцией Реквизиты как обычно.

Итог

Что важно запомнить

Проверка существования реквизита выполняется через Метаданные().Реквизиты.Найти() со сравнением с Неопределено. Стандартные реквизиты ищутся в отдельной коллекции, реквизиты табличных частей — на втором уровне вложенности. Проверка всегда должна предшествовать обращению к реквизиту.