В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает необходимость динамического анализа структуры управляемой формы. Например, при создании универсальных обработок, автозаполнении полей или программной валидации данных нам может потребоваться узнать, какие типы данных разрешено вводить в тот или иной реквизит формы. Попытка решить эту задачу «в лоб» через обход коллекции реквизитов часто вызывает вопросы и ошибки у начинающих разработчиков. В этой статье мы подробно разберем, как правильно и быстро получить типы реквизитов управляемой формы программными методами.
Рассмотрим типичную ситуацию, с которой столкнулся автор темы. Попытка обойти реквизиты формы с помощью встроенного метода ПолучитьРеквизиты() и получить их тип напрямую через функцию ТипЗнч() приводит к неожиданному результату:
МассивРеквизитов = ЭтаФорма.ПолучитьРеквизиты();
Для каждого Реквизит Из МассивРеквизитов Цикл
// Попытка получить тип элемента коллекции
ТипЭлемента = ТипЗнч(Реквизит);
// Результат всегда будет равен типу "РеквизитФормы"
КонецЦикла;
Выясним причину такого поведения платформы. Метод ПолучитьРеквизиты() возвращает массив, элементами которого являются объекты метаданных формы специального типа — РеквизитФормы. Именно поэтому функция ТипЗнч() для любого элемента этого массива возвращает системный тип РеквизитФормы, а не тот тип данных (например, Строка, Число или СправочникСсылка.Номенклатура), который этот реквизит отображает на форме.
Для того чтобы добраться до истинных типов данных, нам необходимо обратиться к свойствам самого объекта РеквизитФормы. У этого объекта нет свойства Тип, но зато у него есть важнейшее свойство ТипЗначения.
Давайте проанализируем структуру свойства ТипЗначения. Оно имеет тип ОписаниеТипов. Поскольку в 1С реквизиты могут быть составного типа (то есть поддерживать ввод значений нескольких разных типов одновременно), свойство ТипЗначения не хранит один конкретный тип.
Чтобы извлечь из объекта ОписаниеТипов все допустимые типы, которые назначены реквизиту в конфигураторе или программно, мы должны использовать метод Типы(). Данный метод возвращает массив обычных типов платформы 1С.
Рассмотрим по шагам, как выглядит схема получения типов для реквизита:
ЭтаФорма.ПолучитьРеквизиты() для получения коллекции описаний реквизитов.ТипЗначения (это объект ОписаниеТипов).ОписаниеТипов вызываем метод Типы(), получая массив конкретных типов данных.Обратите внимание, что метод управляемой формы ПолучитьРеквизиты() доступен исключительно на стороне сервера. Посмотрим на практический пример реализации процедуры, которая обходит все реквизиты управляемой формы верхнего уровня и выводит их типы в окно сообщений:
&НаСервере
Процедура ВывестиТипыРеквизитовФормы()
// Шаг 1. Получаем массив реквизитов верхнего уровня управляемой формы
МассивРеквизитов = ЭтаФорма.ПолучитьРеквизиты();
// Шаг 2. Обходим каждый реквизит формы
Для каждого Реквизит Из МассивРеквизитов Цикл
ИмяРеквизита = Реквизит.Имя;
// Получаем объект ОписаниеТипов для текущего реквизита
ОписаниеТиповРеквизита = Реквизит.ТипЗначения;
// Шаг 3. Получаем массив всех допустимых типов для данного реквизита
МассивДопустимыхТипов = ОписаниеТиповРеквизита.Типы();
// Шаг 4. Анализируем каждый конкретный тип в массиве
Для каждого ТекущийТип Из МассивДопустимыхТипов Цикл
// Переменная ТекущийТип содержит системное значение типа "Тип"
Сообщить("Реквизит формы: " + ИмяРеквизита + " | Допустимый тип данных: " + ТекущийТип);
КонецЦикла;
КонецЦикла;
КонецПроцедуры
При решении практических задач программирования в 1С важно учитывать несколько неочевидных тонкостей, которые помогут вам избежать ошибок при определении типов.
Если мы вызываем метод без параметров, как в примере выше — ЭтаФорма.ПолучитьРеквизиты(), то платформа вернет массив реквизитов только самого верхнего уровня. К ним относятся основной реквизит формы (обычно это Объект или Отчет), а также системные или созданные вручную реквизиты формы.
Если вам требуется узнать типы реквизитов, находящихся внутри составных объектов (например, реквизиты шапки документа или колонки табличной части), вам необходимо передать в метод строковый параметр — путь к родительскому реквизиту:
ЭтаФорма.ПолучитьРеквизиты("Объект") — вернет массив реквизитов основного объекта (например, реквизиты шапки документа: Контрагент, Дата, СуммаДокумента).ЭтаФорма.ПолучитьРеквизиты("Объект.Товары") — вернет массив реквизитов (колонок) табличной части «Товары».В процессе обсуждения на форумах часто возникает путаница между типами самого реквизита формы и типами значения, которое в данный момент в этот реквизит записано. Разберем это различие:
ТипЗнч(ЭтаФорма.ИмяРеквизита), мы получаем тип значения, которое физически находится в поле в данный момент времени. Если реквизит не заполнен, мы можем получить тип Неопределено. Если реквизит имеет составной тип, то в разные моменты времени ТипЗнч() будет возвращать разные типы в зависимости от выбора пользователя.ПолучитьРеквизиты() анализирует схему данных формы, созданную в конфигураторе. Это описание типов статично и никак не зависит от того, заполнено поле на форме в данный момент или нет. Оно возвращает весь спектр типов, которые в принципе разрешено выбирать в данном поле.Используя предложенные методики работы со свойствами объекта РеквизитФормы, вы сможете легко решать любые задачи, связанные с динамическим анализом типов данных на управляемых формах 1С.