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

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

1С: как проверить, есть ли реквизит у формы

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

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

Универсальной встроенной функции вида «ЕстьРеквизитФормы» в платформе нет, поэтому проверку выполняют обходными способами: через коллекцию реквизитов формы, через попытку обращения с обработкой исключения или через анализ структуры формы. Выбор способа зависит от типа формы (управляемая или обычная) и от того, где выполняется код — на клиенте или на сервере.

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

Как устроены реквизиты формы и почему прямого метода нет

Реквизит формы — это данные, которые форма хранит и использует: строки, числа, ссылки, таблицы значений, динамические списки. В управляемой форме реквизиты описываются в конфигураторе на закладке «Реквизиты» редактора формы или добавляются программно методом ИзменитьРеквизиты(). В обычной форме данные чаще привязаны к основному реквизиту объекта или к переменным модуля формы.

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

Важно различать реквизит формы и элемент формы (поле ввода, надпись). Элемент формы — это визуальное отображение, реквизит — данные. Элемент может существовать без реквизита и наоборот. Проверка через Элементы.Найти() отвечает на вопрос «есть ли поле на форме», а не «есть ли реквизит» — это разные задачи.

Проверка реквизита в управляемой форме через ПолучитьРеквизиты()

В управляемой форме состав реквизитов доступен через метод ПолучитьРеквизиты(). Он возвращает массив объектов типа РеквизитФормы, у каждого из которых есть свойства Имя, Путь, ТипЗначения и другие. Чтобы проверить наличие реквизита, достаточно перебрать массив и сравнить имена.

Пример функции для модуля формы или общего модуля с признаком «Сервер»:

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

РеквизитыФормы = Форма.ПолучитьРеквизиты();

Для Каждого Реквизит Из РеквизитыФормы Цикл

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

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

КонецЕсли;

КонецЦикла;

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

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

Вызов из кода формы выглядит так: Если ЕстьРеквизитФормы(ЭтаФорма, "СкидкаПроцент") Тогда .... Метод ПолучитьРеквизиты() доступен только на сервере, поэтому при вызове с клиента потребуется серверная процедура с директивой &НаСервере или &НаСервереБезКонтекста (во втором случае форму нужно передать параметром, что не всегда возможно — см. раздел об ограничениях).

Обратите внимание: метод ПолучитьРеквизиты() по умолчанию возвращает реквизиты верхнего уровня. Если нужно проверить реквизит внутри реквизита-объекта (например, колонку таблицы или поле вложенной структуры), передайте параметр Путь — имя родительского реквизита: Форма.ПолучитьРеквизиты("ТаблицаТоваров") вернёт колонки таблицы значений.

Порядок действий для управляемой формы
  1. 1
    Определите, где выполняется проверка: на клиенте или на сервере
  2. 2
    На сервере вызовите Форма.ПолучитьРеквизиты() и получите массив реквизитов
  3. 3
    Переберите массив и сравните свойство Имя с искомым именем
  4. 4
    Для вложенных реквизитов передайте путь родителя в ПолучитьРеквизиты(Путь)
  5. 5
    По результату выполняйте обращение к реквизиту или альтернативную ветку кода

Универсальная проверка через Попытка...Исключение

Самый простой способ, работающий и на клиенте, и на сервере, — попытаться обратиться к реквизиту внутри конструкции Попытка...Исключение. Если реквизита нет, платформа выбросит исключение, которое мы перехватим и вернём Ложь.

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

Попытка

ЗначениеПроверки = Форма[ИмяРеквизита];

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

Исключение

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

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

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

Обращение через квадратные скобки Форма[ИмяРеквизита] позволяет использовать имя как строку-переменную — это ключевой приём для универсальных проверок. Такой код работает в управляемых формах на тонком, веб- и толстом клиенте без серверного вызова.

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

Проверка в обычной форме (обычное приложение)

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

Практические варианты проверки:

  • Через Попытка...Исключение с обращением ЭтаФорма[ИмяРеквизита] — универсально и надёжно;
  • Через ЭлементыФормы.Найти(ИмяЭлемента) — но это проверка элемента, а не реквизита;
  • Для реквизитов объекта (справочника, документа) — через метаданные: Объект.Метаданные().Реквизиты.Найти(ИмяРеквизита) вернёт Неопределено, если реквизита нет.

Последний вариант — самый корректный, когда вопрос звучит как «есть ли у объекта на форме реквизит с таким именем». Метаданные доступны на сервере, и поиск по ним не вызывает исключений:

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

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

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

Этот же приём с метаданными применим и в управляемых формах, если речь идёт о реквизитах прикладного объекта, а не формы. Различайте: «реквизит формы» — данные формы, «реквизит объекта» — поле справочника или документа, описанное в конфигураторе.

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

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

СпособГде работаетЧто проверяетОграничения
ПолучитьРеквизиты() + переборУправляемая форма, серверРеквизиты формы, включая вложенныеТолько серверный контекст
Попытка + Форма[Имя]Любая форма, клиент и серверДоступность свойства по имениМедленнее, ловит любые ошибки доступа
Метаданные().Реквизиты.Найти()Сервер, объекты конфигурацииРеквизиты объекта (документа, справочника)Не проверяет реквизиты самой формы
Элементы.Найти()Клиент и серверЭлементы (поля) на формеЭлемент ≠ реквизит

Сравнение вариантов

ПолучитьРеквизиты()

Точная проверка состава реквизитов формы; подходит для серверной логики и динамически изменяемых форм, но недоступна на клиенте.

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

Универсальный вариант для клиента и сервера; прост в реализации, но использует исключения как механизм контроля.

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

Правильный выбор, если нужно проверить реквизит объекта, а не формы; работает быстро и без исключений.

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

Первая частая ошибка — путать реквизит формы и элемент формы. Код проверяет Элементы.Найти("ПолеКомментарий"), находит поле ввода и делает вывод, что реквизит «Комментарий» существует. На деле поле может быть связано с другим путём данных или не связано вообще. Проверяйте именно то, что будете использовать.

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

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

Четвёртая ошибка — проверка до создания реквизита. Если реквизит добавляется программно через ИзменитьРеквизиты(), проверка до вызова этого метода вернёт Ложь. Учитывайте порядок выполнения: сначала изменение состава, потом проверка и обращение.

Типичные ошибки
01
Проверка элемента формы вместо реквизита — вывод о наличии данных делается по наличию поля на экране, что неверно
02
Вызов ПолучитьРеквизиты() в клиентской процедуре — ошибка выполнения на тонком клиенте
03
Проверка до вызова ИзменитьРеквизиты() — динамически добавленный реквизит ещё не существует
04
Попытка проверить реквизит объекта через ПолучитьРеквизиты() формы — реквизиты объекта ищутся в метаданных, а не в составе формы

Практические сценарии применения

Сценарий 1: расширение конфигурации. Расширение добавляет реквизит формы, но код должен работать и без расширения. Перед обращением к реквизиту выполняется проверка — если реквизита нет, выполняется базовая ветка логики.

Сценарий 2: универсальная обработка заполнения. Обработка обходит открытые формы документов и заполняет реквизит «Комментарий», если он есть. Проверка через попытку позволяет одной процедурой обслуживать формы разных видов документов.

Сценарий 3: динамическое создание реквизитов. Форма по настройкам пользователя добавляет дополнительные реквизиты через ИзменитьРеквизиты(). Перед добавлением проверяется, нет ли уже реквизита с таким именем, чтобы не получить ошибку дублирования.

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

Как выбрать действие

Проверка выполняется на сервере в управляемой формеИспользуйте перебор массива ПолучитьРеквизиты() по имени
Проверка нужна на клиенте или в обычной формеИспользуйте обращение Форма[Имя] внутри Попытка...Исключение
Нужно проверить реквизит документа или справочникаИщите имя в Метаданные().Реквизиты.Найти() объекта
Реквизит добавляется динамическиПроверяйте наличие перед вызовом ИзменитьРеквизиты() и после него

Как убедиться, что проверка работает

После внедрения функции проверьте оба исхода: существующий реквизит должен дать Истина, заведомо отсутствующий (например, имя «НесуществующийРеквизит123») — Ложь. Проверку удобно выполнить в отладчике, поставив точку останова внутри функции и посмотрев состав массива ПолучитьРеквизиты().

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

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

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

Функция для существующего реквизита
Норма

Возвращает Истина, обращение к реквизиту проходит без ошибок

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

Возвращает Ложь для реально существующего реквизита — проверьте имя и путь

Функция для отсутствующего реквизита
Норма

Возвращает Ложь, код продолжает работу без исключений

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

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

Работа на тонком клиенте
Норма

Проверка выполняется без серверного вызова или с корректным вызовом

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

Ошибка о недоступности метода ПолучитьРеквизиты

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

Можно ли проверить реквизит формы на клиенте без вызова сервера?

Да, через обращение по строковому имени внутри конструкции Попытка...Исключение: Значение = Форма[ИмяРеквизита]. Если реквизита нет, исключение перехватывается и функция возвращает Ложь. Метод ПолучитьРеквизиты() на клиенте недоступен.

Чем реквизит формы отличается от реквизита объекта?

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

Как проверить наличие колонки у таблицы значений — реквизита формы?

Вызовите ПолучитьРеквизиты() с параметром-путём: Форма.ПолучитьРеквизиты("ИмяТаблицы") вернёт массив колонок. Переберите его и сравните имена. Либо обратитесь к колонке через попытку: Таблица[0].ИмяКолонки — но для пустой таблицы этот способ не сработает.

Почему обращение к реквизиту вызывает ошибку «Поле объекта не обнаружено»?

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

Работает ли проверка через Попытка...Исключение в веб-клиенте?

Да, конструкция Попытка...Исключение и обращение к свойствам по строковому имени поддерживаются в веб-клиенте. Это делает способ универсальным для всех видов клиентов, но для серверной логики предпочтительнее перебор ПолучитьРеквизиты() как более быстрый и предсказуемый вариант.

Как проверить, что динамически добавленный реквизит создался успешно?

После вызова ИзменитьРеквизиты() выполните проверку через ПолучитьРеквизиты() и поиск по имени. Если реквизит не появился, проверьте корректность массива добавляемых реквизитов и отсутствие ошибок в описании типа — платформа не всегда сообщает об ошибке явно.

Итог

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

Готового метода проверки реквизита формы в 1С нет. В управляемой форме на сервере используйте перебор ПолучитьРеквизиты(), на клиенте и в обычных формах — обращение по имени внутри Попытка...Исключение. Реквизиты объекта проверяйте через метаданные, а элементы формы не путайте с реквизитами.