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