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

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

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

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

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

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

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

Базовый перебор реквизитов шапки документа

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

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

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

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

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

КонецЦикла;

Обратите внимание на приём ДокументОбъект[ИмяРеквизита] — обращение к свойству объекта по строке с именем. Это стандартная возможность встроенного языка, которая и делает универсальный перебор возможным. Без неё пришлось бы писать отдельную строку кода для каждого реквизита каждого вида документа.

У элемента коллекции метаданных доступны полезные свойства: Имя, Синоним (представление для пользователя), Тип (описание типов значения), Обязательный. Если нужно вывести не внутреннее имя, а понятную подпись — используйте Реквизит.Представление().

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

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

МетаДокумент = Метаданные.Документы.РеализацияТоваровУслуг;

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

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

КонецЦикла;

Если вид документа хранится в строковой переменной, используйте индексированное обращение: Метаданные.Документы[ИмяВидаДокумента]. Перед этим полезно проверить существование вида через Метаданные.Документы.Найти(ИмяВидаДокумента) — иначе при опечатке в имени код упадёт с ошибкой.

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

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

Стандартные реквизиты — Ссылка, Номер, Дата, Проведен, ПометкаУдаления — не входят в коллекцию Реквизиты, поэтому при обычном переборе они «теряются». Для задач вроде универсального копирования или протоколирования это часто становится источником ошибок: документ копируется, а дата и номер остаются пустыми.

Стандартные реквизиты доступны через коллекцию СтандартныеРеквизиты метаданных документа:

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

ИмяРеквизита = СтандартныйРеквизит.Имя;

Сообщить(ИмяРеквизита + " = " + ДокументОбъект[ИмяРеквизита]);

КонецЦикла;

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

Как перебрать табличные части и их колонки

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

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

Сообщить("Табличная часть: " + ТабЧасть.Имя);

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

Сообщить(" Колонка: " + Колонка.Имя);

КонецЦикла;

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

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

Сообщить(Колонка.Имя + " = " + СтрокаТЧ[Колонка.Имя]);

КонецЦикла;

КонецЦикла;

КонецЦикла;

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

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

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

Практические сценарии: копирование, сравнение, выгрузка

Универсальное копирование документа

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

НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();

ЗаполнитьЗначенияСвойств(НовыйДокумент, ИсходныйДокумент);

// либо выборочно через перебор:

Для Каждого Реквизит Из ИсходныйДокумент.Метаданные().Реквизиты Цикл

НовыйДокумент[Реквизит.Имя] = ИсходныйДокумент[Реквизит.Имя];

КонецЦикла;

Для простого копирования шапки часто достаточно встроенной процедуры ЗаполнитьЗначенияСвойств(), но перебор вручную даёт контроль: можно пропускать реквизиты по списку исключений, преобразовывать значения, логировать каждое поле. Табличные части копируют отдельно через НовыйДокумент.Товары.Загрузить(ИсходныйДокумент.Товары.Выгрузить()).

Сравнение двух версий документа

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

Выгрузка в произвольный формат

При выгрузке в JSON, XML или CSV перебор метаданных позволяет автоматически сформировать структуру сообщения. Значения ссылочных типов при этом обычно заменяют на представление или GUID, иначе приёмник получит бессмысленные для него внутренние объекты.

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

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

Чтение метаданных — дешёвая операция, но многократный вызов Метаданные() внутри цикла по тысячам документов создаёт лишнюю нагрузку. Если обрабатывается массив документов одного вида, получите описание метаданных один раз до цикла и переиспользуйте его.

Перебор значений через объект требует, чтобы документ был прочитан из базы целиком. Если нужно обработать много документов, а из каждого — только несколько полей, выгоднее запрос: он выберет только нужные колонки. Перебор через метаданные оправдан, когда состав полей заранее неизвестен или должен быть полным.

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

Сравнение подходов

Перебор метаданных объекта

Подходит для универсальных механизмов и полного состава полей; требует загруженного объекта

Запрос к документу

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

ЗаполнитьЗначенияСвойств

Самый короткий код для копирования шапки, но нет контроля над отдельными реквизитами и нет табличных частей

Как проверить, что перебор работает правильно

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

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

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

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

Состав выведенных полей
Норма

Все реквизиты шапки, стандартные реквизиты и колонки табличных частей присутствуют

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

Отсутствуют Номер/Дата или целые табличные части

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

Совпадают с тем, что видно в форме документа

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

Пустые значения у заполненных полей или строки «Объект» вместо представления

Копия документа
Норма

Новый документ записывается, проводится, содержимое совпадает с исходным

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

Ошибка при записи или пустые табличные части

Часто задаваемые вопросы

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

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

Почему в переборе нет реквизитов Номер и Дата?

Это стандартные реквизиты, они хранятся в отдельной коллекции СтандартныеРеквизиты метаданных документа. Обойдите её дополнительным циклом либо обратитесь к полям напрямую, если нужны только они.

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

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

Как получить синоним (представление) реквизита для вывода пользователю?

Используйте свойство Синоним элемента коллекции метаданных или метод Реквизит.Представление(). Это удобно при формировании печатных форм и протоколов, где внутренние имена полей пользователю непонятны.

Что делать с реквизитами составного типа при переборе?

Значение читается как обычно, через Объект[Имя]. Проверить фактический тип значения помогает ТипЗнч(), а описание допустимых типов хранится в свойстве Тип метаданных реквизита — его можно разобрать через метод Типы().

Учитываются ли дополнительные реквизиты БСП при переборе метаданных?

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

Итог

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

Перебор строится на коллекциях метаданных: Реквизиты (шапка), СтандартныеРеквизиты (Номер, Дата) и ТабличныеЧасти с их колонками. Значения читают по имени через Объект[Имя]. Для копирования и обмена делайте список исключений, не трогайте системные свойства и проверяйте результат на тестовом документе.