Реализация основана на статье Нестандартная расшифровка СКД или расшифровка одного отчета СКД при помощи другого отчета СКД, но имеет существенное дополнение, а именно позволяет производить как стандартное действие расшифровки отчета, так и нестандартное (расшифровку через другой отчет). Причем управление параметрами и отборами в текущей реализации вынесено в отдельные процедуры и функции, что повысило наглядность кода.
За основу отчета для расшифровки взят [УТ11] Дебиторка fifo по долгам контрагентов (СКД, управляемый интерфейс), к которому добавлена актуальная возможность расшифровки через стандартный отчет УТ11 "РасчетыСПартнерами".
Сама методика работает в любой конфигурации на управляемых формах, но пример привожу для УТ11. Отчет интересен не только как реализация методики гибкой расшифровки, но и как удобное подспорье, для пользователя непосредственно при использовании.
Анимированная gif картинка показывает то, что увидит пользователь при попытке расшифровки по элементу "Партнер", предварительно построенного начального отчета:
Т.е. при двойном клике по ячейке, в которой содержится информация о Партнере, открывается дополнительное уточняющее меню, в котором можно выбрать действие по умолчанию "Открыть...", либо получить уточняющий отчет "Показать расчеты с отбором...", причем по разным интервалам времени.
Реализация:
-
Прежде всего, чтобы иметь возможность запрограммировать расшифровку нам понадобится форма расшифровываемого отчета, например ФормаОтчета, её необходимо добавить (элементы формы система добавит сама).
-
Для элемента формы «Результат» в событии «ОбработкаРасшифровки» нужно добавить процедуру, например: «РезультатОбработкаРасшифровки»
-
В модуле этой формы (ФормаОтчета) нужно наполнить процедуру РезультатОбработкаРасшифровки содержимым:
&НаКлиенте
Процедура РезультатОбработкаРасшифровки(Элемент, Расшифровка, СтандартнаяОбработка)
ЭтоГруппа = Ложь;
//Заполняем массив отрабатывемых типов
МассивРасшифровываемых = Новый Массив();
МассивРасшифровываемых.Добавить("Партнер");
МассивРасшифровываемых.Добавить("Контрагент");
МассивРасшифровываемых.Добавить("Организация");
//Получаем значение, по которому произвели двойной щелчек
РасшифровываемоеЗначение = ПолучитьРасшифровкуНаСервере(Расшифровка, МассивРасшифровываемых, ЭтоГруппа); //Партнер, Контрагент или Организация.
Если РасшифровываемоеЗначение = Неопределено Тогда Возврат; КонецЕсли;
СтандартнаяОбработка = Ложь;
//Создание и заполнени объекта ОбработкаРасшифровкиКомпоновкиДанных (подробности в Хелпе)
ОбработкаРасшифровки = Новый ОбработкаРасшифровкиКомпоновкиДанных(ДанныеРасшифровки, Новый ИсточникДоступныхНастроекКомпоновкиДанных(Отчет));
ВыполненноеДействие = ДействиеОбработкиРасшифровкиКомпоновкиДанных.Нет;
ПараметрВыполненногоДействия = Неопределено;
ДоступныеДействия = Новый Массив;
ДоступныеДействия.Добавить(ДействиеОбработкиРасшифровкиКомпоновкиДанных.ОткрытьЗначение);
//ДоступныеДействия.Добавить(ДействиеОбработкиРасшифровкиКомпоновкиДанных.Отфильтровать);
//ДоступныеДействия.Добавить(ДействиеОбработкиРасшифровкиКомпоновкиДанных.Оформить);
//ДоступныеДействия.Добавить(ДействиеОбработкиРасшифровкиКомпоновкиДанных.Расшифровать);
//ДоступныеДействия.Добавить(ДействиеОбработкиРасшифровкиКомпоновкиДанных.Сгруппировать);
//ДоступныеДействия.Добавить(ДействиеОбработкиРасшифровкиКомпоновкиДанных.Упорядочить);
ДополнительныеПунктыМеню = Новый СписокЗначений;
ОбщаяСтрока = "Показать расчеты с отбором " + """" + Строка(ТипЗнч(РасшифровываемоеЗначение)) + " = " + РасшифровываемоеЗначение + """";
ДополнительныеПунктыМеню.Добавить( 1, ОбщаяСтрока + " за месяц");
ДополнительныеПунктыМеню.Добавить( 3, ОбщаяСтрока + " за 3 месяца");
ДополнительныеПунктыМеню.Добавить( 6, ОбщаяСтрока + " за пол года");
ДополнительныеПунктыМеню.Добавить(12, ОбщаяСтрока + " за год");
//Выдаем меню расшифровки, считываем реакцию пользователя
ОбработкаРасшифровки.ВыбратьДействие(Расшифровка, ВыполненноеДействие, ПараметрВыполненногоДействия, ДоступныеДействия, ДополнительныеПунктыМеню);
Если ВыполненноеДействие = ДействиеОбработкиРасшифровкиКомпоновкиДанных.Нет Тогда
ИначеЕсли ВыполненноеДействие = ДействиеОбработкиРасшифровкиКомпоновкиДанных.ОткрытьЗначение Тогда
//Имитация стандартного действия
ОткрытьЗначение(ПараметрВыполненногоДействия);
ИначеЕсли ТипЗнч(ВыполненноеДействие) = Тип("Число") Тогда // Тут требуется наша расшифровка
ФормаР = ПолучитьФорму("Отчет.РасчетыСПартнерами.Форма", , , РасшифровываемоеЗначение); //Форма Расшифровки.
КомпоновщикНастроек = ЭтаФорма.Отчет.КомпоновщикНастроек;
КомпоновщикНастроекР = ФормаР.Отчет.КомпоновщикНастроек;
//Заполняем настройки отчета расшифровки
УстановитьЗначениеОтбораКомпоновщикаНастроекПоОбразцу(КомпоновщикНастроек, КомпоновщикНастроекР, "Партнер");
УстановитьЗначениеОтбораКомпоновщикаНастроекПоОбразцу(КомпоновщикНастроек, КомпоновщикНастроекР, "Контрагент");
УстановитьЗначениеОтбораКомпоновщикаНастроек(КомпоновщикНастроекР, Строка(ТипЗнч(РасшифровываемоеЗначение)), РасшифровываемоеЗначение, ?(ЭтоГруппа, ВидСравненияКомпоновкиДанных.ВИерархии, ВидСравненияКомпоновкиДанных.Равно));
ДатаКонца = ПолучитьЗначениеПераметраКомпоновщикаНастроек(ЭтаФорма.Отчет.КомпоновщикНастроек, "ДатаКонца");
ПериодОтчета = Новый СтандартныйПериод(ДобавитьМесяц(ДатаКонца, - ВыполненноеДействие), ДатаКонца);
УстановитьЗначениеПераметраКомпоновщикаНастроек(КомпоновщикНастроекР, "Период", ПериодОтчета);
//Формируем и выводим отчета-расшифровку
СтруктураВозврата = ОбработатьРасшифровкуНаСервере(ФормаР.Отчет, "ОтчетОбъект.РасчетыСПартнерами", ФормаР.Результат, ФормаР.ДанныеРасшифровки, ФормаР.УникальныйИдентификатор);
ФормаР.Результат = СтруктураВозврата.Результат;
ФормаР.ДанныеРасшифровки = СтруктураВозврата.ДанныеРасшифровки;
ФормаР.Элементы.Результат.ОтображениеСостояния.Видимость = Ложь; //Избавление от надписи. Отчет не сформирован
ФормаР.Элементы.Результат.ОтображениеСостояния.ДополнительныйРежимОтображения = ДополнительныйРежимОтображения.НеИспользовать;
ФормаР.Открыть();
КонецЕсли;
КонецПроцедуры
Серверная процедура ПолучитьРасшифровкуНаСервере, вызываемая из РезультатОбработкаРасшифровки - получает значение расшифровки (конкретную ссылку на элемент справочника, список типов которых переданы в параметрах), а также возвращает признак группы ЭтоГруппа:
&НаСервере
Функция ПолучитьРасшифровкуНаСервере(Расшифровка, МассивИменРасшифровки, ЭтоГруппа = Ложь)
Данные = ПолучитьИзВременногоХранилища(ДанныеРасшифровки);
Поля = Данные.Элементы.Получить(Расшифровка).ПолучитьПоля();
Для Каждого ИмяРасшифровки Из МассивИменРасшифровки Цикл
ПолеНоменклатура = Поля.Найти(ИмяРасшифровки);
Если Не ПолеНоменклатура = Неопределено Тогда Прервать; КонецЕсли;
КонецЦикла;
Если ПолеНоменклатура = Неопределено Тогда
Возврат Неопределено;
Иначе
ЭтоГруппа = ПолеНоменклатура.Значение.ЭтоГруппа;
Возврат ПолеНоменклатура.Значение;
КонецЕсли;
КонецФункции
Клиентская процедура УстановитьЗначениеОтбораКомпоновщикаНастроек вызываемая из РезультатОбработкаРасшифровки (и из УстановитьЗначениеОтбораКомпоновщикаНастроекПоОбразцу) - устанавливает параметры отбора Компоновщика настроек отчета расшифровки, сначала пытается произвести установку пользовательских настроек отбора:
&НаКлиенте
Процедура УстановитьЗначениеОтбораКомпоновщикаНастроек(КомпоновщикНастроекР, ИмяОтбора, Значение, ВидСравнения, Использование = Истина)
ПолеЭлементаОтбора = КомпоновщикНастроекР.Настройки.Отбор.ДоступныеПоляОтбора.Элементы.Найти(ИмяОтбора).Поле;
ИДЭлмОтбора = "";
Для Каждого Элемент Из КомпоновщикНастроекР.Настройки.Отбор.Элементы Цикл
Если Элемент.ЛевоеЗначение = ПолеЭлементаОтбора Тогда ИДЭлмОтбора = Элемент.ИдентификаторПользовательскойНастройки; Прервать; КонецЕсли;
КонецЦикла;
КоллекцияР = КомпоновщикНастроекР.ПользовательскиеНастройки.Элементы; //Пользовательские настройки
Если ИДЭлмОтбора = "" Тогда //Не нашли среди стандартных настроек
Для Каждого Элемент Из КоллекцияР Цикл //Ищем отбор, и добавляем в него.
Если ТипЗнч(Элемент) = Тип("ОтборКомпоновкиДанных") Тогда
ПолеОтбора = Новый ПолеКомпоновкиДанных(ИмяОтбора);
ОтборНайден = Ложь;
Для Каждого ЭлементОтбора Из Элемент.Элементы Цикл
Если ЭлементОтбора.ЛевоеЗначение = ПолеОтбора Тогда ОтборНайден = Истина; Прервать; КонецЕсли;
КонецЦикла;
Если Не ОтборНайден Тогда
ЭлементОтбора = Элемент.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Элемент.Элементы[0].ЛевоеЗначение = ПолеОтбора;
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ИмяОтбора);
КонецЕсли;
Прервать;
КонецЕсли;
КонецЦикла;
Иначе
ЭлементОтбора = КоллекцияР.Найти(ИДЭлмОтбора);
КонецЕсли;
ЭлементОтбора.ПравоеЗначение = Значение;
ЭлементОтбора.Использование = Использование;
ЭлементОтбора.ВидСравнения = ВидСравнения;
КонецПроцедуры
Клиентская процедура УстановитьЗначениеОтбораКомпоновщикаНастроекПоОбразцу вызываемая из РезультатОбработкаРасшифровки - устанавливает параметры отбора Компоновщика настроек отчета расшифровки извлекая их из текущего (расшифровываемого) отчета:
&НаКлиенте
Процедура УстановитьЗначениеОтбораКомпоновщикаНастроекПоОбразцу(КомпоновщикНастроек, КомпоновщикНастроекР, ИмяОтбора)
Коллекция = КомпоновщикНастроек.ПользовательскиеНастройки.Элементы; //Коллекция элементов пользовательчких настроек в текущем отчете
Отбор = КомпоновщикНастроек.Настройки.Отбор;
ПолеЭлементаОтбора = Отбор.ДоступныеПоляОтбора.Элементы.Найти(ИмяОтбора).Поле;
ИДЭлмОтбора = "";
Для Каждого Элемент Из Отбор.Элементы Цикл
Если Элемент.ЛевоеЗначение = ПолеЭлементаОтбора Тогда ИДЭлмОтбора = Элемент.ИдентификаторПользовательскойНастройки; Прервать; КонецЕсли;
КонецЦикла;
ЭлементОтбора = Коллекция.Найти(ИДЭлмОтбора);
УстановитьЗначениеОтбораКомпоновщикаНастроек(КомпоновщикНастроекР, ИмяОтбора, ЭлементОтбора.ПравоеЗначение, ЭлементОтбора.ВидСравнения, ЭлементОтбора.Использование);
КонецПроцедуры
Клиентская функция ПолучитьЗначениеПераметраКомпоновщикаНастроек и процедура УстановитьЗначениеПераметраКомпоновщикаНастроек вызываемые из РезультатОбработкаРасшифровки - устанавливают и получают значения параметров из компоновшика настроек СКД:
&НаКлиенте
Функция ПолучитьЗначениеПераметраКомпоновщикаНастроек(КомпоновщикНастроек, ИмяПараметра)
ИДНастройки = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти(ИмяПараметра).ИдентификаторПользовательскойНастройки;
Коллекция = КомпоновщикНастроек.ПользовательскиеНастройки.Элементы;
Возврат Коллекция.Найти(ИДНастройки).Значение;
КонецФункции
&НаКлиенте
Процедура УстановитьЗначениеПераметраКомпоновщикаНастроек(КомпоновщикНастроекР, ИмяПараметра, Значение)
ИДНастройкиПараметраР = КомпоновщикНастроекР.Настройки.ПараметрыДанных.Элементы.Найти(ИмяПараметра).ИдентификаторПользовательскойНастройки;
КоллекцияР = КомпоновщикНастроекР.ПользовательскиеНастройки.Элементы; //Пользовательские настройки
КоллекцияР.Найти(ИДНастройкиПараметраР).Значение = Значение;
КонецПроцедуры
Серверная процедура ОбработатьРасшифровкуНаСервере, вызываемая из РезультатОбработкаРасшифровки - собственно создает (компонует) отчет для дальнейшего отображения на экране
&НаСервере
Функция ОбработатьРасшифровкуНаСервере(Знач ОтчетХ, ИмяТипаОтчета ,Знач РезультатХ, Знач ДанныеРасшифровкиХ, Знач ИДФормы)
ОтчетОбъект = ДанныеФормыВЗначение(ОтчетХ, Тип(ИмяТипаОтчета)); //Для компоновки результата
РезультатХ.Очистить();
ОтчетОбъект.СкомпоноватьРезультат(РезультатХ, ДанныеРасшифровкиХ); //Собственно формирование отчета
АдресДанныеРасшифровки = ПоместитьВоВременноеХранилище(ДанныеРасшифровкиХ, ИДФормы); //Запоминаем расшифровку (с ИД формы)
Возврат Новый Структура("Результат,ДанныеРасшифровки", РезультатХ, АдресДанныеРасшифровки); //Возвращаем результат и Адрес расщифровки
КонецФункции
Коротко поясню что делается в основной процедуре РезультатОбработкаРасшифровки:
-
Получаем Ссылку (одного из нужных типов), по которой пользователь произвел клик (вызов серверной функции "ПолучитьРасшифровкуНаСервере")
-
Формируем и наполняем содержимым объект ОбработкаРасшифровки
-
Выводим на экран меню расшифровки и считываем выбор пользователя
-
В зависимости от выбора пользователя либо вызываем стандартное действие, либо производим нестандартную расшифровку (//infostart.ru/public/151562/)