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

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

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

Анализ типовых ошибок при инициализации СКД

Рассмотрим две частые ошибки, с которыми сталкиваются разработчики при попытке сформировать отчет кодом:

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

Шаг 1. Получение объекта внешнего отчета и схемы компоновки

Если отчет зарегистрирован в справочнике Дополнительные отчеты и обработки (подсистема БСП), сначала необходимо получить контекст внешнего объекта. Посмотрим на правильный пример получения схемы компоновки:


// Получаем ссылку на дополнительный отчет
ОбъектСсылка = Справочники.ДополнительныеОтчетыИОбработки.НайтиПоНаименованию("Отчет о выполненных услугах");

// Создаем экземпляр объекта внешнего отчета
ОбъектОтчет = ДополнительныеОтчетыИОбработки.ПолучитьОбъектВнешнейОбработки(ОбъектСсылка);

// Получаем схему компоновки данных из макета объекта
СхемаКомпоновкиДанных = ОбъектОтчет.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");

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

Шаг 2. Полный программный цикл компоновки данных

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

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

Рассмотрим пример серверной функции, которая выполняет весь процесс и возвращает готовый табличный документ:


&НаСервере
Функция СформироватьОтчетНаСервере()
    
    // 1. Получаем объект и схему
    ОбъектСсылка = Справочники.ДополнительныеОтчетыИОбработки.НайтиПоНаименованию("Отчет о выполненных услугах");
    ОбъектОтчет  = ДополнительныеОтчетыИОбработки.ПолучитьОбъектВнешнейОбработки(ОбъектСсылка);
    Схема        = ОбъектОтчет.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
    
    // 2. Получаем настройки схемы по умолчанию
    Настройки = Схема.НастройкиПоУмолчанию;
    
    // 3. Формируем макет компоновки
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
    
    МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки, ДанныеРасшифровки);
    
    // 4. Инициализируем процессор компоновки
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
    
    // 5. Выводим результат в табличный документ
    ТабДок = Новый ТабличныйДокумент;
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ТабДок);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
    Возврат ТабДок;

КонецФункции

Шаг 3. Вывод результата пользователю

Выясним, как отобразить сформированный документ пользователю. Существует два основных сценария:

  1. Открытие в отдельном окне: объект ТабличныйДокумент передается с сервера на клиент и открывается стандартным методом.
  2. Вывод в поле на текущей форме: табличный документ заполняется непосредственно в реквизите формы.

Посмотрим на клиентский код для открытия отчета в отдельном окне:


&НаКлиенте
Процедура СформироватьИПоказать(Команда)
    
    ТабличныйДокумент = СформироватьОтчетНаСервере();
    ТабличныйДокумент.Показать("Отчет о выполненных услугах");
    
КонецПроцедуры

Если отчет должен отображаться на форме обработки, где создан реквизит формы Результат с типом ТабличныйДокумент, на сервере следует обращаться напрямую к реквизиту по имени:


&НаСервере
Процедура ВывестиНаФормуСервер()
    
    // Очищаем реквизит формы напрямую по имени (НЕ через коллекцию Элементы)
    Результат.Очистить();
    
    // Направляем вывод сразу в реквизит формы
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(Результат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
КонецПроцедуры

Оптимизация вывода больших отчетов

Когда отчет содержит большой объем строк, единовременный вывод методом ПроцессорВывода.Вывести(...) может приводить к повышенному потреблению оперативной памяти. В таких случаях рекомендуется использовать пошаговый вывод элементов в цикле:


ПроцессорВывода.УстановитьДокумент(ТабДок);
ПроцессорВывода.НачатьВывод();

Пока Истина Цикл
    
    ЭлементРезультата = ПроцессорКомпоновки.Следующий();
    Если ЭлементРезультата = Неопределено Тогда
        Прервать;
    КонецЕсли;
    
    ПроцессорВывода.ВывестиЭлемент(ЭлементРезультата);
    
КонецЦикла;

ПроцессорВывода.ЗакончитьВывод();

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

← На главную