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

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

Как проверить наличие реквизита в справочнике 1С

Как проверить наличие реквизита в справочнике 1С через метаданные, функцию Найти и код на встроенном языке. Примеры, типичные ошибки и частые вопросы.

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

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

Важно различать две задачи: проверить наличие реквизита в структуре справочника (есть ли такое поле в конфигурации) и проверить заполненность значения у конкретного элемента. Ниже разобраны обе ситуации, а также проверка табличных частей, стандартных реквизитов и типовые ошибки.

Как проверить реквизит через метаданные

Каждый объект конфигурации описывается в дереве метаданных. Для справочника состав реквизитов хранится в свойстве Реквизиты объекта метаданных. Метод Найти() принимает имя реквизита строкой и возвращает либо объект описания, либо Неопределено.

МетаданныеСправочника = Метаданные.Справочники.Номенклатура;

РеквизитАртикул = МетаданныеСправочника.Реквизиты.Найти("Артикул");

Если РеквизитАртикул <> Неопределено Тогда

Сообщить("Реквизит ""Артикул"" существует");

Иначе

Сообщить("Реквизита ""Артикул"" нет в справочнике");

КонецЕсли;

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

Такой способ подходит, когда имя справочника известно заранее. Если справочник тоже определяется динамически, сначала проверяют его наличие через Метаданные.Справочники.Найти("ИмяСправочника"), и только потом ищут реквизит.

bsl
Если Метаданные.Справочники.Номенклатура.Реквизиты.Найти("Артикул") <> Неопределено Тогда
    // реквизит существует
КонецЕсли;

Универсальная функция проверки реквизита

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

Функция РеквизитСправочникаСуществует(ИмяСправочника, ИмяРеквизита) Экспорт

МетаданныеСпр = Метаданные.Справочники.Найти(ИмяСправочника);

Если МетаданныеСпр = Неопределено Тогда

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

КонецЕсли;

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

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

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

Функцию удобно размещать в общем модуле с признаком «Сервер», так как обращение к метаданным на клиенте в тонком и веб-клиенте ограничено. Вызов из клиентского кода делается через серверную процедуру.

Как проверить состав табличной части и стандартные реквизиты

Реквизиты табличных частей хранятся отдельно от реквизитов шапки. Сначала проверяют наличие самой табличной части через ТабличныеЧасти.Найти(), затем ищут реквизит внутри неё.

МетаданныеСпр = Метаданные.Справочники.Контрагенты;

ТабличнаяЧасть = МетаданныеСпр.ТабличныеЧасти.Найти("КонтактнаяИнформация");

Если ТабличнаяЧасть <> Неопределено

И ТабличнаяЧасть.Реквизиты.Найти("Представление") <> Неопределено Тогда

// реквизит табличной части существует

КонецЕсли;

Стандартные реквизиты — Код, Наименование, Владелец, Родитель, ПометкаУдаления — находятся в коллекции СтандартныеРеквизиты. Они присутствуют у большинства справочников, но их состав зависит от настроек: например, Владелец есть только у подчинённых справочников, а Родитель — у иерархических.

Если МетаданныеСпр.СтандартныеРеквизиты.Найти("Владелец") <> Неопределено Тогда

// справочник подчинённый

КонецЕсли;

Через стандартные реквизиты удобно определять свойства справочника без прямого анализа настроек: наличие Родителя означает иерархию, наличие Владельца — подчинённость другому объекту.

Как проверить заполненность реквизита у элемента

Отдельная задача — узнать, заполнен ли реквизит у конкретного элемента справочника. Здесь метаданные не нужны: проверяется значение через функцию ЗначениеЗаполнено() или сравнение с пустым значением соответствующего типа.

Элемент = Справочники.Номенклатура.НайтиПоКоду("000000123");

Если ЗначениеЗаполнено(Элемент.Артикул) Тогда

Сообщить("Артикул заполнен: " + Элемент.Артикул);

Иначе

Сообщить("Артикул не указан");

КонецЕсли;

Для ссылочных реквизитов пустое значение — это пустая ссылка соответствующего типа, для строк — пустая строка, для чисел — ноль. Функция ЗначениеЗаполнено() корректно обрабатывает все эти случаи, поэтому предпочтительнее ручных сравнений.

Если нужно проверить заполненность у большого числа элементов, используют запрос с условием ГДЕ Реквизит = &ПустоеЗначение или Реквизит ЕСТЬ NULL — это быстрее, чем перебор объектов в цикле, и не выгружает данные в память.

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

Метаданные + Найти()

Проверяет наличие реквизита в структуре конфигурации. Подходит для универсального кода, не обращается к данным.

ЗначениеЗаполнено()

Проверяет, заполнено ли значение у конкретного элемента. Требует, чтобы реквизит существовал.

Запрос с условием

Проверяет заполненность сразу у множества элементов. Оптимален для массовой обработки.

Проверка через консоль кода и отладчик

Не всегда нужно писать обработку: разовую проверку удобно выполнить в консоли кода или через окно «Вычислить выражение» в отладчике. Достаточно ввести выражение Метаданные.Справочники.Номенклатура.Реквизиты.Найти("Артикул") и посмотреть результат — Неопределено означает отсутствие реквизита.

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

В типовых конфигурациях также полезна функция «Все функции» → «Стандартные» → сведения о конфигурации, но состав реквизитов быстрее всего смотреть именно в конфигураторе или через метаданные в консоли кода.

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

Типичные ошибки при проверке реквизитов

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

Вторая ошибка — путать представление реквизита (синоним, который видит пользователь) с именем. Метод Найти() ищет по имени, а не по синониму. Если в конфигураторе реквизит называется АртикулПоставщика, а отображается как «Артикул поставщика», искать нужно по первому варианту.

Третья ошибка — попытка проверить реквизит на клиенте в тонком клиенте. Объект Метаданные там недоступен, код завершится ошибкой. Проверка выполняется на сервере.

Типичные ошибки
01
Обращение к реквизиту без проверки — ошибка «Поле объекта не обнаружено» и остановка кода
02
Поиск по синониму вместо имени — Найти() вернёт Неопределено, хотя реквизит существует
03
Вызов Метаданные на клиенте тонкого клиента — ошибка выполнения, проверку нужно перенести на сервер
04
Пропуск проверки существования самого справочника — падение кода до проверки реквизита

Когда проверка обязательна и её ограничения

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

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

Ограничение метода: Найти() ищет только по имени и не учитывает реквизиты, добавленные через расширение конфигурации в отключённом состоянии. Если расширение активно, его реквизиты видны в метаданных сеанса; если отключено — нет. Учитывайте это при работе с базами, где применяются расширения.

Итог

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

Наличие реквизита проверяется через Метаданные.Справочники.Имя.Реквизиты.Найти(ИмяРеквизита) — Неопределено означает отсутствие. Сначала проверяйте сам справочник, для табличных частей и стандартных реквизитов используйте свои коллекции, а проверку выполняйте на сервере.

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

Как проверить реквизит, если имя справочника заранее неизвестно?

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

Чем отличается проверка реквизита от проверки его заполненности?

Наличие реквизита — это свойство конфигурации, проверяется через метаданные и одинаково для всех элементов. Заполненность — свойство конкретного элемента, проверяется через ЗначениеЗаполнено() или запрос.

Можно ли проверить реквизит без программирования?

Да. Откройте конфигуратор, найдите справочник в дереве конфигурации и посмотрите список реквизитов на закладке «Данные». Это самый простой способ для разовой проверки.

Почему Найти() возвращает Неопределено, хотя реквизит виден в форме?

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

Как проверить реквизит у документа или другого объекта?

Принцип тот же: Метаданные.Документы.ИмяДокумента.Реквизиты.Найти(ИмяРеквизита). Коллекция Реквизиты есть у всех объектных типов метаданных — документов, регистров, планов счетов и других.

Замедляет ли проверка через метаданные выполнение кода?

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