Разработка и Конфигурация · 10 мин
Как проверить наличие реквизита в справочнике 1С
Как проверить наличие реквизита в справочнике 1С через метаданные, функцию Найти и код на встроенном языке. Примеры, типичные ошибки и частые вопросы.
Проверка наличия реквизита у справочника — типовая задача при написании универсальных обработок, обменов данными и внешних отчётов. Если обратиться к несуществующему реквизиту напрямую, встроенный язык выдаст ошибку «Поле объекта не обнаружено», и выполнение кода прервётся. Поэтому перед обращением к реквизиту его существование проверяют через коллекцию метаданных.
Основной инструмент проверки — объект Метаданные и свойство Реквизиты объекта метаданных справочника. Метод Найти() возвращает описание реквизита, если он есть, и Неопределено, если реквизита нет. Этот подход работает в любой конфигурации и не зависит от состава конкретного справочника.
Важно различать две задачи: проверить наличие реквизита в структуре справочника (есть ли такое поле в конфигурации) и проверить заполненность значения у конкретного элемента. Ниже разобраны обе ситуации, а также проверка табличных частей, стандартных реквизитов и типовые ошибки.
Как проверить реквизит через метаданные
Каждый объект конфигурации описывается в дереве метаданных. Для справочника состав реквизитов хранится в свойстве Реквизиты объекта метаданных. Метод Найти() принимает имя реквизита строкой и возвращает либо объект описания, либо Неопределено.
МетаданныеСправочника = Метаданные.Справочники.Номенклатура;
РеквизитАртикул = МетаданныеСправочника.Реквизиты.Найти("Артикул");
Если РеквизитАртикул <> Неопределено Тогда
Сообщить("Реквизит ""Артикул"" существует");
Иначе
Сообщить("Реквизита ""Артикул"" нет в справочнике");
КонецЕсли;
Имя реквизита указывается без пробелов, точно так, как оно задано в конфигураторе. Регистр букв значения не имеет, но лучше копировать имя из конфигуратора, чтобы не ошибиться в написании. Проверка выполняется мгновенно и не обращается к базе данных — метаданные загружены в память сеанса.
Такой способ подходит, когда имя справочника известно заранее. Если справочник тоже определяется динамически, сначала проверяют его наличие через Метаданные.Справочники.Найти("ИмяСправочника"), и только потом ищут реквизит.
Если Метаданные.Справочники.Номенклатура.Реквизиты.Найти("Артикул") <> Неопределено Тогда
// реквизит существует
КонецЕсли;Универсальная функция проверки реквизита
Если проверка нужна в нескольких местах, её выносят в отдельную функцию общего модуля. Функция принимает имя справочника и имя реквизита строками, что позволяет использовать её в динамическом коде — например, при загрузке данных из файлов, где состав колонок заранее неизвестен.
Функция РеквизитСправочникаСуществует(ИмяСправочника, ИмяРеквизита) Экспорт
МетаданныеСпр = Метаданные.Справочники.Найти(ИмяСправочника);
Если МетаданныеСпр = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
Возврат МетаданныеСпр.Реквизиты.Найти(ИмяРеквизита) <> Неопределено;
КонецФункции
Обратите внимание на двойную проверку: сначала существование самого справочника, затем реквизита. Если пропустить первый шаг и обратиться к несуществующему справочнику, код упадёт с ошибкой ещё до проверки реквизита. В универсальных обработках обе проверки обязательны.
Функцию удобно размещать в общем модуле с признаком «Сервер», так как обращение к метаданным на клиенте в тонком и веб-клиенте ограничено. Вызов из клиентского кода делается через серверную процедуру.
Как проверить состав табличной части и стандартные реквизиты
Реквизиты табличных частей хранятся отдельно от реквизитов шапки. Сначала проверяют наличие самой табличной части через ТабличныеЧасти.Найти(), затем ищут реквизит внутри неё.
МетаданныеСпр = Метаданные.Справочники.Контрагенты;
ТабличнаяЧасть = МетаданныеСпр.ТабличныеЧасти.Найти("КонтактнаяИнформация");
Если ТабличнаяЧасть <> Неопределено
И ТабличнаяЧасть.Реквизиты.Найти("Представление") <> Неопределено Тогда
// реквизит табличной части существует
КонецЕсли;
Стандартные реквизиты — Код, Наименование, Владелец, Родитель, ПометкаУдаления — находятся в коллекции СтандартныеРеквизиты. Они присутствуют у большинства справочников, но их состав зависит от настроек: например, Владелец есть только у подчинённых справочников, а Родитель — у иерархических.
Если МетаданныеСпр.СтандартныеРеквизиты.Найти("Владелец") <> Неопределено Тогда
// справочник подчинённый
КонецЕсли;
Через стандартные реквизиты удобно определять свойства справочника без прямого анализа настроек: наличие Родителя означает иерархию, наличие Владельца — подчинённость другому объекту.
Как проверить заполненность реквизита у элемента
Отдельная задача — узнать, заполнен ли реквизит у конкретного элемента справочника. Здесь метаданные не нужны: проверяется значение через функцию ЗначениеЗаполнено() или сравнение с пустым значением соответствующего типа.
Элемент = Справочники.Номенклатура.НайтиПоКоду("000000123");
Если ЗначениеЗаполнено(Элемент.Артикул) Тогда
Сообщить("Артикул заполнен: " + Элемент.Артикул);
Иначе
Сообщить("Артикул не указан");
КонецЕсли;
Для ссылочных реквизитов пустое значение — это пустая ссылка соответствующего типа, для строк — пустая строка, для чисел — ноль. Функция ЗначениеЗаполнено() корректно обрабатывает все эти случаи, поэтому предпочтительнее ручных сравнений.
Если нужно проверить заполненность у большого числа элементов, используют запрос с условием ГДЕ Реквизит = &ПустоеЗначение или Реквизит ЕСТЬ NULL — это быстрее, чем перебор объектов в цикле, и не выгружает данные в память.
Сравнение способов проверки
Проверяет наличие реквизита в структуре конфигурации. Подходит для универсального кода, не обращается к данным.
Проверяет, заполнено ли значение у конкретного элемента. Требует, чтобы реквизит существовал.
Проверяет заполненность сразу у множества элементов. Оптимален для массовой обработки.
Проверка через консоль кода и отладчик
Не всегда нужно писать обработку: разовую проверку удобно выполнить в консоли кода или через окно «Вычислить выражение» в отладчике. Достаточно ввести выражение Метаданные.Справочники.Номенклатура.Реквизиты.Найти("Артикул") и посмотреть результат — Неопределено означает отсутствие реквизита.
Альтернатива без программирования — открыть конфигуратор, найти справочник в дереве конфигурации и посмотреть состав реквизитов на закладке «Данные». Это самый надёжный способ, если есть доступ к конфигуратору и не требуется проверка в работающем коде.
В типовых конфигурациях также полезна функция «Все функции» → «Стандартные» → сведения о конфигурации, но состав реквизитов быстрее всего смотреть именно в конфигураторе или через метаданные в консоли кода.
- 1Определите точное имя справочника и реквизита в конфигураторе
- 2Проверьте наличие справочника: Метаданные.Справочники.Найти(Имя)
- 3Проверьте реквизит: Реквизиты.Найти(ИмяРеквизита)
- 4Если результат Неопределено — реквизита нет, обращаться к нему нельзя
- 5Для табличных частей повторите поиск внутри ТабличныеЧасти
- 6Проверьте результат на тестовой базе перед запуском в рабочей
Типичные ошибки при проверке реквизитов
Самая частая ошибка — обращение к реквизиту без проверки в коде, который должен работать с разными конфигурациями. Обработка, написанная под одну базу, падает на другой, где реквизит переименован или удалён. Универсальный код всегда проверяет структуру через метаданные.
Вторая ошибка — путать представление реквизита (синоним, который видит пользователь) с именем. Метод Найти() ищет по имени, а не по синониму. Если в конфигураторе реквизит называется АртикулПоставщика, а отображается как «Артикул поставщика», искать нужно по первому варианту.
Третья ошибка — попытка проверить реквизит на клиенте в тонком клиенте. Объект Метаданные там недоступен, код завершится ошибкой. Проверка выполняется на сервере.
Когда проверка обязательна и её ограничения
Проверка обязательна во внешних обработках и отчётах, которые запускаются в разных базах: состав реквизитов в них отличается. Также она нужна при обмене данными, загрузке из Excel и в механизмах, где имя реквизита приходит из настроек или файла сопоставления.
В коде, жёстко привязанном к одной конфигурации, проверка избыточна — она замедляет чтение кода и не даёт выигрыша, так как состав реквизитов фиксирован. Там достаточно прямого обращения.
Ограничение метода: Найти() ищет только по имени и не учитывает реквизиты, добавленные через расширение конфигурации в отключённом состоянии. Если расширение активно, его реквизиты видны в метаданных сеанса; если отключено — нет. Учитывайте это при работе с базами, где применяются расширения.
Что важно запомнить
Наличие реквизита проверяется через Метаданные.Справочники.Имя.Реквизиты.Найти(ИмяРеквизита) — Неопределено означает отсутствие. Сначала проверяйте сам справочник, для табличных частей и стандартных реквизитов используйте свои коллекции, а проверку выполняйте на сервере.
Частые вопросы
Как проверить реквизит, если имя справочника заранее неизвестно?
Используйте динамическое обращение: Метаданные.Справочники.Найти(ИмяСправочника), где имя передаётся строкой. Полученный объект метаданных проверяйте на Неопределено, затем ищите реквизит через Реквизиты.Найти().
Чем отличается проверка реквизита от проверки его заполненности?
Наличие реквизита — это свойство конфигурации, проверяется через метаданные и одинаково для всех элементов. Заполненность — свойство конкретного элемента, проверяется через ЗначениеЗаполнено() или запрос.
Можно ли проверить реквизит без программирования?
Да. Откройте конфигуратор, найдите справочник в дереве конфигурации и посмотрите список реквизитов на закладке «Данные». Это самый простой способ для разовой проверки.
Почему Найти() возвращает Неопределено, хотя реквизит виден в форме?
Скорее всего, вы ищете по синониму (отображаемому названию), а не по имени. Откройте свойства реквизита в конфигураторе и используйте значение поля «Имя». Также проверьте, не добавлен ли реквизит отключённым расширением.
Как проверить реквизит у документа или другого объекта?
Принцип тот же: Метаданные.Документы.ИмяДокумента.Реквизиты.Найти(ИмяРеквизита). Коллекция Реквизиты есть у всех объектных типов метаданных — документов, регистров, планов счетов и других.
Замедляет ли проверка через метаданные выполнение кода?
Нет. Метаданные загружены в память сеанса, и поиск по коллекции выполняется практически мгновенно, без обращения к базе данных. Проверку можно смело выполнять в циклах.