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

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

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

Причина возникновения ошибки при создании реквизитов

Разберем ситуацию, с которой часто сталкиваются начинающие разработчики. При попытке программно добавить реквизит формы через конструктор РеквизитФормы, возникает ошибка: "Недопустимое значение параметра (параметр номер '2')".

Проанализируем причину. Ошибка кроется в том, что в качестве второго параметра конструктора РеквизитФормы ожидается объект типа ОписаниеТипов, а не просто строка или ссылка на тип. Кроме того, важно понимать различие между Реквизитом формы (данными) и Элементом формы (визуальным полем). Сначала мы создаем структуру данных (реквизит), а затем привязываем к ней визуальный объект.

Шаг 1. Программное создание реквизитов и элементов формы

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

Выполним следующие действия в модуле формы:


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

КонецПроцедуры

В данном примере мы использовали ИзменитьРеквизиты. Обратите внимание, что эта операция является ресурсоемкой, поэтому ее рекомендуется выполнять один раз при создании формы.

Шаг 2. Программное формирование отчетов в табличные документы

Теперь, когда структура формы готова, нам нужно заполнить каждый табличный документ своим графиком. Это удобно делать по нажатию кнопки "Сформировать". Основная задача — в цикле обходить показатели, настраивать параметры СКД и выводить результат в соответствующий реквизит.

Рассмотрим код формирования на сервере:


&НаСервере
Процедура СформироватьНаСервере()
    
    // Получаем макет отчета из конфигурации
    ОтчетОбъект = Отчеты.ГрафикПоказателя.Создать();
    СхемаСКД = ОтчетОбъект.СхемаКомпоновкиДанных;
    Настройки = СхемаСКД.НастройкиПоУмолчанию;
    
    // Снова получаем список показателей (или кэшируем его заранее)
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ Показатель ИЗ РегистрСведений.АктуальныеПоказатели";
    Выборка = Запрос.Выполнить.Выбрать();
    
    Номер = 1;
    Пока Выборка.Следующий() Цикл
        
        ИмяРеквизита = "ТабДокПоказатель_" + Номер;
        
        // Получаем сам объект табличного документа из реквизита формы
        ТекущийТабДок = ЭтотОбъект[ИмяРеквизита];
        ТекущийТабДок.Очистить(); // Обязательно очищаем перед выводом
        
        // Устанавливаем параметр "Показатель" в настройках СКД
        ПараметрСКД = Настройки.ПараметрыДанных.Элементы.Найти("Показатель");
        Если ПараметрСКД <> Неопределено Тогда
            ПараметрСКД.Значение = Выборка.Показатель;
            ПараметрСКД.Использование = Истина;
        КонецЕсли;
        
        // Инициализируем макет компоновки
        КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
        МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаСКД, Настройки);
        
        // Процессор компоновки
        ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
        ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
        
        // Процессор вывода в конкретный табличный документ
        ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
        ПроцессорВывода.УстановитьДокумент(ТекущийТабДок);
        ПроцессорВывода.Вывести(ПроцессорКомпоновки);
        
        // Настройка отображения графиков (опционально)
        Если ТекущийТабДок.Рисунки.Количество() > 0 Тогда
            Диаграмма = ТекущийТабДок.Рисунки[0]; // Предполагаем, что график - первый рисунок
            // Здесь можно программно подогнать размер рисунка под область
        КонецЕсли;
        
        Номер = Номер + 1;
    КонецЦикла;
    
КонецПроцедуры

Важные рекомендации по оптимизации

Проанализируем ситуацию: если в базе данных окажется 50 показателей, форма будет перегружена 50-ю полями табличных документов. Это может привести к значительным задержкам в работе интерфейса (так называемым "фризам"). Чтобы этого избежать, рассмотрим несколько советов:

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

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

← На главную