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

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

Как получить все реквизиты формы в 1С

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

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

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

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

Как работает метод ПолучитьРеквизиты()

Метод ПолучитьРеквизиты() вызывается у объекта управляемой формы и возвращает массив, каждый элемент которого — объект типа «РеквизитФормы». У элемента массива доступны свойства: Имя (строка с именем реквизита), Путь (путь к данным для реквизитов, связанных с объектом), Заголовок и ТипЗначения (объект «ОписаниеТипов»).

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

Типовой пример обхода всех реквизитов формы:

МассивРеквизитов = ЭтотОбъект.ПолучитьРеквизиты();

Для Каждого Реквизит Из МассивРеквизитов Цикл

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

КонецЦикла;

Обратите внимание: метод возвращает только описания (метаданные уровня формы), а не сами значения. Чтобы получить значение, нужно обратиться к реквизиту по имени через квадратные скобки: ЭтотОбъект[Реквизит.Имя] в серверном контексте модуля формы.

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

Получение реквизитов на клиенте и на сервере

Метод ПолучитьРеквизиты() доступен как в клиентском, так и в серверном контексте модуля формы. На клиенте обращение идёт через ЭтаФорма.ПолучитьРеквизиты(), на сервере внутри модуля формы — через ЭтотОбъект.ПолучитьРеквизиты(). Состав возвращаемых данных одинаков, но работа со значениями отличается.

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

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

Отличие реквизитов формы от реквизитов объекта и элементов управления

Частая путаница у начинающих разработчиков — смешение трёх разных сущностей: реквизитов формы, реквизитов объекта метаданных и элементов управления (полей ввода, таблиц) на форме. Это не одно и то же, и методы их получения различаются.

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

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

Что получаемМетод / коллекцияКогда использовать
Реквизиты формыПолучитьРеквизиты()Обход всех данных формы, сериализация, универсальные механизмы
Реквизиты объекта метаданныхМетаданные.<Объект>.РеквизитыРабота с объектом вне формы, построение запросов, обмены
Элементы управленияЭтаФорма.ЭлементыУправление видимостью, доступностью, оформлением полей

Обход реквизитов с получением значений: практический пример

Рассмотрим прикладную задачу: собрать все реквизиты формы верхнего уровня вместе со значениями в структуру для последующей обработки. Код выполняется на сервере в модуле формы:

&НаСервере

Функция СобратьДанныеФормы()

Результат = Новый Структура;

Для Каждого Реквизит Из ЭтотОбъект.ПолучитьРеквизиты() Цикл

Попытка

Результат.Вставить(Реквизит.Имя, ЭтотОбъект[Реквизит.Имя]);

Исключение

// Реквизит содержит несериализуемый тип — пропускаем

КонецПопытки;

КонецЦикла;

Возврат Результат;

КонецФункции

Обратите внимание на конструкцию «Попытка/Исключение»: некоторые реквизиты содержат типы, которые нельзя поместить в структуру для передачи на клиент (например, «ДанныеФормыДерево» в определённых контекстах или хранилища значений со сложным содержимым). Без обработки исключения универсальный обход упадёт на первом же таком реквизите.

Для реквизитов табличного типа («ТаблицаЗначений», «ДанныеФормыКоллекция») простого обращения по имени недостаточно, если нужно выгрузить строки. Проверяйте тип через ТипЗнч() и обрабатывайте коллекции отдельным циклом по строкам.

Типичные ошибки
01
Обход ЭтаФорма.Элементы вместо ПолучитьРеквизиты() — в результат попадают надписи, группы и кнопки, а не данные
02
Отсутствие Попытка/Исключение при универсальном обходе — код падает на реквизитах с несериализуемыми типами
03
Попытка обратиться к значению реквизита на клиенте, когда тип доступен только на сервере
04
Ожидание, что ПолучитьРеквизиты() вернёт реквизиты табличных частей объекта — их нужно получать через колонки соответствующего реквизита-коллекции

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

Если форма содержит реквизит типа «ТаблицаЗначений» или «ДинамическийСписок», метод ПолучитьРеквизиты() вернёт только сам реквизит-коллекцию, но не её колонки. Для получения колонок таблицы значений на сервере используйте метод ПолучитьРеквизиты("ИмяТаблицы") — он вернёт массив подчинённых реквизитов, то есть колонок.

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

Для динамического списка состав доступных полей определяется не реквизитами формы, а настройками самого списка: запросом, основной таблицей и настройками компоновки данных. Получать их нужно через свойства списка (ЭтаФорма.Список.КомпоновщикНастроек), а не через обход реквизитов.

Маршрут решения

Как выбрать подход

Нужны все данные формы верхнего уровняИспользуйте ПолучитьРеквизиты() без параметров
Нужны реквизиты редактируемого объекта (документа, справочника)Вызовите ПолучитьРеквизиты("Объект") или обратитесь к метаданным объекта
Нужны колонки таблицы значений на формеВызовите ПолучитьРеквизиты("ИмяТаблицы")
Нужны только видимые пользователю поляОбходите ЭтаФорма.Элементы и читайте свойство ПутьКДанным

Проверка результата и отладка

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

Для отладки удобно использовать «Табло» (окно вычисления выражений) в режиме предприятия при остановке в точке останова: выражение ЭтотОбъект.ПолучитьРеквизиты().Количество() покажет число реквизитов, а обращение к элементу массива по индексу — свойства конкретного реквизита.

Если ожидаемый реквизит отсутствует в результате, проверьте три вещи: не ищете ли вы его на другом уровне иерархии (нужен параметр «Путь»), не является ли искомое поле элементом управления без связи с данными, и не добавлен ли реквизит программно после момента вызова вашего кода.

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

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

Количество реквизитов в результате
Норма

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

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

Меньше ожидаемого — вероятно, часть реквизитов подчинена другому реквизиту

Имена реквизитов
Норма

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

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

Есть лишние служебные имена или отсутствуют динамические реквизиты

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

Читаются через ЭтотОбъект[Имя] без исключений

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

Ошибка обращения — тип недоступен в текущем контексте выполнения

Ограничения и безопасные границы самостоятельной работы

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

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

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

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

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

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

Почему ПолучитьРеквизиты() не возвращает колонки табличной части документа?

Метод без параметров возвращает только реквизиты верхнего уровня. Колонки табличной части — это подчинённые реквизиты; получите их вызовом ПолучитьРеквизиты("Объект.ИмяТабличнойЧасти") или обратитесь к метаданным документа.

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

Найдите реквизит в массиве, возвращаемом ПолучитьРеквизиты(), по имени и прочитайте свойство ТипЗначения — это объект «ОписаниеТипов». Для вывода в строку используйте Строка(Реквизит.ТипЗначения).

Работает ли метод в обычных формах?

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

Как отличить реквизит-коллекцию от простого реквизита при обходе?

Проверьте ТипЗначения реквизита: для таблиц значений описание типов будет содержать тип «ТаблицаЗначений» или «ДанныеФормыКоллекция». Альтернатива — попытаться получить подчинённые реквизиты вызовом ПолучитьРеквизиты(Имя): непустой результат означает наличие колонок.

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

Да, метод ИзменитьРеквизиты() позволяет добавлять и удалять реквизиты формы в runtime. После изменения вызов ПолучитьРеквизиты() вернёт уже актуальный состав. Учтите, что удаление реквизита, связанного с элементом управления, требует предварительного удаления элемента.

Итог

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

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