Как в 1С программно проверить, существует ли реквизит на форме?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

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


// Этот код вызовет исключение, если реквизита нет
Если ЭтаФорма[НаименованиеРеквизита] = Неопределено Тогда
    Сообщить("Реквизита нет");
Иначе
    Сообщить("Реквизит есть");
КонецЕсли;

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

Решение 1: Использование конструкции `Попытка...Исключение`

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

Этот метод гарантированно работает как на клиенте, так и на сервере, и является универсальным решением.

Посмотрим на пример реализации в виде функции:


&НаКлиенте
Функция ПроверитьРеквизит(ИмяРеквизита)

    Попытка
        // Пытаемся прочитать значение реквизита.
        // Если реквизит существует, эта строка выполнится без ошибок.
        ТестовоеЗначение = ЭтаФорма[ИмяРеквизита];
        ЕстьРеквизит = Истина;
    Исключение
        // Если реквизита нет, мы попадем в эту секцию.
        ЕстьРеквизит = Ложь;
    КонецПопытки;

    Возврат ЕстьРеквизит;

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

// Пример использования
Если ПроверитьРеквизит("МойДинамическийРеквизит") Тогда
    Сообщить("Реквизит 'МойДинамическийРеквизит' уже существует.");
Иначе
    Сообщить("Реквизит нужно создать.");
КонецЕсли;

Преимущества: Простота, надежность и универсальность.

Недостатки: Некоторые разработчики считают использование обработки исключений для управления логикой программы (control flow) не самым изящным стилем программирования. Однако в данном контексте это полностью оправданный и широко распространенный прием.

Решение 2: Получение и анализ коллекции реквизитов формы

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

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

Пример кода:


// Проверяем наличие реквизита через коллекцию
Если ЭтаФорма.Реквизиты.Найти("МойДинамическийРеквизит") = Неопределено Тогда
    Сообщить("Реквизита нет, создаем...");
    // Код создания реквизита
Иначе
    Сообщить("Реквизит уже есть.");
КонецЕсли;

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

Решение 3: Универсальный метод через `ЗаполнитьЗначенияСвойств`

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

Разберем логику по шагам:

  1. Создаем структуру, в которой ключ совпадает с именем искомого реквизита.
  2. В качестве значения для этого ключа устанавливаем некое уникальное значение, которого заведомо не может быть в реальных данных. Идеальный кандидат — новый УникальныйИдентификатор.
  3. Вызываем процедуру ЗаполнитьЗначенияСвойств(), передавая ей нашу структуру и объект для проверки (в нашем случае — форму ЭтаФорма). Эта процедура пытается заполнить значения в структуре из одноименных свойств объекта.
  4. Проверяем значение в нашей структуре. Если оно изменилось (т.е. стало не равно нашему уникальному идентификатору), значит, у объекта было найдено свойство с таким именем, и его значение было скопировано в структуру. Если же значение осталось прежним, значит, свойства у объекта нет.

Пример реализации функции:


// Проверяет наличие реквизита или свойства у произвольного объекта без обращения к метаданным.
//
// Параметры:
//  Объект - Произвольный - объект, у которого нужно проверить наличие реквизита или свойства;
//  ИмяРеквизита - Строка - имя реквизита или свойства.
//
// Возвращаемое значение:
//  Булево - Истина, если свойство есть.
//
Функция ЕстьРеквизитИлиСвойствоОбъекта(Объект, ИмяРеквизита) Экспорт

    КлючУникальности = Новый УникальныйИдентификатор;
    СтруктураПроверки = Новый Структура(ИмяРеквизита, КлючУникальности);

    ЗаполнитьЗначенияСвойств(СтруктураПроверки, Объект);

    Возврат СтруктураПроверки[ИмяРеквизита] <> КлючУникальности;

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

// Пример использования
Если ЕстьРеквизитИлиСвойствоОбъекта(ЭтаФорма, "МойДинамическийРеквизит") Тогда
    Сообщить("Реквизит найден!");
КонецЕсли;

Этот метод особенно хорош тем, что он работает для любых объектов, а не только для форм.

Решение 4: Использование Библиотеки стандартных подсистем (БСП)

Если ваша конфигурация разработана с использованием БСП, то вам повезло. Описанный выше элегантный метод уже реализован и доступен для использования. Изучить этот и другие полезные механизмы поможет актуальный справочник по методам БСП с примерами использования.

Функция находится в общем модуле ОбщегоНазначенияКлиентСервер и называется ЕстьРеквизитИлиСвойствоОбъекта.

Пример использования:


ИмяПроверяемогоРеквизита = "МойДинамическийРеквизит";

Если ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(ЭтаФорма, ИмяПроверяемогоРеквизита) Тогда
    Сообщить("Реквизит найден с помощью функции БСП!");
КонецЕсли;

Это предпочтительный способ, если ваша конфигурация содержит БСП, так как он соответствует стандартам разработки и использует уже отлаженный и проверенный механизм.

Важные нюансы и возможные проблемы

При написании универсальных проверок стоит помнить о некоторых крайних случаях:

← На главную