Как проверить наличие реквизита или свойства у объекта в 1С: универсальные методы

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

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

Метод 1: Анализ метаданных (для объектов конфигурации)

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


// Проверка реквизита у документа или справочника
Если Объект.Метаданные().Реквизиты.Найти(ИмяРеквизита) <> Неопределено Тогда
    Сообщить("Реквизит найден в основных реквизитах");
ИначеЕсли Объект.Метаданные().ТабличныеЧасти.Найти(ИмяРеквизита) <> Неопределено Тогда
    Сообщить("Это имя табличной части");
КонецЕсли;

Важные нюансы:

  1. Метод Метаданные() работает только для объектов, имеющих постоянное описание в дереве метаданных. Он не подойдет для Структура, Соответствие или ДанныеФормыСтруктура.
  2. Помните, что реквизиты могут быть не только «обычными», но и общими реквизитами, а также стандартными (например, Дата, Номер, Код, Наименование). Для их проверки нужно обращаться к соответствующим коллекциям метаданных (СтандартныеРеквизиты).
  3. Обращение к метаданным через точку от объекта — операция относительно медленная. Если вам нужно проверить тысячи объектов в цикле, этот метод может создать задержку.

Метод 2: Использование структуры и ЗаполнитьЗначенияСвойств (Универсальный "хак")

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

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


Функция НаличиеСвойстваУОбъекта(Объект, ИмяСвойства)
    // Создаем уникальный маркер, которого точно нет в объекте
    МаркерОтсутствия = Новый УникальныйИдентификатор;
    
    // Создаем структуру, где ключ - искомое имя, а значение - наш маркер
    ПроверочнаяСтруктура = Новый Структура(ИмяСвойства, МаркерОтсутствия);
    
    // Копируем значения из объекта в структуру. 
    // Если свойство существует, маркер будет перезаписан значением из объекта.
    ЗаполнитьЗначенияСвойств(ПроверочнаяСтруктура, Объект);
    
    // Если значение изменилось (стало не равно маркеру), значит реквизит есть
    Возврат ПроверочнаяСтруктура[ИмяСвойства] <> МаркерОтсутствия;
КонецФункции

Почему этот метод хорош?

Ограничение: Этот метод может не сработать, если у пользователя нет прав доступа на чтение конкретного реквизита (RLS). Платформа просто проигнорирует копирование, и функция вернет Ложь, даже если в конфигураторе реквизит существует.

Метод 3: Использование встроенных функций БСП

Если вы работаете в современной конфигурации на базе «Библиотеки стандартных подсистем» (БСП), например, в 1С:ERP, УТ 11 или БП 3.0, не нужно изобретать велосипед. Разработчики 1С уже предусмотрели готовые инструменты в общем модуле ОбщегоНазначения.

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

  1. ОбщегоНазначения.ЕстьРеквизитИлиСвойствоОбъекта(Объект, ИмяСвойства) — самая универсальная функция. Она внутри себя определяет тип объекта и выбирает оптимальный алгоритм проверки.
  2. ОбщегоНазначенияКлиентСервер.ЕстьРеквизитОбъекта(Объект, ИмяРеквизита) — клиент-серверный вариант для простых проверок.
  3. ОбщегоНазначения.ЕстьРеквизитТабЧастиОбъекта(ИмяРеквизита, МетаданныеОбъекта, ИмяТабЧасти) — специализированная функция для работы с табличными частями.

Пример вызова из БСП:


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

Метод 4: Блок Попытка — Исключение

Это самый простой в написании, но самый спорный с точки зрения культуры программирования метод. Мы просто пытаемся обратиться к реквизиту «в лоб» и ловим ошибку, если его нет.


Результат = Ложь;
Попытка
    Значение = Объект[ИмяСвойства];
    Результат = Истина;
Исключение
    // Свойства не существует или нет прав
    Результат = Ложь;
КонецПопытки;

Разберем, почему «Попытку» стоит использовать с осторожностью:

Генерация исключения в 1С — это очень дорогая операция для процессора. Если вы используете такой код внутри цикла на 10 000 итераций, и у половины объектов реквизита нет, ваша обработка будет работать в 20-50 раз медленнее, чем при использовании метода со структурой. Используйте Попытка — Исключение только там, где вы уверены, что отсутствие реквизита — это редчайший исключительный случай, либо при работе с COM-объектами (где другие методы просто не работают).

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

Выясним причины, по которым проверка может вести себя по-разному:

1. Структуры и Соответствия:

Для них лучше всего использовать встроенный метод Свойство(). Это максимально быстро и корректно.

Если МояСтруктура.Свойство("НужныйКлюч") Тогда ...

2. Формы и ДанныеФормы:

При работе на управляемых формах реквизиты объекта формы (например, Объект.Ссылка) доступны через Объект, но сама форма может иметь дополнительные реквизиты. Метод ЗаполнитьЗначенияСвойств здесь справляется лучше всего.

3. COM-объекты (внешнее соединение):

Если вы подключились к другой базе через V83.ComConnector, методы метаданных будут работать очень медленно из-за сетевых задержек. В этом случае Попытка — Исключение часто становится единственным разумным выходом, так как COM-объекты не поддерживают метод ЗаполнитьЗначенияСвойств напрямую с объектами текущей базы.

Итоговые рекомендации

Рассмотрим сводную таблицу по выбору метода:

Выбрав правильный инструмент, вы обеспечите не только стабильную работу программы без ошибок «Поле объекта не обнаружено», но и высокую скорость выполнения вашего кода.

← На главную