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

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

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

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

Во встроенном языке 1С 8 нет прямого оператора вида «ЕстьРеквизит», поэтому проверка наличия реквизита у справочника, документа или другого объекта выполняется косвенными способами. Чаще всего используют анализ метаданных объекта, попытку обращения через свойство с перехватом ошибки или проверку структуры строки табличной части. Выбор способа зависит от того, с чем вы работаете: с объектом данных, записью регистра, строкой динамического списка или произвольной структурой.

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

Ниже разобраны рабочие приёмы для основных сценариев: проверка через метаданные, безопасное обращение через «Попытка», анализ структур и таблиц значений, а также особенности проверки реквизитов табличных частей и в запросах.

Проверка реквизита через метаданные объекта

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

Типовой фрагмент кода выглядит так:

Функция ЕстьРеквизит(Объект, ИмяРеквизита)

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

Возврат МетаОбъект.Реквизиты.Найти(ИмяРеквизита) <> Неопределено;

КонецФункции

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

Для проверки стандартного реквизита код аналогичен:

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

// у объекта есть стандартный реквизит Код

КонецЕсли;

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

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

Функция ЕстьРеквизитТЧ(Объект, ИмяТЧ, ИмяРеквизита)

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

МетаТЧ = МетаОбъект.ТабличныеЧасти.Найти(ИмяТЧ);

Если МетаТЧ = Неопределено Тогда

Возврат Ложь; // нет самой табличной части

КонецЕсли;

Возврат МетаТЧ.Реквизиты.Найти(ИмяРеквизита) <> Неопределено;

КонецФункции

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

Проверка через перехват ошибки (Попытка/Исключение)

Когда тип объекта заранее неизвестен или метаданные недоступны (например, работа идёт со строкой таблицы значений или произвольным значением), применяют обращение к реквизиту внутри конструкции Попытка..Исключение.

Функция ЕстьРеквизитПопыткой(Объект, ИмяРеквизита)

Попытка

Значение = Объект[ИмяРеквизита];

Возврат Истина;

Исключение

Возврат Ложь;

КонецПопытки;

КонецФункции

Обращение через квадратные скобки Объект[ИмяРеквизита] позволяет подставить имя реквизита из переменной — это удобно в универсальном коде. Если свойства нет, платформа выбросит исключение, функция вернёт Ложь, и выполнение программы продолжится штатно.

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

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

Для структур (Структура) существует штатный метод Свойство(), который проверяет наличие ключа и заодно может вернуть его значение:

Значение = Неопределено;

Если СтруктураДанных.Свойство("Организация", Значение) Тогда

// ключ есть, в переменной Значение — его содержимое

КонецЕсли;

Второй параметр необязателен: если передать только имя, метод просто вернёт Истина или Ложь. Это самый чистый способ проверки для структур, и перехват ошибок здесь не нужен.

Для строк таблицы значений (СтрокаТаблицыЗначений) метода Свойство() нет. Наличие колонки проверяется через коллекцию колонок самой таблицы:

Если ТаблицаДанных.Колонки.Найти("Сумма") <> Неопределено Тогда

// колонка Сумма существует

КонецЕсли;

Сравнение способов проверки

Метаданные().Реквизиты.Найти()

Подходит для объектов конфигурации (справочники, документы). Точно и быстро, но не покрывает стандартные реквизиты.

Попытка/Исключение

Универсально для любых значений, включая строки ТЗ и COM-объекты. Медленнее и скрывает природу ошибки.

Структура.Свойство()

Штатный способ только для структур. Не работает для строк таблиц значений и объектов данных.

Колонки.Найти()

Для таблиц значений и их строк. Проверяет колонку таблицы, а не отдельной строки.

Проверка наличия реквизита в запросе

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

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

ЕстьКомментарий = МетаДок.Реквизиты.Найти("Комментарий") <> Неопределено;

ТекстЗапроса = "ВЫБРАТЬ Док.Ссылка";

Если ЕстьКомментарий Тогда

ТекстЗапроса = ТекстЗапроса + ", Док.Комментарий";

КонецЕсли;

ТекстЗапроса = ТекстЗапроса + " ИЗ Документ.РеализацияТоваровУслуг КАК Док";

Обратите внимание: здесь проверка идёт через глобальный контекст Метаданные, а не через конкретный объект. Это удобно, когда экземпляра объекта под рукой нет — например, при построении универсального отчёта по произвольному виду документов.

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

Реквизиты управляемой формы — это не метаданные объекта, а отдельная коллекция. Проверить наличие реквизита формы можно через метод ПолучитьРеквизиты() формы, который возвращает массив описаний:

Функция ЕстьРеквизитФормы(Форма, ИмяРеквизита)

Для Каждого Реквизит Из Форма.ПолучитьРеквизиты() Цикл

Если Реквизит.Имя = ИмяРеквизита Тогда

Возврат Истина;

КонецЕсли;

КонецЦикла;

Возврат Ложь;

КонецФункции

Альтернатива — обращение к реквизиту формы через ЭтаФорма[ИмяРеквизита] внутри Попытка/Исключение. Это короче, но, как и в случае с объектами, маскирует причину ошибки. Для одноразовой проверки при открытии формы такой вариант допустим.

Порядок действий при универсальной проверке
  1. 1
    Определите тип проверяемого значения: объект конфигурации, структура, строка ТЗ или форма
  2. 2
    Для объекта конфигурации вызовите Метаданные() и выполните Реквизиты.Найти(Имя)
  3. 3
    Для стандартного реквизита проверьте коллекцию СтандартныеРеквизиты
  4. 4
    Для табличной части сначала найдите её в ТабличныеЧасти, затем ищите реквизит внутри
  5. 5
    Для структуры вызовите Свойство(Имя), для таблицы значений — Колонки.Найти(Имя)
  6. 6
    Если тип неизвестен, оберните обращение Объект[Имя] в Попытка/Исключение
  7. 7
    Проверьте результат: Неопределено или Ложь означает, что реквизита нет

Типичные ошибки и ограничения

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

Вторая ошибка — проверка реквизита по ссылке вместо объекта. У переменной типа ДокументСсылка метод Метаданные() тоже есть, поэтому проверка работает и от ссылки — это корректно. Но если попытаться обратиться к реквизиту табличной части через ссылку без получения объекта, данные будут недоступны: табличные части читаются только через ПолучитьОбъект() или запрос.

Третья группа проблем — регистр имён. Встроенный язык 1С нечувствителен к регистру, поэтому «Сумма» и «сумма» — один и тот же реквизит. Но при передаче имён из внешних систем (XML, JSON) лишние пробелы или невидимые символы приведут к тому, что поиск не найдёт реквизит. Перед проверкой имя стоит обрезать функцией СокрЛП().

Типичные ошибки
01
Искать стандартный реквизит (Дата, Номер, Код) в коллекции Реквизиты — он там не найдётся, нужна коллекция СтандартныеРеквизиты
02
Искать реквизит табличной части, не проверив существование самой табличной части — обращение к несуществующей ТЧ вызовет ошибку
03
Использовать Попытка/Исключение в массовых циклах — это замедляет обработку и скрывает реальные ошибки
04
Передавать имя реквизита с пробелами или невидимыми символами из внешних источников без СокрЛП — поиск не найдёт существующий реквизит
05
Пытаться проверить поле запроса внутри текста запроса — проверку нужно делать через метаданные до формирования текста
Контрольные точки

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

Результат Реквизиты.Найти(Имя)
Норма

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

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

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

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

Значение читается без исключения

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

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

Проверка стандартного реквизита
Норма

Найден через СтандартныеРеквизиты.Найти()

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

Поиск в Реквизиты дал Неопределено и сделан ложный вывод

Имя реквизита из внешнего источника
Норма

Имя обработано СокрЛП и совпадает с метаданными

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

Лишние пробелы — реквизит не находится

Часто задаваемые вопросы

Можно ли проверить наличие реквизита у ссылки, не получая объект?

Да. У ссылочных типов (ДокументСсылка, СправочникСсылка и др.) есть метод Метаданные(), поэтому проверку состава реквизитов можно выполнить без вызова ПолучитьОбъект() и без обращения к данным. Это быстрее и не создаёт лишних объектов в памяти. Но само значение реквизита табличной части по ссылке прочитать нельзя — для этого нужен объект или запрос.

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

Через метаданные регистра: Метаданные.РегистрыСведений.ИмяРегистра.Реквизиты.Найти(Имя). Отдельно проверяются измерения (коллекция Измерения) и ресурсы (коллекция Ресурсы) — у регистров данные разбиты на три коллекции, и искать нужно в той, которая соответствует роли поля.

Почему Реквизиты.Найти("Дата") возвращает Неопределено у документа?

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

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

Метод Найти() коллекции реквизитов принимает строку, поэтому переменная подходит напрямую: Реквизиты.Найти(ИмяПеременной). Для обращения к самому значению используйте синтаксис квадратных скобок: Объект[ИмяПеременной]. Перед поиском очистите имя от пробелов функцией СокрЛП.

Работает ли проверка через метаданные в расширении конфигурации?

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

Что быстрее: проверка через метаданные или через Попытку?

Разовая проверка через метаданные работает быстрее и не генерирует исключений. Попытка оправдана только когда метаданные недоступны (произвольные значения, внешние объекты) или проверка единична. В циклах по тысячам записей перехват исключений даёт заметное замедление, поэтому состав колонок и реквизитов лучше проверять один раз до цикла.

Итог

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

Универсального оператора проверки реквизита в 1С 8 нет. Для объектов конфигурации используйте Метаданные().Реквизиты.Найти() с учётом отдельных коллекций стандартных реквизитов, измерений и ресурсов; для структур — метод Свойство(); для таблиц значений — Колонки.Найти(); для неизвестных типов — Попытка/Исключение. Перед обращением к значению всегда убеждайтесь, что проверка охватывает нужную коллекцию, а имя очищено от лишних символов.