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

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

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

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

В чем заключается ключевая особенность управляемых форм

На управляемых формах 1С элементы интерфейса (объекты коллекции Элементы) не хранят данные самостоятельно — они лишь визуализируют реквизиты формы. Попытка выполнить прямое присвоение вида ЭтаФорма["ИмяЭлемента"] = ТабличныйДокумент или обращение через Элементы.ИмяПоля = ТабличныйДокумент приводит к ошибке «Поле объекта не обнаружено» или к неработоспособности интерфейса.

Для корректного отображения данных необходимо выполнить три обязательных шага:

  1. Программно создать реквизит формы с типом ТабличныйДокумент с помощью метода ИзменитьРеквизиты().
  2. Создать элемент формы вида ВидПоляФормы.ПолеТабличногоДокумента и связать его свойство ПутьКДанным с именем созданного реквизита.
  3. Заполнить динамический реквизит формы сформированными данными.

Типичная ошибка при создании реквизита формы

Выясним причину частой ошибки начинающих разработчиков при создании объекта РеквизитФормы. При передаче типа в конструктор напрямую:


// Вызовет ошибку "Недопустимое значение параметра (параметр номер '2')"
нРеквизит = Новый РеквизитФормы("ИмяРеквизита", Тип("ТабличныйДокумент"),,, Ложь);

Конструктор РеквизитФормы во втором параметре строго ожидает объект ОписаниеТипов, а не просто системный Тип. Правильное создание выглядит следующим образом:


нРеквизит = Новый РеквизитФормы("ИмяРеквизита", Новый ОписаниеТипов("ТабличныйДокумент"),,, Ложь);

Пошаговая реализация программного вывода табличного документа

Рассмотрим подробнее реализацию на практическом примере, когда для каждого показателя создается новая страница на панели вкладок и выводится своя детализация.


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

Важные правила работы и оптимизация

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

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

Альтернативный вариант: использование статического поля

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

← На главную