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