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

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

При переходе с обычных форм на управляемые разработчики часто сталкиваются с задачей адаптации классических отчетов, формируемых прямым выводом областей макета в табличный документ. На управляемой форме действует клиент-серверная архитектура, из-за которой прямое обращение к элементам интерфейса вроде ЭлементыФормы.ДокументРезультат вызывает ошибки. Разберем по шагам, как правильно переписать алгоритм формирования и вывода отчета.

Ключевые отличия управляемых форм при работе с табличным документом

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

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

Вариант 1. Формирование отчета в модуле управляемой формы

Рассмотрим вариант, когда весь алгоритм выборки данных и заполнения областей находится непосредственно в модуле формы. В этом случае на форме создается реквизит (например, РезультатОтчета с типом ТабличныйДокумент), который вынесен на форму в виде поля табличного документа.

Посмотрим на пример кода модуля формы:


&НаКлиенте
Процедура СформироватьОтчет(Команда)
    СформироватьОтчетНаСервере();
КонецПроцедуры

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

Вариант 2. Вынос логики формирования в модуль объекта

Для более чистой архитектуры и повторного использования кода логику построения отчета выносят в модуль объекта, передавая табличный документ в качестве параметра.

Разберем реализацию в модуле управляемой формы:


&НаКлиенте
Процедура СформироватьОтчет(Команда)
    СформироватьВМодулеОбъекта();
КонецПроцедуры

&НаСервере
Процедура СформироватьВМодулеОбъекта()
    ОтчетОбъект = РеквизитФормыВЗначение("Отчет");
    ОтчетОбъект.СформироватьОтчет(РезультатОтчета);
КонецПроцедуры

И код процедуры в модуле объекта отчета:


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

Вариант 3. Оптимизация через серверную функцию без контекста

Если требуется минимизировать объем передаваемых данных между клиентом и сервером, генерацию отчета можно выполнять в функции с директивой &НаСервереБезКонтекста, создавая локальный табличный документ и возвращая его на клиент.

Посмотрим на реализацию:


&НаКлиенте
Процедура СформироватьОтчет(Команда)
    РезультатОтчета = СформироватьНаСервереБезКонтекста();
КонецПроцедуры

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

Важные детали при работе с группировками

Обратите внимание на вызовы методов группировки строк:

  1. Метод НачатьАвтогруппировкуСтрок() должен вызываться до начала вывода иерархических строк, а не внутри цикла.
  2. После завершения циклов вывода необходимо обязательно вызывать парный метод ЗакончитьАвтогруппировкуСтрок().
  3. Для правильного отображения уровней иерархии вторым параметром метода Вывести() рекомендуется передавать уровень выборки: ТабличныйДокумент.Вывести(Область, Выборка.Уровень()).
← На главную