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

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

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

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

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

Важно понимать разницу между тремя сущностями: метаданные описывают структуру справочника (какие реквизиты есть, их типы и длины), объект справочника (СправочникОбъект) хранит конкретные значения, а ссылка (СправочникСсылка) позволяет читать реквизиты через точку, но с обращением к базе. От того, с чем вы работаете, зависит выбор способа перебора.

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

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

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

Обращение к значению реквизита по имени выполняется через квадратные скобки: Объект[ИмяРеквизита]. Это работает и для СправочникОбъект, и для СправочникСсылка, и для строки выборки запроса, если реквизит присутствует в выборке. Такой универсальный механизм делает код обхода независимым от конкретного справочника.

bsl
МетаданныеСправочника = Метаданные.Справочники.Номенклатура;
Для Каждого Реквизит Из МетаданныеСправочника.Реквизиты Цикл
    ИмяРеквизита = Реквизит.Имя;
    Синоним = Реквизит.Синоним;
    ТипРеквизита = Реквизит.Тип;
КонецЦикла;

Если нужен перебор реквизитов произвольного справочника, имя которого заранее неизвестно, получайте метаданные через объект: Объект.Метаданные().Реквизиты или через ссылку: Ссылка.Метаданные().Реквизиты. Это правильный подход для универсальных обработок, работающих с любым видом справочника.

Базовый пример: перебор реквизитов и чтение значений

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

bsl
СсылкаНаЭлемент = Справочники.Номенклатура.НайтиПоКоду("000000001");
Если Не СсылкаНаЭлемент.Пустая() Тогда
    МетаданныеСпр = СсылкаНаЭлемент.Метаданные();
    Для Каждого Реквизит Из МетаданныеСпр.Реквизиты Цикл
        Значение = СсылкаНаЭлемент[Реквизит.Имя];
        Сообщить(Реквизит.Имя + " = " + Строка(Значение));
    КонецЦикла;
КонецЕсли;

Обратите внимание: при чтении реквизита через ссылку платформа выполняет обращение к базе данных. Если реквизитов много и элементов тоже много, эффективнее сначала получить объект методом Ссылка.ПолучитьОбъект() или выбрать данные запросом, а перебор метаданных использовать только для получения списка имён.

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

Перебор стандартных и общих реквизитов

Коллекция Реквизиты содержит только те реквизиты, которые разработчик добавил в конфигураторе. Стандартные реквизиты — Код, Наименование, Родитель, Владелец, ПометкаУдаления, Предопределенный — в неё не входят. Если нужен полный список полей, стандартные реквизиты перебираются отдельно через МетаданныеСпр.СтандартныеРеквизиты.

bsl
// Стандартные реквизиты
Для Каждого СтдРеквизит Из МетаданныеСпр.СтандартныеРеквизиты Цикл
    Значение = СсылкаНаЭлемент[СтдРеквизит.Имя];
КонецЦикла;

// Общие реквизиты (если используются)
Для Каждого ОбщийРеквизит Из Метаданные.ОбщиеРеквизиты Цикл
    // проверка состава через ОбщийРеквизит.Состав
КонецЦикла;

Состав стандартных реквизитов зависит от настроек справочника: если длина кода равна нулю, реквизита Код фактически нет; если справочник не иерархический, Родитель отсутствует; если нет владельцев — нет Владелец. Универсальный код должен учитывать свойства ДлинаКода, Иерархический и Владельцы метаданных справочника.

Перебор табличных частей справочника

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

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

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

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

Перебор реквизитов в управляемой форме

На клиенте в управляемом приложении метаданные недоступны — это частое затруднение у начинающих разработчиков. Перебор реквизитов выполняют на сервере в процедуре с директивой &НаСервере, а результат возвращают на клиент, например, в виде массива структур или таблицы значений, преобразованной в данные формы.

Порядок действий в управляемой форме
  1. 1
    Создайте серверную процедуру с директивой &НаСервере или &НаСервереБезКонтекста
  2. 2
    Получите метаданные справочника и переберите коллекцию Реквизиты
  3. 3
    Сформируйте массив структур с полями Имя, Синоним, Тип, Значение
  4. 4
    Верните массив в клиентскую процедуру и выведите в таблицу формы
  5. 5
    Проверьте результат на элементе с заполненными и пустыми реквизитами

Директива &НаСервереБезКонтекста предпочтительнее, если не нужен доступ к реквизитам формы: такой вызов не сериализует данные формы и работает быстрее. Однако вернуть из неё можно только сериализуемые типы — структуры, массивы, примитивы. Объект ОписаниеТипов на клиент передавать нельзя, поэтому тип реквизита преобразуйте в строку заранее.

Массовый перебор реквизитов множества элементов

Когда нужно обойти реквизиты всех элементов справочника, вложенный перебор «выборка + метаданные» — правильный подход, но чтение значений лучше делать через запрос. Запрос забирает все поля одним обращением, а метаданные используются только для формирования списка колонок.

bsl
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ * ИЗ Справочник.Номенклатура";
Выборка = Запрос.Выполнить().Выбрать();
МетаданныеСпр = Метаданные.Справочники.Номенклатура;
Пока Выборка.Следующий() Цикл
    Для Каждого Реквизит Из МетаданныеСпр.Реквизиты Цикл
        Значение = Выборка[Реквизит.Имя];
    КонецЦикла;
КонецЦикла;

Конструкция ВЫБРАТЬ * выбирает все поля, включая стандартные. Для больших справочников с сотнями тысяч элементов помните о расходе памяти: если данные не нужны одновременно, используйте обход выборки без выгрузки в таблицу значений и не накапливайте результаты в структурах без необходимости.

Типичные ошибки и как их проверить

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

Типичные ошибки
01
Поиск стандартных реквизитов (Код, Наименование) в коллекции Реквизиты — их там нет, нужна коллекция СтандартныеРеквизиты
02
Вызов Метаданные на клиенте в управляемом приложении — доступно только на сервере, код падает с ошибкой
03
Чтение реквизитов по ссылке внутри большого цикла — каждое обращение идёт в базу, производительность падает в разы
04
Попытка записать элемент, полученный как ссылка, без ПолучитьОбъект() — изменения не сохранятся
05
Игнорирование реквизитов с типом ХранилищеЗначения при выгрузке — данные теряются без предупреждения

Для проверки корректности обхода сравните количество обработанных реквизитов с числом реквизитов в конфигураторе и убедитесь, что значения совпадают с данными формы элемента. Полезно вывести тип каждого значения через ТипЗнч() — так сразу видно, где ожидалась ссылка, а пришла строка.

Контрольные точки

Как проверить результат

Число перебранных реквизитов
Норма

Совпадает с количеством реквизитов в конфигураторе

Тревожный признак

Меньше — возможно, пропущены стандартные или общие реквизиты

Значения реквизитов
Норма

Совпадают с данными в форме элемента

Тревожный признак

Пустые значения у заполненных полей — читаете не тот объект

Табличные части
Норма

Количество строк и значений совпадает с формой

Тревожный признак

Табличная часть пуста в коде, но заполнена в форме — обращение идёт к ссылке вместо объекта

FAQ

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

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

Почему в коллекции Реквизиты нет полей Код и Наименование?

Это стандартные реквизиты, которые платформа создаёт автоматически. Они находятся в отдельной коллекции СтандартныеРеквизиты метаданных справочника. Для полного обхода объедините обе коллекции в своём коде.

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

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

Как узнать тип значения реквизита при переборе?

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

Как перебрать реквизиты всех справочников конфигурации сразу?

Добавьте внешний цикл по Метаданные.Справочники: для каждого вида справочника получайте его коллекцию Реквизиты и ТабличныеЧасти. Такой подход используется в обработках выгрузки структуры конфигурации и универсальных обменах.

Что делать с реквизитами типа ХранилищеЗначения при выгрузке?

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

Итог

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

Перебор реквизитов справочника выполняется через метаданные: коллекция Реквизиты для пользовательских полей, СтандартныеРеквизиты для служебных, ТабличныеЧасти для табличных частей. Значения читаются по имени через квадратные скобки. В управляемом приложении код размещается на сервере, а при массовой обработке значения эффективнее получать запросом.