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