Есть свойство объекта 1С: проверить реквизит и метод

Дата: 19.09.2026 09:47:59
Метаданные
БСП
ЗаполнитьЗначенияСвойств
Реквизиты
Встроенный язык
Комментарий:
0
Платформа:
8.3
Конфигурация:
Любая
Формы:
Любые

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

Где встречается задача

  • Отчёт или обработка для нескольких конфигураций: в одной у номенклатуры есть «Артикул», в другой его нет или он называется иначе.
  • Общая процедура для разных документов: у реализации есть «Склад», у акта на услуги — нет.
  • Код в расширении, который должен пережить обновление типовой: реквизит могли переименовать или удалить.
  • Структура параметров, в которую вызывающий код кладёт ключи по своему усмотрению.
  • Результат запроса, текст которого собирается динамически, поэтому набор колонок заранее неизвестен.

Какой способ выбрать

Что проверяемСпособГде работает
Реквизит справочника или документаМетаданные().Реквизиты.Найти(Имя), в БСП — ОбщегоНазначения.ЕстьРеквизитОбъектаСервер
Свойство любого значения: объект, данные формы, форма, строка таблицы, выборкаЗаполнитьЗначенияСвойств в структуру с маркером, в БСП — ЕстьРеквизитИлиСвойствоОбъектаКлиент и сервер
Ключ структуры, параметры формыСтруктура.Свойство(Ключ)Клиент и сервер
Колонка таблицы значений или результата запросаКолонки.Найти(Имя)Сервер
Элемент формыЭлементы.Найти(Имя)Клиент и сервер
Общий модуль, подсистемаМетаданные.ОбщиеМодули.Найти(Имя), в БСП — ОбщегоНазначения.ПодсистемаСуществуетСервер
Процедура или функцияПопытка + ВыполнитьСервер

Проверка реквизита по метаданным

Самый прямой путь — спросить у метаданных. Данные из базы при этом не читаются, и результат не зависит от того, что лежит в поле. Нужен объект метаданных: у ссылки и у объекта его возвращает метод Метаданные(), по типу значения — Метаданные.НайтиПоТипу(ТипЗнч(Значение)). На тонком клиенте глобального свойства Метаданные нет, так что проверка выполняется на сервере.

Подвох в том, что коллекция Реквизиты содержит только реквизиты, которые добавил разработчик. «Наименование», «Код», «Дата», «Номер», «Владелец» лежат в СтандартныеРеквизиты, табличные части — в ТабличныеЧасти. Функция ниже смотрит все три коллекции:

// Общий модуль с флагом «Сервер».
// Есть ли у справочника или документа реквизит, табличная часть
// или стандартный реквизит с именем ИмяПоля.
Функция ЕстьПолеВМетаданных(МетаданныеОбъекта, ИмяПоля) Экспорт

	Если МетаданныеОбъекта.Реквизиты.Найти(ИмяПоля) <> Неопределено Тогда
		Возврат Истина;
	КонецЕсли;

	Если МетаданныеОбъекта.ТабличныеЧасти.Найти(ИмяПоля) <> Неопределено Тогда
		Возврат Истина;
	КонецЕсли;

	ИмяВРег = ВРег(ИмяПоля);
	Для Каждого СтандартныйРеквизит Из МетаданныеОбъекта.СтандартныеРеквизиты Цикл
		Если ВРег(СтандартныйРеквизит.Имя) = ИмяВРег Тогда
			Возврат Истина;
		КонецЕсли;
	КонецЦикла;

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

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

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

Типичное применение — собрать запрос под конкретную конфигурацию:

// Общий модуль с флагом «Сервер».
// Артикул попадает в запрос, только если такой реквизит есть в этой конфигурации.
Функция ТоварыДокумента(Ссылка) Экспорт
	
	МетаНоменклатура = Метаданные.Справочники.Найти("Номенклатура");
	Если МетаНоменклатура <> Неопределено
		И ЕстьПолеВМетаданных(МетаНоменклатура, "Артикул") Тогда
		ПолеАртикула = "Товары.Номенклатура.Артикул";
	Иначе
		ПолеАртикула = """"""; // в тексте запроса окажется пустая строка ""
	КонецЕсли;

	Запрос = Новый Запрос;
	Запрос.Текст = СтрЗаменить(
		"ВЫБРАТЬ
		|	Товары.Номенклатура КАК Номенклатура,
		|	&ПолеАртикула КАК Артикул,
		|	Товары.Количество КАК Количество
		|ИЗ
		|	Документ.РеализацияТоваровУслуг.Товары КАК Товары
		|ГДЕ
		|	Товары.Ссылка = &Ссылка", "&ПолеАртикула", ПолеАртикула);
	Запрос.УстановитьПараметр("Ссылка", Ссылка);
	
	Возврат Запрос.Выполнить().Выгрузить();
	
КонецФункции

В БСП похожую проверку делает ОбщегоНазначения.ЕстьРеквизитОбъекта(ИмяРеквизита, МетаданныеОбъекта) — функция описана в документации БСП 3.1 и 3.2. Порядок параметров непривычный: имя первым, метаданные вторым. Перед использованием откройте код функции в своей версии и посмотрите, учитывает ли она стандартные реквизиты.

Есть свойство объекта или нет: приём с ЗаполнитьЗначенияСвойств

Метаданные не помогут, если на руках не объект базы, а Объект на управляемой форме, сама форма, строка табличной части или выборка из запроса. Для них работает приём, на котором построена функция БСП ЕстьРеквизитИлиСвойствоОбъекта («есть реквизит или свойство объекта»): создаём структуру с нужным ключом, кладём в неё уникальное значение-маркер и копируем туда свойства проверяемого значения через ЗаполнитьЗначенияСвойств. Если свойство есть, маркер затрётся его значением. Если нет — останется на месте.

// Общий модуль СвойстваОбъектовКлиентСервер (флаги «Клиент» и «Сервер»).
// Возвращает Истина, если у Источника есть реквизит или свойство ИмяСвойства.
// Найденное значение возвращается в третьем параметре.
Функция ЕстьСвойство(Источник, Знач ИмяСвойства, ЗначениеСвойства = Неопределено) Экспорт

	ЗначениеСвойства = Неопределено;
	Если Источник = Неопределено Или ПустаяСтрока(ИмяСвойства) Тогда
		Возврат Ложь;
	КонецЕсли;
	ИмяСвойства = СокрЛП(ИмяСвойства);

	Маркер = Новый УникальныйИдентификатор;
	Приемник = Новый Структура;
	Попытка
		Приемник.Вставить(ИмяСвойства, Маркер);
	Исключение
		// Имя с пробелом, точкой или запятой не может быть именем свойства.
		Возврат Ложь;
	КонецПопытки;

	ЗаполнитьЗначенияСвойств(Приемник, Источник);

	Если Приемник[ИмяСвойства] = Маркер Тогда
		Возврат Ложь;
	КонецЕсли;

	ЗначениеСвойства = Приемник[ИмяСвойства];
	Возврат Истина;

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

Вызов из формы документа — проверка идёт на клиенте, без серверного вызова:

// Модуль формы документа.
&НаКлиенте
Процедура ПоказатьКомментарий(Команда)

	Комментарий = "";
	Если СвойстваОбъектовКлиентСервер.ЕстьСвойство(Объект, "Комментарий", Комментарий)
		И ЗначениеЗаполнено(Комментарий) Тогда
		ПоказатьПредупреждение(, Комментарий);
	Иначе
		ПоказатьПредупреждение(, "Комментария у этого документа нет.");
	КонецЕсли;

КонецПроцедуры

Разбор ключевых строк

  • Новый УникальныйИдентификатор — маркер, который гарантированно не совпадёт ни с одним значением источника. Если положить в структуру Неопределено, функция ошибётся на свойствах, значение которых тоже Неопределено: свойство есть, а проверка скажет «нет».
  • Приемник.Вставить внутри Попытки — ключ структуры обязан быть корректным идентификатором. Имена вроде «Контрагент.ИНН» или «Сумма НДС» вызовут исключение; здесь оно превращается в ответ «свойства нет».
  • ЗаполнитьЗначенияСвойств(Приемник, Источник) без списка свойств — платформа идёт по ключам приёмника и ищет одноимённые свойства у источника. Отсутствующие она пропускает молча, поэтому ошибки не будет.
  • Сравнение с маркером — единственное место, где принимается решение. Третий параметр позволяет не обращаться к свойству второй раз.

Ограничения приёма

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

Ещё одна деталь: функция отвечает «есть» и для табличной части, и для любого другого свойства источника. У формы, например, найдутся Заголовок и Элементы. Если нужен именно реквизит объекта, проверяйте метаданными.

Структура, таблица значений и результат запроса

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

// Модуль формы.
&НаСервере
Процедура НастроитьПоДанным(ДополнительныеПараметры, Запрос)

	// Структура и ФиксированнаяСтруктура: метод Свойство,
	// второй параметр сразу получает значение ключа.
	Склад = Неопределено;
	ЕстьСклад = ДополнительныеПараметры.Свойство("Склад", Склад)
		И ЗначениеЗаполнено(Склад);

	// Результат запроса и таблица значений: коллекция Колонки.
	Результат = Запрос.Выполнить();
	ЕстьАртикул = (Результат.Колонки.Найти("Артикул") <> Неопределено);

	// Элементы формы.
	Если Элементы.Найти("ТоварыАртикул") <> Неопределено Тогда
		Элементы.ТоварыАртикул.Видимость = ЕстьАртикул;
	КонецЕсли;
	Если Элементы.Найти("ГруппаДоставка") <> Неопределено Тогда
		Элементы.ГруппаДоставка.Видимость = ЕстьСклад;
	КонецЕсли;

КонецПроцедуры

Тем же методом проверяют параметры формы в ПриСозданииНаСервере: Параметры.Свойство("ЗначенияЗаполнения").

Как получить свойства объекта списком

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

// Общий модуль с флагом «Сервер».
// Имена стандартных реквизитов, реквизитов и табличных частей
// справочника или документа по ссылке.
Функция ИменаПолейОбъекта(Ссылка) Экспорт

	МетаданныеОбъекта = Ссылка.Метаданные();
	Имена = Новый Массив;

	Для Каждого Реквизит Из МетаданныеОбъекта.СтандартныеРеквизиты Цикл
		Имена.Добавить(Реквизит.Имя);
	КонецЦикла;
	Для Каждого Реквизит Из МетаданныеОбъекта.Реквизиты Цикл
		Имена.Добавить(Реквизит.Имя);
	КонецЦикла;
	Для Каждого ТабличнаяЧасть Из МетаданныеОбъекта.ТабличныеЧасти Цикл
		Имена.Добавить(ТабличнаяЧасть.Имя);
	КонецЦикла;

	Возврат Имена;

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

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

В типовых на БСП словом «свойства» называют ещё и дополнительные реквизиты и сведения из подсистемы «Свойства». Реквизитами метаданных они не являются: дополнительные реквизиты хранятся строками табличной части ДополнительныеРеквизиты, дополнительные сведения — в регистре сведений ДополнительныеСведения. Ни проверка по метаданным, ни ЗаполнитьЗначенияСвойств их по имени не найдут; для работы с ними есть программный интерфейс модуля УправлениеСвойствами.

Проверка существования метода: Попытка и Выполнить

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

// Общий модуль с флагом «Сервер».
// Вызывает ИмяМодуля.ИмяПроцедуры(Параметр), если обычный (не глобальный)
// общий модуль есть и компилируется на сервере.
// Истина — вызов прошёл без исключения. Платформа 8.3.17 и новее.
Функция ВызватьПроцедуруЕслиЕсть(ИмяМодуля, ИмяПроцедуры, Параметр) Экспорт

	Если Не ЭтоКорректноеИмя(ИмяМодуля) Или Не ЭтоКорректноеИмя(ИмяПроцедуры) Тогда
		ВызватьИсключение "Недопустимое имя модуля или процедуры";
	КонецЕсли;

	МетаМодуль = Метаданные.ОбщиеМодули.Найти(ИмяМодуля);
	Если МетаМодуль = Неопределено Или Не МетаМодуль.Сервер Или МетаМодуль.Глобальный Тогда
		// Глобальный модуль по имени не адресуется: его методы входят в глобальный контекст.
		Возврат Ложь;
	КонецЕсли;

	Попытка
		Выполнить(ИмяМодуля + "." + ИмяПроцедуры + "(Параметр)");
	Исключение
		ЗаписьЖурналаРегистрации("ВызовНеобязательнойПроцедуры",
			УровеньЖурналаРегистрации.Предупреждение, , ,
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		Возврат Ложь;
	КонецПопытки;

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

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

// Имя допустимо, если из него получается ключ структуры:
// буквы, цифры и подчёркивание, первый символ не цифра.
Функция ЭтоКорректноеИмя(Имя)

	Если ТипЗнч(Имя) <> Тип("Строка") Или ПустаяСтрока(Имя) Тогда
		Возврат Ложь;
	КонецЕсли;

	Попытка
		Проверка = Новый Структура;
		Проверка.Вставить(Имя);
	Исключение
		Возврат Ложь;
	КонецПопытки;

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

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

Что здесь важно:

  • Имя модуля и процедуры проверяется до Выполнить. Строка собирается в код, и если имя пришло из настроек, файла или от пользователя, без проверки в неё можно подсунуть произвольный код. Приём со структурой пропускает только буквы, цифры и подчёркивание.
  • Наличие модуля проверяется по метаданным. Свойство Сервер отсекает клиентские модули, а Глобальный — глобальные: их методы вызываются без имени модуля, и строка «Модуль.Процедура» для них упадёт, хотя метод есть.
  • Исключение записывается в журнал регистрации, иначе ошибка внутри существующего метода будет выглядеть как его отсутствие. Объект ОбработкаОшибок появился в платформе 8.3.17, и с этой версии глобальная функция ПодробноеПредставлениеОшибки() считается устаревшей. На более старых платформах пишите именно её, а не ОписаниеОшибки(): в подробном представлении есть стек вызовов.

В БСП 3.x для этого есть готовые ОбщегоНазначения.ВыполнитьМетодКонфигурации(ИмяМетода, Параметры) и ОбщегоНазначения.ВыполнитьМетодОбъекта(Объект, ИмяМетода, Параметры): они сами проверяют имя, а параметры принимают массивом. Если же нужно вызвать модуль необязательной подсистемы, в типовых принято обходиться без Выполнить:

// Серверный общий модуль в конфигурации на БСП 3.x.
Процедура ОбработатьСвойстваЕслиЕсть() Экспорт
	
	Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Свойства") Тогда
		Возврат;
	КонецЕсли;
	
	МодульУправлениеСвойствами = ОбщегоНазначения.ОбщийМодуль("УправлениеСвойствами");
	// Дальше обычный вызов экспортного метода:
	// МодульУправлениеСвойствами.ИмяМетода(...)
	
КонецПроцедуры

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

СпособСкоростьБезопасность
МетаданныеБыстро, данные не читаются. В цикле сохраните результат проверки в переменнуюКод не выполняется
ЗаполнитьЗначенияСвойствБыстро для значений в памяти; для ссылки на сервере — чтение из базыКод не выполняется
Попытка вокруг прямого обращенияДёшево, пока нет исключения; каждое исключение заметно дорожеПрячет посторонние ошибки
ВыполнитьСтрока компилируется при каждом вызове — в цикле это заметноРиск внедрения кода, если имя пришло извне

Общее правило: проверяйте один раз до цикла, а не на каждой строке. Если реквизита «Артикул» нет в конфигурации, его не появится и на сотой итерации.

Типичные ошибки

  • «Поле объекта не обнаружено (Артикул)» — прямое обращение без проверки. Та же ошибка бывает у выборки запроса, если поле убрали из текста, а код обработки выборки остался прежним.
  • Поиск стандартного реквизита в коллекции Реквизиты. «Наименование» или «Дата» там не найдутся, и проверка ответит «нет».
  • Общие реквизиты. Реквизит, заданный в ветке «Общие реквизиты», в коллекции Реквизиты конкретного объекта не виден. Его ищут в Метаданные.ОбщиеРеквизиты с учётом состава или проверяют приёмом с ЗаполнитьЗначенияСвойств.
  • Маркер Неопределено вместо уникального значения — ложное «свойства нет» для пустых полей.
  • Путь через точку. «Контрагент.ИНН» не является именем свойства. Проверьте «Контрагент», получите значение, затем проверяйте «ИНН» у него.
  • «Метод объекта не обнаружен (ЗаполнитьТовары)» и молчаливый перехват. Если Исключение ничего не пишет, ошибка внутри существующего метода маскируется под его отсутствие.
  • Попытка внутри транзакции. Если вызванный метод упал на записи или блокировке данных, перехват исключения транзакцию не спасёт: при фиксации платформа сообщит «В данной транзакции уже происходили ошибки!». Проверяйте наличие модуля и метода до НачатьТранзакцию().

Частые вопросы

Где в БСП функция «есть реквизит или свойство объекта»?

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

Можно ли проверить свойство у объекта на клиенте?

Для данных формы — да: Объект, реквизиты формы и строки табличных частей проверяются приёмом с ЗаполнитьЗначенияСвойств. Метаданные на тонком клиенте недоступны, поэтому для ссылки нужен серверный вызов.

Как проверить реквизит, если есть только ссылка?

На сервере получите Ссылка.Метаданные() и проверьте коллекции, как в функции ЕстьПолеВМетаданных. Значение потом читайте запросом или функцией БСП ОбщегоНазначения.ЗначениеРеквизитаОбъекта — так не придётся загружать объект целиком.

Как проверить метод, не вызывая его?

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

Увидит ли проверка реквизиты из расширения?

Если расширение подключено в сеансе, его реквизиты есть и у объекта, и в метаданных, так что оба способа их найдут. Когда расширение отключено, проверка ответит «нет» — ради этого её и пишут.

Когда проще заказать

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

По теме

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.


1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.