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