Разработка и Конфигурация · 10 мин
Как получить все реквизиты справочника в 1С
Способы получить все реквизиты справочника 1С: через метаданные, запрос и консоль кода. Примеры на встроенном языке, типичные ошибки и проверка результата.
Задача получить все реквизиты справочника возникает у разработчика 1С регулярно: при написании универсальных обработок обмена, построении динамических отчётов, выгрузке данных во внешние системы или сравнении конфигураций. Справочник в 1С состоит из стандартных реквизитов (Ссылка, Код, Наименование, ПометкаУдаления и другие) и реквизитов, заданных в конфигураторе, поэтому «жёстко» прописывать их список в коде нельзя — при изменении конфигурации такой код сломается.
Правильный подход — обращаться к объекту метаданных справочника. Через него доступны имена, синонимы, типы и длины всех реквизитов без привязки к конкретной конфигурации. Дополнительно реквизиты можно получить через запрос с обходом по полям или через построитель запроса, если нужна не только структура, но и данные.
Ниже разобраны основные способы: перебор метаданных, получение реквизитов объекта, работа через запрос и построитель, а также особенности стандартных и табличных частей. Примеры приведены на встроенном языке 1С и подходят для версий платформы 8.3.
Получение реквизитов через метаданные
Основной и самый надёжный способ — коллекция реквизитов объекта метаданных. Каждый справочник в дереве метаданных имеет свойство Реквизиты, которое содержит описания всех реквизитов, созданных в конфигураторе. Перебор коллекции выполняется обычным циклом:
МетаСпр = Метаданные.Справочники.Номенклатура;
Для Каждого Реквизит Из МетаСпр.Реквизиты Цикл
Сообщить(Реквизит.Имя + " | " + Реквизит.Синоним + " | " + Реквизит.Тип);
КонецЦикла;
У каждого элемента коллекции доступны свойства: Имя — идентификатор реквизита, Синоним — представление для пользователя, Тип — описание типов значения, Длина и Точность для строк и чисел. Если реквизит составного типа, уточнить состав можно через Реквизит.Тип.Типы(), который вернёт массив допустимых типов.
Если имя справочника заранее неизвестно и приходит параметром, обращайтесь по строке: Метаданные.Справочники[ИмяСправочника]. Перед обращением стоит проверить существование объекта через Метаданные.Справочники.Найти(ИмяСправочника) — иначе при опечатке в имени код завершится ошибкой.
МетаСпр = Метаданные.Справочники.Найти(ИмяСправочника);
Если МетаСпр <> Неопределено Тогда
Для Каждого Реквизит Из МетаСпр.Реквизиты Цикл
Сообщить(Реквизит.Имя);
КонецЦикла;
КонецЕсли;Стандартные реквизиты справочника
Реквизиты, заданные в конфигураторе, — не полный список. У каждого справочника есть стандартные реквизиты, которые платформа создаёт автоматически: Ссылка, Код, Наименование, Владелец (для подчинённых), Родитель (для иерархических), ПометкаУдаления, Предопределенный и другие. Они хранятся в отдельной коллекции СтандартныеРеквизиты.
Для Каждого СтандРеквизит Из МетаСпр.СтандартныеРеквизиты Цикл
Сообщить(СтандРеквизит.Имя);
КонецЦикла;
Набор стандартных реквизитов зависит от настроек справочника. Если справочник не подчинённый, реквизита Владелец в коллекции не будет; если отключена иерархия — не будет Родителя. Поэтому универсальный код должен перебирать коллекцию, а не обращаться к конкретным именам напрямую.
Для получения полного списка полей объекта обычно объединяют обе коллекции: сначала стандартные реквизиты, затем пользовательские. Это особенно важно при построении универсальных выгрузок, где нужны и Код, и Наименование, и все дополнительные поля.
Реквизиты табличных частей
Если у справочника есть табличные части, их реквизиты хранятся отдельно и в коллекцию Реквизиты не попадают. Сначала перебирают коллекцию ТабличныеЧасти, затем внутри каждой — её реквизиты:
Для Каждого ТЧ Из МетаСпр.ТабличныеЧасти Цикл
Сообщить("Табличная часть: " + ТЧ.Имя);
Для Каждого Реквизит Из ТЧ.Реквизиты Цикл
Сообщить(" " + Реквизит.Имя + " (" + Реквизит.Тип + ")");
КонецЦикла;
КонецЦикла;
У табличных частей тоже есть стандартные реквизиты — как минимум НомерСтроки и Ссылка. При выгрузке данных это учитывают, чтобы не смешивать поля шапки и строк табличной части в одну плоскую структуру.
Получение реквизитов через запрос
Когда нужны не только имена, но и значения реквизитов, используют запрос. Простой вариант — выбрать все поля конструкцией ВЫБРАТЬ *, однако в явном виде список реквизитов из такого запроса не извлечь. Для анализа структуры результата служит коллекция колонок результата запроса:
Запрос = Новый Запрос("ВЫБРАТЬ ПЕРВЫЕ 1 * ИЗ Справочник.Номенклатура");
Результат = Запрос.Выполнить().Выгрузить();
Для Каждого Колонка Из Результат.Колонки Цикл
Сообщить(Колонка.Имя + " | " + Колонка.ТипЗначения);
КонецЦикла;
Этот способ удобен тем, что возвращает сразу типы значений в виде объекта ОписаниеТипов и учитывает виртуальные поля. Минус — запрос фактически обращается к базе данных, что на больших таблицах даёт лишнюю нагрузку, поэтому ограничение ПЕРВЫЕ 1 обязательно.
Сравнение способов
Подходит для анализа структуры без обращения к данным; не включает стандартные реквизиты в основной коллекции
Даёт полный набор полей с типами значений, но требует обращения к базе
Позволяет и прочитать состав полей, и динамически сформировать запрос по ним; сложнее в коде
Использование построителя запроса
Построитель запроса занимает промежуточное положение: он анализирует текст запроса и заполняет коллекцию доступных полей без необходимости вручную разбирать метаданные. Это удобно, когда по списку реквизитов нужно тут же построить динамический запрос с отборами:
Построитель = Новый ПостроительЗапроса("ВЫБРАТЬ * ИЗ Справочник.Номенклатура");
Построитель.ЗаполнитьНастройки();
Для Каждого Поле Из Построитель.ДоступныеПоля Цикл
Сообщить(Поле.Имя + " | " + Поле.ТипЗначения);
КонецЦикла;
Коллекция ДоступныеПоля содержит как реквизиты, так и поля через точку (например, реквизиты ссылочных полей), поэтому для плоского списка реквизитов самого справочника отбирайте поля верхнего уровня без вложенности.
Реквизиты конкретного объекта в режиме предприятия
Иногда нужно получить реквизиты не из метаданных, а из уже созданного объекта — например, при обходе ссылки произвольного типа. В этом случае метаданные берут от самого объекта: Ссылка.Метаданные(). Дальше логика та же — перебор коллекции реквизитов:
МетаОбъект = СсылкаНаЭлемент.Метаданные();
Для Каждого Реквизит Из МетаОбъект.Реквизиты Цикл
Значение = СсылкаНаЭлемент[Реквизит.Имя];
Сообщить(Реквизит.Имя + " = " + Значение);
КонецЦикла;
Обращение к значению реквизита по имени выполняется через квадратные скобки — это ключевой приём универсального кода. Учтите: чтение реквизитов через ссылку вызывает обращение к базе на каждый элемент, поэтому в циклах по большому числу элементов эффективнее один запрос, выбирающий нужные поля пакетно.
Типичные ошибки и проверка результата
Самая частая ошибка — ожидание, что коллекция Реквизиты содержит Код и Наименование. Их там нет: это стандартные реквизиты, и код молча «теряет» ключевые поля. Вторая типичная проблема — обращение к Метаданные.Справочники.Имя по строке без проверки существования, что приводит к падению обработки при переименовании объекта в конфигурации.
Ещё одна ошибка — игнорирование функциональных опций. Если реквизит отключён функциональной опцией, он остаётся в метаданных, но в интерфейсе и ряде механизмов недоступен. Для проверки используйте ПолучитьФункциональнуюОпцию или проверку через объект метаданных функциональной опции.
Проверить результат просто: выведите список полученных реквизитов и сравните его с закладкой «Данные» в конфигураторе для этого справочника. Количество и имена должны совпадать с учётом стандартных реквизитов и табличных частей.
Как проверить результат
Совпадает с закладкой «Данные» в конфигураторе
Отсутствуют поля — вероятно, не перебраны стандартные реквизиты или табличные части
Составные типы показывают все допустимые значения
Выводится только первый тип составного реквизита
Один запрос на пакет элементов
Обращение к базе на каждый элемент в цикле
Частые вопросы
Как получить реквизиты справочника, если известно только его имя в виде строки?
Используйте индексированное обращение: Метаданные.Справочники[ИмяСправочника]. Перед этим желательно проверить существование через Метаданные.Справочники.Найти(ИмяСправочника), чтобы избежать ошибки выполнения при неверном имени.
Почему в коллекции Реквизиты нет полей Код и Наименование?
Это стандартные реквизиты, которые платформа хранит в отдельной коллекции СтандартныеРеквизиты объекта метаданных. Для полного списка полей перебирайте обе коллекции.
Можно ли получить список реквизитов без программирования?
Да. В конфигураторе откройте справочник и перейдите на закладку «Данные» — там перечислены все реквизиты и табличные части. Также список полей виден в консоли запросов при выборе таблицы справочника.
Как узнать тип значения конкретного реквизита?
Через метаданные: Реквизит.Тип возвращает объект ОписаниеТипов. Для составного типа метод Типы() вернёт массив всех допустимых типов, а свойства Длина и Точность уточнят параметры строк и чисел.
Учитываются ли дополнительные реквизиты (БСП) в коллекции Реквизиты?
Нет. Дополнительные реквизиты и сведения из библиотеки стандартных подсистем хранятся в отдельных таблицах и не входят в метаданные справочника. Их получают через механизмы БСП, например через наборы свойств в справочнике наборов дополнительных реквизитов.
Что быстрее: метаданные или запрос с ВЫБРАТЬ *?
Метаданные. Обращение к коллекции Реквизиты не затрагивает базу данных и выполняется мгновенно. Запрос используют, когда помимо структуры нужны сами значения или типы в виде ОписаниеТипов результата.
Что важно запомнить
Все реквизиты справочника получают через Метаданные.Справочники.Имя.Реквизиты, стандартные поля — через СтандартныеРеквизиты, реквизиты табличных частей — отдельно. Для данных используйте запрос, для массовой обработки избегайте чтения реквизитов через ссылку в цикле.