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