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