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