В данной статье я решил показать пример использования расшифровки отчета СКД, для установки отборов колонки (колонок) отчета в выбранном диапазоне чисел. Для решение задачи пришлось собирать много информации с разных источников, поэтому решил всю информацию объединить в этой статье.
1 Программное добавление дополнительного пункта меню расшифровки
Для добавления дополнительного пункта меню нужно создать форму отчета и переопределить процедуры обработчики табличного документа Результат:
РезультатОбработкаРасшифровки() - нажатие на ячейке отчета правой кнопкой мыши
РезультатОбработкаДополнительнойРасшифровки() - нажатие на ячейке левой кнопкой мыши
Если база создана на основании БСП можно не создавать форму отчета, выполнить доработки через общим модуль ОтчетыКлиентПереопределяемый (не реализовано у меня):
ОтчетыКлиентПереопределяемый.ОбработкаРасшифровки()
ОтчетыКлиентПереопределяемый.ОбработкаДополнительнойРасшифровки().
Код процедур:
&НаКлиенте
Процедура РезультатОбработкаРасшифровки(Элемент, Расшифровка, СтандартнаяОбработка, ДополнительныеПараметры)
//вызываем процедуру которая для числа переопределяем обработку расшифровку
ОбработкаРасшифровкиНачало(Элемент, Расшифровка, СтандартнаяОбработка, ДополнительныеПараметры);
КонецПроцедуры
&НаКлиенте
Процедура РезультатОбработкаДополнительнойРасшифровки(Элемент, Расшифровка, СтандартнаяОбработка, ДополнительныеПараметры)
//вызываем процедуру которая для числа переопределяем обработку расшифровку
ОбработкаРасшифровкиНачало(Элемент, Расшифровка, СтандартнаяОбработка, ДополнительныеПараметры);
КонецПроцедуры
В процедуре ОбработкаРасшифровкиНачало получаем объект расшифровки (значение в ячейке табличного документа) с дополнительными проверкам на пустое значение и на тип Число. После проверки данных объекта расшифровки для Числа переопределяем расшифровку (для других типов нет смысла задавать диапазон, хотя можно и для типа "Дата" реализовать)
&НаКлиенте
Процедура ОбработкаРасшифровкиНачало(Элемент, Расшифровка, СтандартнаяОбработка, ДополнительныеПараметры)
//получаем структуру с данными объекта расшифровки
ОбъектРасшифровки = ПолучитьОбъектРасшифровки(Расшифровка, ДанныеРасшифровки);
Если ОбъектРасшифровки <> Неопределено Тогда
//переопределяем действия обработки расшифровки компоновки данных для числа
Если ОбъектРасшифровки.ЭтоЧисло ИЛИ ОбъектРасшифровки.ЭтоПустаяСтрока Тогда
//отменяем стандартную обработку расшифровки
СтандартнаяОбработка = Ложь;
//создаем обработчик расшифровки и инициализируем данными расшифровки отчета и источником доступных настроек для отчета
ОбработкаРасшифровки = Новый ОбработкаРасшифровкиКомпоновкиДанных(ДанныеРасшифровки, Новый ИсточникДоступныхНастроекКомпоновкиДанных(Отчет));
//задаем список доступных действий расшифровки
ДоступныеДействия = Новый Массив();
ДоступныеДействия.Добавить(ДействиеОбработкиРасшифровкиКомпоновкиДанных.Отфильтровать);
ДоступныеДействия.Добавить(ДействиеОбработкиРасшифровкиКомпоновкиДанных.Упорядочить);
ДоступныеДействия.Добавить(ДействиеОбработкиРасшифровкиКомпоновкиДанных.Сгруппировать);
ДоступныеДействия.Добавить(ДействиеОбработкиРасшифровкиКомпоновкиДанных.Расшифровать);
ДоступныеДействия.Добавить(ДействиеОбработкиРасшифровкиКомпоновкиДанных.Оформить);
//добавляем дополнительные действия расшифровки
ДополнительныеПунктыМеню = Новый СписокЗначений;
ДополнительныеПунктыМеню.Добавить(ПолучитьИмяДопПунктМеню_ОтфильтроватьДиапазон());
//Выдаем меню расшифровки, считываем реакцию пользователя
ДополнительныеПараметры = Новый Структура("ОбъектРасшифровки, Расшифровка", ОбъектРасшифровки, Расшифровка);
ОписаниеОповещения = Новый ОписаниеОповещения("ОбработкаРасшифровкиЗавершение", ЭтаФорма, ДополнительныеПараметры);
ОбработкаРасшифровки.ПоказатьВыборДействия(ОписаниеОповещения, Расшифровка, ДоступныеДействия, ДополнительныеПунктыМеню);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьОбъектРасшифровки(Расшифровка, ДанныеРасшифровки)
ОбъектРасшифровки = Неопределено;
ДанныеРашифровкиОбъект = ПолучитьИзВременногоХранилища(ДанныеРасшифровки);
ЭлементРасшифровки = ДанныеРашифровкиОбъект.Элементы.Получить(Расшифровка);
ПоляЭлементаРасшифровки = ЭлементРасшифровки.ПолучитьПоля();
КоличествоПолейРасшифровки = ПоляЭлементаРасшифровки.Количество();
Если КоличествоПолейРасшифровки Тогда
ОбъектРасшифровки = Новый Структура();
Индекс = 0;
Для Каждого ПолеЭлементаРасшифровки ИЗ ПоляЭлементаРасшифровки Цикл
//Значение
ИмяЗначения = "Значение" + ?(Индекс = 0, "", Индекс);
ОбъектРасшифровки.Вставить(ИмяЗначения, ПолеЭлементаРасшифровки.Значение);
//Поле
ИмяПоля = "Поле" + ?(Индекс = 0, "", Индекс);
ОбъектРасшифровки.Вставить(ИмяПоля, ПолеЭлементаРасшифровки.Поле);
//проверка на число
ИмяЗначения = "ЭтоЧисло" + ?(Индекс = 0, "", Индекс);
ОбъектРасшифровки.Вставить(ИмяЗначения, ТипЗнч(ПолеЭлементаРасшифровки.Значение) = Тип("Число"));
//проверка на число
ИмяЗначения = "ЭтоПустаяСтрока" + ?(Индекс = 0, "", Индекс);
ОбъектРасшифровки.Вставить(ИмяЗначения, ПустаяСтрока(ПолеЭлементаРасшифровки.Значение));
Индекс = Индекс + 1;
КонецЦикла;
КонецЕсли;
Возврат ОбъектРасшифровки;
КонецФункции // ПолучитьОбъектРасшифровки()
&НаКлиенте
Функция ПолучитьИмяДопПунктМеню_ОтфильтроватьДиапазон() Экспорт
Возврат НСтр("ru = 'Отфильтровать диапазон от ... до ...'; uk = 'Відфільтрувати діапазон від ... до ...'");
КонецФункции
2 Программная обработка расшифровки
После того как пользователь выбрал действие расшифровки необходимо определить какой из пунктов меню он выбрал:
- созданный программно пункт меню выбора диапазона - нужно вызвать форму выбора двух чисел;
- пункт Отфильтровать - нужно открыть новый отчет с параметрами фильтра (так реализован стандартный механизм);
- для прочих пунктов меню необходимо вызвать ОтработатьРасшифровку (функционал с сайта ИТС).
&НаКлиенте
Функция ОбработкаРасшифровкиЗавершение(ВыполненноеДействие, ПараметрВыполненногоДействия, ДополнительныеПараметры) Экспорт
ОбъектРасшифровки = ДополнительныеПараметры.ОбъектРасшифровки;
Расшифровка = ДополнительныеПараметры.Расшифровка;
ИмяПоля = ОбъектРасшифровки.Поле;
Если ВыполненноеДействие = ДействиеОбработкиРасшифровкиКомпоновкиДанных.Нет ИЛИ ВыполненноеДействие = Неопределено Тогда
//ничего не выполняем, пользователь отменил обработку расшифровки
ИначеЕсли ТипЗнч(ВыполненноеДействие) = Тип("Строка")
И ВыполненноеДействие = ПолучитьИмяДопПунктМеню_ОтфильтроватьДиапазон() Тогда
//пользователь выбрал наш дополнительный пункт меню
//создаем описание оповещения формы выбора двух чисел
ДополнительныеПараметрыОповещения = Новый Структура("ИмяПоля", ИмяПоля);
ОписаниеОповещения = Новый ОписаниеОповещения("ОтфильтроватьДиапазонНачалоВыбораЗавершение", ЭтотОбъект, ДополнительныеПараметрыОповещения);
ПараметрыФормы = Новый Структура;
//открываем форму выбора двух чисел
ОткрытьФорму("ВнешнийОтчет.РасшифровкаДиапазона.Форма.ФормаВыбораДвухЧисел",
ПараметрыФормы,
ЭтаФорма,
Новый УникальныйИдентификатор,,,
ОписаниеОповещения,
РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
ИначеЕсли ВыполненноеДействие = ДействиеОбработкиРасшифровкиКомпоновкиДанных.Отфильтровать Тогда
//стандартное действие "Отфильтровать" открывается в новой форме отчета, поэтому переопределяем его
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("СформироватьПриОткрытии", Истина);
ПараметрыФормы.Вставить("Расшифровка", Новый ОписаниеОбработкиРасшифровкиКомпоновкиДанных(ДанныеРасшифровки, Расшифровка, ПараметрВыполненногоДействия));
ОткрытьФорму("ВнешнийОтчет.РасшифровкаДиапазона.Форма.ФормаОтчета", ПараметрыФормы, , Истина);
Иначе
//для всех остальных используем процедуру взятую с сайта ИТС
ОтработатьРасшифровку(Новый ОписаниеОбработкиРасшифровкиКомпоновкиДанных(ДанныеРасшифровки, Расшифровка, ПараметрВыполненногоДействия), ИмяПоля);
КонецЕсли;
КонецФункции // ОбработкаРасшифровкиЗавершение()
//переопределяем обработку расшифровки
&НаСервере
Процедура ОтработатьРасшифровку(ОписаниеОбработкиРасшифровки, ИмяПоля)
ДанныеРасшифровкиОбъект = ПолучитьИзВременногоХранилища(ДанныеРасшифровки);
ОбработкаРасшифровки = Новый ОбработкаРасшифровкиКомпоновкиДанных(ДанныеРасшифровкиОбъект, Новый ИсточникДоступныхНастроекКомпоновкиДанных(Отчет));
РезультирующиеНастройки = ОбработкаРасшифровки.ПрименитьНастройки(ОписаниеОбработкиРасшифровки.Идентификатор, ОписаниеОбработкиРасшифровки.ПрименяемыеНастройки);
Если ТипЗнч(РезультирующиеНастройки) = Тип("НастройкиКомпоновкиДанных") Тогда
Отчет.КомпоновщикНастроек.ЗагрузитьНастройки(РезультирующиеНастройки);
ИначеЕсли ТипЗнч(РезультирующиеНастройки) = Тип("ПользовательскиеНастройкиКомпоновкиДанных") Тогда
Отчет.КомпоновщикНастроек.ЗагрузитьПользовательскиеНастройки(РезультирующиеНастройки);
КонецЕсли;
СкомпоноватьРезультат();
КонецПроцедуры
3 Программное добавление отборов НастройкиКомпоновкиДанных. Добавление отборов пользовательских насроек. Перерисовка пользовательских настроек
После получения чисел диапазона нужно программно добавить отбор в НастройкиКомпоновкиДанных и ПользовательскиеНастройки, а также перерисовать пользовательськие настройки.
&НаКлиенте
Процедура ОтфильтроватьДиапазонНачалоВыбораЗавершение(Результат, ДополнительныеПараметры) Экспорт
//получаем имя поля из дополнительных параметров
ИмяПоля = ДополнительныеПараметры.ИмяПоля;
Если Результат <> Неопределено Тогда
//получаем копию настроек компоновки данных.
НастройкиКомпоновкиДанных = ПолучитьТекущиеНастройки();
//удаляем предыдущие отборы по полю
//если конфигурация на основании БСП, то можно использовать функцию общего модуля ОбщегоНазначенияКлиентСервер
//ОбщегоНазначенияКлиентСервер.УдалитьЭлементыГруппыОтбора(НастройкиКомпоновкиДанных.Отбор, ИмяПоля);
УдалитьЭлементыГруппыОтбора(НастройкиКомпоновкиДанных.Отбор, ИмяПоля);
//добавляем новые отборы по полю
//если конфигурация на основании БСП, то можно использовать функцию общего модуля ОбщегоНазначенияКлиентСервер
//ДобавленныйЭлементЗначениеОт = ОбщегоНазначенияКлиентСервер.ДобавитьЭлементКомпоновки(НастройкиКомпоновкиДанных.Отбор, ИмяПоля, ВидСравненияКомпоновкиДанных.БольшеИлиРавно, Результат.ЗначениеОт, , Истина, РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ, Новый УникальныйИдентификатор());
//ДобавленныйЭлементЗначениеДо = ОбщегоНазначенияКлиентСервер.ДобавитьЭлементКомпоновки(НастройкиКомпоновкиДанных.Отбор, ИмяПоля, ВидСравненияКомпоновкиДанных.МеньшеИлиРавно, Результат.ЗначениеДо, , Истина, РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ, Новый УникальныйИдентификатор());
ДобавленныйЭлементЗначениеОт = ДобавитьЭлементКомпоновки(НастройкиКомпоновкиДанных.Отбор, ИмяПоля, ВидСравненияКомпоновкиДанных.БольшеИлиРавно, Результат.ЗначениеОт, , Истина, РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ, Новый УникальныйИдентификатор());
ДобавленныйЭлементЗначениеДо = ДобавитьЭлементКомпоновки(НастройкиКомпоновкиДанных.Отбор, ИмяПоля, ВидСравненияКомпоновкиДанных.МеньшеИлиРавно, Результат.ЗначениеДо, , Истина, РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ, Новый УникальныйИдентификатор());
Если Ложь Тогда //Если нужно открыть отчет в новом окне, тогда проставляем "Истина"
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("СформироватьПриОткрытии" , Истина);
ПараметрыФормы.Вставить("Вариант" , НастройкиКомпоновкиДанных);
ПараметрыФормы.Вставить("ПользовательскиеНастройки" , Отчет.КомпоновщикНастроек.ПользовательскиеНастройки);
ОткрытьФорму("ВнешнийОтчет.РасшифровкаДиапазона.Форма.ФормаОтчета", ПараметрыФормы, , Истина);
Иначе
//для отображенния добавленных элементов в пользовательских настоек создадим временный компоновщик и загрузим из него настройки
//так мы сможем заполнить пользовательские настройки
КомпоновщикВременный = Новый КомпоновщикНастроекКомпоновкиДанных;
КомпоновщикВременный.ЗагрузитьНастройки(НастройкиКомпоновкиДанных);
Отчет.КомпоновщикНастроек.ЗагрузитьНастройки(НастройкиКомпоновкиДанных);
Отчет.КомпоновщикНастроек.ЗагрузитьПользовательскиеНастройки(КомпоновщикВременный.ПользовательскиеНастройки);
ПользовательскиеНастройки = Отчет.КомпоновщикНастроек.ПользовательскиеНастройки;
//для наших новых отборов устанавливаем видимость "Быстрый доступ" и отображаем их на форме
//есть конфигурация создана на основании БСП, тогда можно использовать функцию общего модуля ОтчетыКлиентСервер
//ПользовательскаяНастройкаЗначениеОт = ОтчетыКлиентСервер.НайтиПользовательскуюНастройку(ПользовательскиеНастройки, ДобавленныйЭлементЗначениеОт.ИдентификаторПользовательскойНастройки);
//ПользовательскаяНастройкаЗначениеДо = ОтчетыКлиентСервер.НайтиПользовательскуюНастройку(ПользовательскиеНастройки, ДобавленныйЭлементЗначениеДо.ИдентификаторПользовательскойНастройки);
ПользовательскаяНастройкаЗначениеОт = НайтиПользовательскуюНастройку(ПользовательскиеНастройки, ДобавленныйЭлементЗначениеОт.ИдентификаторПользовательскойНастройки);
ПользовательскаяНастройкаЗначениеДо = НайтиПользовательскуюНастройку(ПользовательскиеНастройки, ДобавленныйЭлементЗначениеДо.ИдентификаторПользовательскойНастройки);
Если ПользовательскаяНастройкаЗначениеОт <> Неопределено Тогда
ПользовательскаяНастройкаЗначениеОт.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ;
КонецЕсли;
Если ПользовательскаяНастройкаЗначениеДо <> Неопределено Тогда
ПользовательскаяНастройкаЗначениеДо.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ;
КонецЕсли;
СкомпоноватьРезультат();
//вызываем создание елементов формы пользовательских настроек
ОбновитьЭлементыПользовательскихНастроек();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
// Функция возвращает копию настроек компоновки данных.
//
// Возвращаемое значение:
// - НастройкиКомпоновкиДанных - настройки компоновки данных
//
&НаСервере
Функция ПолучитьТекущиеНастройки()
Возврат Отчет.КомпоновщикНастроек.ПолучитьНастройки();
КонецФункции
// Процедура пересоздает элементы формы для редактирования пользовательских настроек отчета
//
&НаСервере
Процедура ОбновитьЭлементыПользовательскихНастроек()
СоздатьЭлементыФормыПользовательскихНастроек(,РежимОтображенияНастроекКомпоновкиДанных.БыстрыйДоступ);
КонецПроцедуры
Этот механизм позволяет накладывать отборы на несколько колонок отчета, все они будут работать с условием "И".
Отборы отключаются простым снятием галочек с отборов в пользовательских настройках, а так как пользовательские настройки отображаются сразу на форме, то пользователю не нужно открывать дополнительные окна.
Для меня основными проблемами при создании этого механизма были:
- передача НастроекКомпоновкиДанных в новую форму отчета (решилась через использование параметра формы "Вариант")
- добавление отбора в пользовательские настройки (решилась через временный компоновщик данных)
- перерисовка элементов пользовательских настроек на сервере (ну не знал я что нужно использовать СоздатьЭлементыФормыПользовательскихНастроек и с трудом нашел на форумах, хотя возможно что я просто плохо искал))
В статье использовались материалы из:
https://its.1c.ru/db/metod8dev/content/3728/hdoc
//infostart.ru/1c/articles/542677/
Прикрепляю рабочий пример отчета на управляемой форме, платформа 8.3.14. Отчет тянет статические данные, поэтому должен работать на большинстве конфигураций
В отчете задублированы функции общих модулей ОтчетыКлиентСервер, ОбщегоНазначенияКлиентСервер и т.д., а также добавлена форма выбора двух чисел. Основные процедуры и функции полностью выведены в статью.