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

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

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

Comments
So empty here ... leave a comment!