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