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

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

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

Как перебрать все реквизиты объекта в 1С через метаданные: цикл по реквизитам, табличным частям, проверка заполненности, типовые ошибки и готовые примеры кода.

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

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

Ниже разобраны рабочие примеры для обычных реквизитов, стандартных реквизитов и табличных частей, а также ограничения подхода и типичные ошибки, из-за которых универсальные обработки «падают» на реальных базах.

Базовый способ: цикл по коллекции метаданных

Основной приём — обойти коллекцию Метаданные().Реквизиты и для каждого элемента прочитать значение по имени. Это работает для справочников, документов, планов счетов, планов видов характеристик, бизнес-процессов и задач.

ОбъектМетаданные = Объект.Метаданные();

Для Каждого Реквизит Из ОбъектМетаданные.Реквизиты Цикл

ИмяРеквизита = Реквизит.Имя;

Значение = Объект[ИмяРеквизита];

Сообщить(ИмяРеквизита + " = " + Значение);

КонецЦикла;

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

У каждого элемента коллекции доступны полезные свойства: Имя, Синоним, Тип (объект ОписаниеТипов), Комментарий, ПроверкаЗаполнения. Это позволяет строить универсальные механизмы: например, выводить пользователю синонимы вместо служебных имён или проверять, допускает ли реквизит строковый тип.

1c
Для Каждого Реквизит Из Объект.Метаданные().Реквизиты Цикл
    Значение = Объект[Реквизит.Имя];
    Сообщить(Реквизит.Синоним + " = " + Значение);
КонецЦикла;

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

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

Для Каждого СтандартныйРеквизит Из Объект.Метаданные().СтандартныеРеквизиты Цикл

Значение = Объект[СтандартныйРеквизит.Имя];

Сообщить(СтандартныйРеквизит.Имя + " = " + Значение);

КонецЦикла;

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

Если нужен полный перечень «всех полей», объедините оба цикла: сначала стандартные реквизиты, затем пользовательские. Не забудьте, что значение стандартного реквизита «Ссылка» у объекта совпадает с самой ссылкой, а «ПометкаУдаления» имеет булев тип.

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

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

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

Для Каждого Строка Из Объект[ТабЧасть.Имя] Цикл

Для Каждого РеквизитТЧ Из ТабЧасть.Реквизиты Цикл

Значение = Строка[РеквизитТЧ.Имя];

Сообщить(ТабЧасть.Имя + "." + РеквизитТЧ.Имя + " = " + Значение);

КонецЦикла;

КонецЦикла;

КонецЦикла;

Обращение к значению идёт через строку табличной части, а не через саму табличную часть — частая ошибка новичков. Также учитывайте, что у табличной части есть стандартный реквизит «НомерСтроки», который в коллекцию Реквизиты не входит.

Практические сценарии использования

Проверка заполненности всех реквизитов

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

Для Каждого Реквизит Из Объект.Метаданные().Реквизиты Цикл

Если Реквизит.ПроверкаЗаполнения = ПроверкаЗаполнения.ВыдаватьОшибку

И Не ЗначениеЗаполнено(Объект[Реквизит.Имя]) Тогда

Сообщить("Не заполнен реквизит: " + Реквизит.Синоним);

КонецЕсли;

КонецЦикла;

Сравнение двух объектов

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

Универсальное копирование данных

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

Порядок действий для универсального перебора
  1. 1
    Получите описание метаданных: МетаданныеОбъекта = Объект.Метаданные()
  2. 2
    Пройдите циклом по МетаданныеОбъекта.Реквизиты и читайте значения как Объект[Реквизит.Имя]
  3. 3
    При необходимости добавьте цикл по СтандартныеРеквизиты для Кода, Наименования, Номера, Даты
  4. 4
    Для табличных частей добавьте вложенный цикл по ТабличныеЧасти и строкам
  5. 5
    Проверьте результат на объекте с незаполненными реквизитами и на объекте без табличных частей

Сравнение с альтернативными подходами

Перебор через метаданные — не единственный способ. В зависимости от задачи может быть удобнее запрос или сериализация.

Сравнение вариантов

Цикл по Метаданные().Реквизиты

Подходит для обработки одного объекта в памяти: заполнение, проверка, сравнение. Неэффективен для массовой обработки тысяч записей.

Запрос с выбором полей

Быстрее при массовой обработке, но требует явного перечисления полей в тексте запроса; универсальность достигается построением текста запроса по метаданным.

Сериализация XDTO или ЗначениеВСтрокуВнутр

Удобна для выгрузки объекта целиком, но не даёт постраничного контроля над отдельными реквизитами.

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

Типичные ошибки и ограничения

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

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

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

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

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

Вывод списка реквизитов
Норма

В списке присутствуют все реквизиты из конфигуратора, включая добавленные недавно

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

Отсутствуют Код/Наименование/Номер — значит, не перебраны СтандартныеРеквизиты

Работа с табличной частью
Норма

Для каждой строки выводятся значения всех колонок

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

Ошибка обращения к свойству или одинаковые значения для всех строк

Объект без табличных частей
Норма

Цикл по ТабличныеЧасти просто не выполняется, ошибок нет

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

Код падает из-за жёсткого обращения к конкретной табличной части по имени

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

Можно ли перебрать реквизиты, не получая объект из базы?

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

Почему в цикле не видно реквизиты «Код» и «Наименование»?

Это стандартные реквизиты, они не входят в коллекцию Реквизиты. Переберите отдельно Метаданные().СтандартныеРеквизиты — там будут Код, Наименование, Ссылка, ПометкаУдаления и другие системные поля, состав которых зависит от настроек объекта.

Как перебрать реквизиты объекта на управляемой форме?

На форме данные обычно представлены как ДанныеФормыСтруктура, у которой нет метода Метаданные(). Варианты: получить метаданные через ссылку объекта (Объект.Ссылка.Метаданные()), либо преобразовать данные формы в объект через РеквизитФормыВЗначение("Объект") и работать с ним. Для чтения значений достаточно первого варианта.

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

У элемента коллекции метаданных есть свойство Тип — это объект ОписаниеТипов. Через него можно проверить, содержит ли реквизит конкретный тип: Реквизит.Тип.СодержитТип(Тип("Строка")). Это полезно при универсальном копировании или фильтрации реквизитов по типу.

Перебираются ли общие реквизиты в этой коллекции?

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

Что быстрее: перебор по метаданным или прямое обращение по именам?

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

Итог

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

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