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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Проблема клиент-серверного взаимодействия

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

Рассмотрим пошагово способы решения этой задачи, начиная от простых клиентских «хитростей» и заканчивая серверным анализом метаданных.

Способ 1. Анализ через элементы формы и ПутьКДанным

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

Разберем пример кода для обхода элементов:


// Код выполняется на клиенте для перехваченной формы
СписокРеквизитов = Новый Массив;

Для Каждого Элемент Из ФормаОбъект.Элементы Цикл
    // Проверяем наличие свойства ПутьКДанным у элемента
    Попытка
        Путь = Элемент.ПутьКДанным;
        Если ЗначениеЗаполнено(Путь) Тогда
            // Путь может быть составным, например "Объект.Наименование"
            // Нам нужно имя корневого реквизита
            ЧастиПути = СтрРазделить(Путь, ".");
            ИмяКорня = ЧастиПути[0];
            
            Если СписокРеквизитов.Найти(ИмяКорня) = Неопределено Тогда
                СписокРеквизитов.Добавить(ИмяКорня);
            КонецЕсли;
        КонецЕсли;
    Исключение
        // Не у всех элементов есть это свойство (например, у Групп)
    КонецПопытки;
КонецЦикла;

Преимущества: Работает полностью на клиенте, не требует контекстного вызова сервера.

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

Способ 2. Определение состава через метаданные по имени формы

Выясним, как получить полную структуру реквизитов, заданную в конфигураторе. Несмотря на то, что саму форму передать на сервер нельзя, мы можем передать ее полное строковое имя. Свойство ИмяФормы доступно на клиенте и содержит путь вида Справочник.Номенклатура.Форма.ФормаОбъекта.

Рассмотрим реализацию на сервере:


&НаСервереБезКонтекста
Функция ПолучитьСтруктуруРеквизитовПоИмени(ПолноеИмяФормы)
    
    Результат = Новый Массив;
    ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(ПолноеИмяФормы);
    
    Если ОбъектМетаданных <> Неопределено Тогда
        Для Каждого РеквизитФормы Из ОбъектМетаданных.Реквизиты Цикл
            Инфо = Новый Структура;
            Инфо.Вставить("Имя", РеквизитФормы.Имя);
            Инфо.Вставить("Тип", РеквизитФормы.Тип);
            Инфо.Вставить("Заголовок", РеквизитФормы.Синоним);
            Результат.Добавить(Инфо);
        КонецЦикла;
    КонецЕсли;
    
    Возврат Результат;
    
КонецФункции

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

Способ 3. Использование метода «ЗаполнитьЗначенияСвойств» как зонда

Рассмотрим ситуацию, когда нам нужно проверить наличие конкретного реквизита на клиенте, не зная структуры формы заранее. Один из самых быстрых способов — использование метода ЗаполнитьЗначенияСвойств со структурой-приемником. Это позволяет избежать медленных блоков Попытка...Исключение при обращении к несуществующим свойствам.

Посмотрим на пример «зондирования» формы:


// Список стандартных имен, которые мы хотим найти
ПотенциальныеИмена = "Объект, Запись, Список, ТекущийОбъект, Отчет";
СтруктураЗонд = Новый Структура(ПотенциальныеИмена);

// Заполняем структуру из формы. 
// Заполнятся только те поля, которые реально есть в форме как реквизиты
ЗаполнитьЗначенияСвойств(СтруктураЗонд, ИсследуемаяФорма);

Для Каждого Свойство Из СтруктураЗонд Цикл
    Если Свойство.Значение <> Неопределено Тогда
        // Реквизит найден, можем анализировать его значение
        Сообщить("Найден активный реквизит: " + Свойство.Ключ);
    КонецЕсли;
КонецЦикла;

Способ 4. Определение типа основного реквизита (Отчеты и Обработки)

Часто основной вопрос звучит так: «Как понять, что за объект стоит за формой, если это не справочник или документ?» Для ссылочных типов мы можем обратиться к Объект.Ссылка. Для отчетов и обработок ситуация сложнее, так как Объект (или Отчет) на клиенте имеет тип ДанныеФормыСтруктура, который не содержит информации о типе исходного объекта метаданных.

Выясним причину: в управляемых формах данные отвязаны от прикладных объектов для минимизации трафика. Чтобы узнать тип, проанализируем ИмяФормы. Если имя начинается с Обработка.ИмяОбработки..., мы можем на сервере получить тип:

ТипОбъекта = Тип("ОбработкаОбъект." + ИмяОбработки);

Резюме и рекомендации

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

  1. Используйте ИмяФормы для получения базового состава реквизитов через Метаданные на сервере.
  2. Перебирайте коллекцию Элементы на клиенте, чтобы найти динамически созданные или важные для интерфейса поля через ПутьКДанным.
  3. Применяйте ЗаполнитьЗначенияСвойств для быстрой проверки наличия стандартных реквизитов (Объект, Параметры) без вызова исключений.
  4. Для получения значений конкретных реквизитов (если их имена уже известны) используйте прямое обращение через точку, так как на клиенте УправляемаяФорма позволяет читать значения своих реквизитов напрямую.

Такой комплексный анализ позволит вашей универсальной обработке корректно работать с любыми формами в системе, независимо от их сложности и способа проектирования.

← На главную