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

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

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

Разбор основной проблемы: почему не работает простой обход

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

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

Решение 1: Использование метода РеквизитФормыВЗначение

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


&НаСервере
Процедура ПолучитьРеквизитыНаСервере()
    // Преобразуем данные формы в ДокументОбъект
    ДокОбъект = РеквизитФормыВЗначение("Объект");
    
    // Теперь нам доступны метаданные объекта
    Для каждого Реквизит Из ДокОбъект.Метаданные().Реквизиты Цикл
        Сообщить("Имя реквизита: " + Реквизит.Имя + " | Синоним: " + Реквизит.Синоним);
    КонецЦикла;
КонецПроцедуры

Этот метод хорош тем, что он гарантированно дает доступ ко всем свойствам метаданных. Однако помните, что РеквизитФормыВЗначение — это ресурсоемкая операция, так как система создает в памяти полную копию объекта. Если ваша цель — просто получить список имен, существуют более "легкие" способы.

Решение 2: Обращение к метаданным через ссылку

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


&НаСервере
Процедура ПолучитьСписокЧерезСсылку()
    // Проверяем, что ссылка не пустая
    Если Не Объект.Ссылка.Пустая() Тогда
        МетаданныеДокумента = Объект.Ссылка.Метаданные();
        Для каждого Реквизит Из МетаданныеДокумента.Реквизиты Цикл
            Сообщить(Реквизит.Имя);
        КонецЦикла;
    КонецЕсли;
КонецПроцедуры

Этот подход идеален для уже существующих документов. Если же вы создаете новый документ, который еще не записан, используйте метод обращения к метаданным по типу.

Решение 3: Универсальное получение метаданных по типу объекта

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


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

Важный нюанс: Стандартные реквизиты

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

Чтобы получить абсолютно все поля документа, необходимо объединить перебор двух коллекций:


&НаСервере
Процедура ПолучитьВсеВсеРеквизиты()
    МетаданныеДока = Метаданные.Документы.ЗаказПокупателя;
    
    Сообщить("--- Стандартные реквизиты ---");
    Для каждого СтрРеквизит Из МетаданныеДока.СтандартныеРеквизиты Цикл
        Сообщить(СтрРеквизит.Имя);
    КонецЦикла;
    
    Сообщить("--- Обычные реквизиты ---");
    Для каждого Реквизит Из МетаданныеДока.Реквизиты Цикл
        Сообщить(Реквизит.Имя);
    КонецЦикла;
КонецПроцедуры

Как получить не только имена, но и значения реквизитов

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


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

Дополнительные рекомендации

  1. Общие реквизиты: Помните, что в конфигурации могут быть включены Общие реквизиты. Если они входят в состав вашего документа, они могут не отображаться в коллекции Объект.Метаданные().Реквизиты. Их состав нужно проверять в ветке общих метаданных.
  2. Табличные части: Если вам нужны не только "шапочные" реквизиты, но и данные таблиц, используйте коллекцию МетаданныеОбъекта.ТабличныеЧасти. Каждая табличная часть имеет свою вложенную коллекцию Реквизиты.
  3. Права доступа: При программном переборе реквизитов всегда учитывайте права текущего пользователя. Использование метода ПравоДоступа("Чтение", МетаданныеПоля) поможет избежать критических ошибок при выполнении кода под пользователем с ограниченными правами.

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

← На главную