Расшифровка отчета на СКД с детализацией по выбранному полю на основе БСП






В данной статье рассмотрим механизм работы с расшифровкой отчета, созданного при помощи системы компоновки данных, в управляемом приложении.
Показывать буду на примере реальной задачи.
Условие: использовать имеющиеся в конфигурации механизмы БСП, с минимальными и «правильными» изменениями.
Расшифровка должны быть двух видов на каждом поле:
1. Открывать ссылочный объект
2. Открывать новую форму с детализацией табличной части документа.
Собственно ради второго пункта и писалась статья, в основном для себя, чтобы не забыть.

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

Имеется некий отчет, у него схема компоновки данных, наборы данных, ресурсы, Параметры, Настройки.

Основные настройки отчета:

1. Рассмотрим вкладку «Макеты» основной схемы компоновки данных.

В макете описано каждое поле, для того что бы можно было сделать расшифровку по ним.

Если поле не ссылочного типа:

— В параметре расшифровки указываем наименование параметра

— В параметрах макета в поле Выражение делаем выбор

— В Параметр расшифровки в поле Выражение указываем ссылку на документ, по которому будет производиться расшифровка.

Если поле ссылочного типа:

Все тоже самое, только в Параметр расшифровки добавляем 2 параметра:

— Один из низ это ссылка на элемент указанный в поле

— Второй это ссылка на документ, по которому будет производиться расшифровка

На этом со схемой компоновки данных закончили.

3. Формы в отчете я использовал БСПшные, только для расшифровки создал свою форму "ФормаРасшифровки" с типом «Форма Отчета»

4. Открываем основную форму отчета БСП, для элемента формы «ОтчетТабличныйДокумент»  ищем событие «ОбработкаРасшифровки» и переходим в нее.

В открывшейся процедуре вызываем процедуру обработки в переопределяемом модуле.

ОтчетыКлиентПереопределяемый.ОбработкаРасшифровки(ЭтотОбъект, Элемент, Расшифровка, СтандартнаяОбработка);

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

Процедура ОбработкаРасшифровки(ФормаОтчета, Элемент, Расшифровка, СтандартнаяОбработка) Экспорт

Если ФормаОтчета.НастройкиОтчета.ПолноеИмя = "Отчет.ДвижениеМаркированногоТовара" Тогда

Если ОбщегоНазначенияКлиент.ПодсистемаСуществует(
"ТакскомПодсистемы.ЭлектронныйДокументооборот.РеализацияМаркированнойПродукции") Тогда

МодульРеализацияМаркированнойПродукцииКлиент =
ОбщегоНазначенияКлиент.ОбщийМодуль("РеализацияМаркированнойПродукцииКлиент");

МодульРеализацияМаркированнойПродукцииКлиент.ОбработкаРасшифровкиОтчетаДвижениеМаркированногоТовара(
ФормаОтчета, Расшифровка, СтандартнаяОбработка);

КонецЕсли;

КонецЕсли;

КонецПроцедуры

6. Полный код вызываемой процедуры:

Процедура ОбработкаРасшифровкиОтчетаДвижениеМаркированногоТовара(ФормаОтчета, Расшифровка, СтандартнаяОбработка) Экспорт

СтандартнаяОбработка = Ложь;

ОбработкаРасшифровки = Новый ОбработкаРасшифровкиКомпоновкиДанных(
ФормаОтчета.ОтчетДанныеРасшифровки,
Новый ИсточникДоступныхНастроекКомпоновкиДанных(ФормаОтчета.Отчет));

ДополнительныеПараметры = Новый Структура;
ДополнительныеПараметры.Вставить("Расшифровка", Расшифровка);
ДополнительныеПараметры.Вставить("ОтчетДанныеРасшифровки", ФормаОтчета.ОтчетДанныеРасшифровки);
ДополнительныеПараметры.Вставить("ФормаОтчета", ФормаОтчета);

ОписаниеОповещения = Новый ОписаниеОповещения("ПоказатьВыборДействияЗавершение", ЭтотОбъект, ДополнительныеПараметры);

ДоступныеДействия = Новый Массив;
ДоступныеДействия.Добавить(ДействиеОбработкиРасшифровкиКомпоновкиДанных.ОткрытьЗначение);

ДополнительныеПунктыМеню = Новый СписокЗначений;
ДополнительныеПунктыМеню.Добавить("КодыМаркировки", НСтр("ru = 'Коды маркировки документа'"));

ОбработкаРасшифровки.ПоказатьВыборДействия(ОписаниеОповещения, Расшифровка, ДоступныеДействия, ДополнительныеПунктыМеню);

КонецПроцедуры

Разберем подробно код процедуры

Прежде всего отменяем стандартную обработку:

СтандартнаяОбработка = Ложь;

Создаем обработку расшифровки:

ОбработкаРасшифровки = Новый ОбработкаРасшифровкиКомпоновкиДанных(
ФормаОтчета.ОтчетДанныеРасшифровки,
Новый ИсточникДоступныхНастроекКомпоновкиДанных(ФормаОтчета.Отчет));

 Создаем ОписаниеОповещения с параметрами, для алгоритма после выбора действия пользователем:

ДополнительныеПараметры = Новый Структура;
ДополнительныеПараметры.Вставить("Расшифровка", Расшифровка);
ДополнительныеПараметры.Вставить("ОтчетДанныеРасшифровки", ФормаОтчета.ОтчетДанныеРасшифровки);
ДополнительныеПараметры.Вставить("ФормаОтчета", ФормаОтчета);

ОписаниеОповещения = Новый ОписаниеОповещения("ПоказатьВыборДействияЗавершение", ЭтотОбъект, ДополнительныеПараметры);

Добавляем два действия, одно платформенное, другое создаем свое собственное "КодыМаркировки":

ДоступныеДействия = Новый Массив;
ДоступныеДействия.Добавить(ДействиеОбработкиРасшифровкиКомпоновкиДанных.ОткрытьЗначение);

ДополнительныеПунктыМеню = Новый СписокЗначений;
ДополнительныеПунктыМеню.Добавить("КодыМаркировки", НСтр("ru = 'Коды маркировки документа'"));

Вызываем меню выбора действий:

ОбработкаРасшифровки.ПоказатьВыборДействия(ОписаниеОповещения, Расшифровка, ДоступныеДействия, ДополнительныеПунктыМеню);

7. В обработке оповещения обрабатываем каждый пункт меню действий

— В первом случае просто открываем объект по ссылке

— Во втором вызываем процедуру, которая нам вернет выбранное поле.

И если Выбранное поле заполнено, тогда вызываем процедуру открывающую новую форму отчета.

Процедура ПоказатьВыборДействияЗавершение(ВыполненноеДействие, ПараметрВыполненногоДействия, ДополнительныеПараметры) Экспорт

Если ВыполненноеДействие = ДействиеОбработкиРасшифровкиКомпоновкиДанных.ОткрытьЗначение Тогда

ПоказатьЗначение(Неопределено, ПараметрВыполненногоДействия);

ИначеЕсли ВыполненноеДействие = "КодыМаркировки" Тогда

ВыбранноеПоле = РеализацияМаркированнойПродукцииВызовСервера.ОбработкаРасшифровкиОтчетаДвижениеМаркированногоТовара(
ДополнительныеПараметры.ОтчетДанныеРасшифровки, ДополнительныеПараметры.Расшифровка);

Если ВыбранноеПоле = Неопределено Тогда
Возврат
КонецЕсли;

ОткрытьОтчетРасшифровкуПоВыбранномуПолю(ДополнительныеПараметры.ФормаОтчета, ВыбранноеПоле);

КонецЕсли;

КонецПроцедуры

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

Функция ОбработкаРасшифровкиОтчетаДвижениеМаркированногоТовара(ОтчетДанныеРасшифровки, Расшифровка) Экспорт

Возврат РеализацияМаркированнойПродукцииСервер.ПолеРасшифровкиОтчетаДвижениеМаркированногоТовара(
ОтчетДанныеРасшифровки, Расшифровка)

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

А уже в серверном общем модуле, описываем алгоритм получения выбранного поля Документ поступления.

Функция ПолеРасшифровкиОтчетаДвижениеМаркированногоТовара(ОтчетДанныеРасшифровки, Расшифровка) Экспорт

ДанныеРасшифровки = ПолучитьИзВременногоХранилища(ОтчетДанныеРасшифровки);
ПоляРасшифровки = ДанныеРасшифровки.Элементы.Получить(Расшифровка).ПолучитьПоля();

НайденноеПоле = ПоляРасшифровки.Найти("ДокументПоступления");
Если НайденноеПоле = Неопределено Тогда
Возврат Неопределено;
Иначе
Возврат НайденноеПоле.Значение;
КонецЕсли;

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

 

8. Процедура инициализирует открытие формы отчета с передачей параметров.

Процедура ОткрытьОтчетРасшифровкуПоВыбранномуПолю(ФормаОтчета, ВыбранноеПоле)

Отбор = Новый Структура;
Отбор.Вставить("ДокументСсылка", ВыбранноеПоле);

ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Отбор", Отбор);
ПараметрыФормы.Вставить("КлючНазначенияИспользования", "КодыМаркировки");

ОткрытьФорму(
"Отчет.ДвижениеМаркированногоТовара.Форма.ФормаРасшифровки", ПараметрыФормы, ФормаОтчета, ФормаОтчета.УникальныйИдентификатор);

КонецПроцедуры

9. В модуле открывшейся формы процедура ПриСозданииНаСервере:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

Если Параметры.Свойство("АвтоТест") Тогда
Возврат;
КонецЕсли;

СтандартнаяОбработка = Ложь;

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

Схема = Отчеты.ДвижениеМаркированногоТовара.ПолучитьМакет("РасшифровкаКодыМаркировки");
Схема.НаборыДанных[0].Запрос = Запрос;

//Из схемы возьмем настройки по умолчанию
Настройки = Схема.НастройкиПоУмолчанию;
Для Каждого СтрокаОтбора Из Параметры.Отбор Цикл

Отбор = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Отбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(СтрокаОтбора.Ключ);
Отбор.ПравоеЗначение = СтрокаОтбора.Значение;

КонецЦикла;

//Формируем макет, с помощью компоновщика макета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;

//Передаем в макет компоновки схему, настройки и данные расшифровки
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки);

//Выполним компоновку с помощью процессора компоновки
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки);

//Очищаем поле табличного документа
Результат.Очистить();

//Выводим результат в табличный документ
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(Результат);

ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);

АвтоЗаголовок = Ложь;
Заголовок = НСтр("ru = 'Коды операций (расшифровка)'");

КонецПроцедуры

Разберем ключевые строки процедуры:

— Проверяем параметры формы, и вызываем формирование динамического запроса по полученному параметру ссылки на документ.

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

— Процедура формирования динамического запроса:

&НаСервере
Функция СформироватьДинамическиЗапрос(ДокументСсылка)

ШаблонЗапроса = "ВЫБРАТЬ
| КодыМаркировки.Ссылка КАК ДокументСсылка,
| КодыМаркировки.НомерСтроки КАК НомерСтроки,
| КодыМаркировки.СерийныйНомер КАК СерийныйНомер
|ИЗ
| Документ.%1.КодыМаркировки КАК КодыМаркировки";

Запрос = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
ШаблонЗапроса,
ДокументСсылка.Метаданные().Имя);

Возврат Запрос;

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

— Получаем макет скд и в первом наборе данных переопределяем запрос, на тот, что мы сформировали динамически выше.

Схема = Отчеты.ДвижениеМаркированногоТовара.ПолучитьМакет("РасшифровкаКодыМаркировки");
Схема.НаборыДанных[0].Запрос = Запрос;

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

документа будет расшифровываться. На вкладке "Настройки" вывод детальных записей, больше настроек у этой схемы нет.

— Применяем настройки и добавляем полученный в параметрах отбор

//Из схемы возьмем настройки по умолчанию
Настройки = Схема.НастройкиПоУмолчанию;
Для Каждого СтрокаОтбора Из Параметры.Отбор Цикл

Отбор = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Отбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(СтрокаОтбора.Ключ);
Отбор.ПравоеЗначение = СтрокаОтбора.Значение;

КонецЦикла;

— После располагается типовой код по программному формированию отчета,

куда мы передаем полученную схему, и сформированные настройки отчета.

 

P.S.

Статья, по формированию расшифровки, без использования БСП

Работа с расшифровкой отчета на СКД

6 Comments

  1. artms

    Получение данных из документов, не зачет на экзамене, нужно было сделать регистр сведений, событием. Возможно здесь приводится отчет встроенный но «СформироватьДинамическиЗапрос» это мягко говоря не верно. Новый запрос, нужно сделать либо как отчет № 2 либо как второй набор данных передав параметр «КлючТекущегоВарианта», настройки. Параметры отчета нужно было передать через параметр «ПользовательскиеНастройки,Отбор», а не кодом «ПриСозданииНаСервере». Тогда ваш код не нужен почти весь, достаточно правильно настроить отчет № 2 или вариант. И сделать заполнение пользовательских настроек, полученных на основании расшифровки отчета № 2. Конечно, возможно автор пытался минимально изменить конфигурацию и это частично его оправдывает, но не оправдывает вторую часть публикации.

    Reply
  2. Viktor_Ermakov

    (1)Спасибо Вам за отзыв.

    1. «Получение данных из документов, не зачет на экзамене, нужно было сделать регистр сведений, событием» — тут Вы правы, но это уже тема архитектуры, в рамках которой я был ограничен.

    2. «СформироватьДинамическиЗапрос» — чем это плохо, поясните, ведь я заведомо не знаю тип документа по которому мне нужно получить расшифровку, поэтому формирую динамический запрос. Это кстати стандартная практика типовых решений в настоящее время.

    3. «Новый запрос, нужно сделать либо как отчет № 2 либо как второй набор данных передав параметр «КлючТекущегоВарианта»» — это уже тонкости, вариации решения. Я против отчета №2, а вот второй набор можно сделать, но не вижу ничего плохого во второй схеме компоновки.

    4. «Параметры отчета нужно было передать через параметр «ПользовательскиеНастройки,Отбор», а не кодом «ПриСозданииНаСервере»» — то что использовать нужно пользовательские настройки это да. Но что значит передать, я не понял.

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

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

    Reply
  3. artms

    (2)

    что значит передать,

    2. «СформироватьДинамическиЗапрос» — это к получению данных из документов, в логике формирования запроса динамически нет никаких нарушений.

    4.Делал открытие отчета СКД с заполнением параметров и отборами так :

    // в общем модуле на сервере
    Функция УстановитьПользовательскиеНастройкиОтчета(ТипОтчета,СтруктураПараметров)
    
    СтруктураНастроек = Новый Структура;
    ОтчетОбъект = Отчеты[ТипОтчета].Создать();
    
    ПользовательскиеНастройки = ОтчетОбъект.КомпоновщикНастроек.ПользовательскиеНастройки;
    Для Каждого ЭлПараметр  Из СтруктураПараметров Цикл
    Для Каждого ПараметрСКД Из ПользовательскиеНастройки.Элементы Цикл
    Если ТипЗнч(ПараметрСКД) = Тип(«ЗначениеПараметраНастроекКомпоновкиДанных») Тогда
    Если строка(ПараметрСКД.Параметр) = ЭлПараметр.Ключ Тогда
    ПараметрСКД.Значение = ЭлПараметр.Значение;
    ПараметрСКД.Использование = Истина;
    КонецЕсли;
    КонецЕсли;
    КонецЦикла;
    КонецЦикла;
    
    Возврат ПользовательскиеНастройки;
    
    КонецФункции
    
    &НаКлиенте
    Процедура ОткрытьЦелевойПрием()
    
    СтрПараметры = Новый Структура;
    СтрПараметры.Вставить(«ПриемнаяКампания», Объект.Ссылка);
    
    ПользовательскиеНастройки = УстановитьПользовательскиеНастройкиОтчета(«ПК_ЦелевойПрием»,СтрПараметры);
    
    Отбор = Новый Структура;
    Отбор.Вставить(«Специальность»);
    Отбор.Вставить(«УсловияОбучения»);
    ЗначенияКлючейРегистра = ЗначенияКлючейРегистра(ВыбраннаяСтрока,Отбор);
    
    ПараметрыФормы = Новый Структура(«Отбор,ПользовательскиеНастройки, СформироватьПриОткрытии», Отбор,ПользовательскиеНастройки, Истина);
    
    ОткрытьФорму(«Отчет.ПК_ЦелевойПрием.ФормаОбъекта», ПараметрыФормы);
    
    КонецПроцедуры
    

    Показать

    (УстановитьПользовательскиеНастройкиОтчета — сделана не рекурсивно, т.к. группы условий это не стандартные наборы параметров и их даже если есть устанавливать не нужно, так было принято)

    Reply
  4. bmk74

    Хм ну и заморочки, так то уже все решено за вас

    Ссылка на статью .

    Добавить в расширение, единственное они в стандартном варианте почему то не сделали ключ варианта нельзя передать в открываемый отчет, но и это можно добавить…

    Reply
  5. Viktor_Ermakov

    (4) Во первых не совсем понял как Ваше решение покрывает задачу в данной статье?

    У меня в расшифровке строится запрос к ТЧ документа, тип которого мне заранее не известен, поэтому запрос формируется динамически.

    Во вторых о каком расширении может идти речь, если ты разрабатываешь свою конфигурацию на БСП.

    Reply
  6. Viktor_Ermakov

    (3) Спасибо за пояснения, учтем.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *