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