При работе со старыми типовыми конфигурациями (такими как Управление производственным предприятием 1.3, Управление торговлей 10.3 или Комплексная автоматизация 1.1) разработчики часто сталкиваются с механизмом «Универсального отчета», построенного на базе технологического объекта ПостроительОтчета. Этот объект во многом уступает современной Системе компоновки данных (СКД), однако он все еще активно поддерживается и эксплуатируется во многих корпоративных информационных системах.
Типичная проблема, с которой сталкиваются программисты при кастомизации таких отчетов: непонимание того, в какой момент и каким образом ссылка на конкретный объект (например, Номенклатуру) передается в механизм расшифровки и как перехватить это значение программно для реализации собственной логики.
В этой статье мы подробно разберем внутреннюю кухню работы расшифровки Построителя отчетов, выясним назначение ключевых свойств и методов, а также научимся перехватывать и модифицировать эти данные на практических примерах.
Когда ПостроительОтчета выводит результат запроса в табличный документ, за автоматическое формирование расшифровки отвечает свойство объекта: ПостроительОтчета.ЗаполнениеРасшифровки.
Для этого свойства может быть установлено одно из значений системного перечисления ВидЗаполненияРасшифровкиПостроителяОтчета. В универсальных отчетах практически всегда используется значение Расшифровка. Разберем подробнее, что это значит:
"Номенклатура", "Склад", "ХарактеристикаНоменклатуры"), а значениями становятся конкретные ссылки из базы данных для текущей строки (например, СправочникСсылка.Номенклатура).Расшифровка области ячеек табличного документа.Таким образом, когда пользователь производит двойной клик по ячейке с количеством или номенклатурой, процедура-обработчик расшифровки на клиенте получает эту структуру «как есть».
Давайте посмотрим на стандартный шаблон обработки этого события в формах универсальных отчетов. На форме отчета всегда располагается элемент управления «Поле табличного документа» (обычно с именем ПолеТабличногоДокументаРезультат). У этого поля определено событие ОбработкаРасшифровки.
Разберем типичный код этого обработчика:
Процедура ПолеТабличногоДокументаРезультатОбработкаРасшифровки(Элемент, Расшифровка, СтандартнаяОбработка)
// Отключаем стандартный диалог расшифровки платформы
СтандартнаяОбработка = Ложь;
// Передаем управление в процедуру модуля отчета
ОбработкаРасшифровки(Расшифровка, ОтчетОбъект);
КонецПроцедуры
В процедуре модуля отчета (или общем модуле, если используется типовой механизм универсального отчета) управление передается дальше:
Процедура ОбработкаРасшифровки(Расшифровка, Объект) Экспорт
ДополнительныеПараметры = Неопределено;
УниверсальныйОтчет.ОбработкаРасшифровкиУниверсальногоОтчета(Расшифровка, Объект, ДополнительныеПараметры);
КонецПроцедуры
Если мы остановим выполнение программы отладчиком внутри этой процедуры, то увидим, что параметр Расшифровка содержит коллекцию значений — Структура. Мы можем легко прочитать любое значение по имени поля:
Если ТипЗнч(Расшифровка) = Тип("Структура") Тогда
// Проверим, есть ли в структуре расшифровки нужный нам аналитический разрез
Если Расшифровка.Свойство("Номенклатура") Тогда
ВыбраннаяНоменклатура = Расшифровка.Номенклатура;
// Здесь мы можем открыть форму элемента или выполнить дополнительный расчет
Предупреждение("Вы выбрали номенклатуру: " + Строка(ВыбраннаяНоменклатура));
КонецЕсли;
КонецЕсли;
Очень часто у разработчиков возникает резонный вопрос: "Я вижу структуру расшифровки, но где в коде происходит сопоставление этой структуры с отборами нового (детализирующего) отчета?"
Этот процесс скрыт внутри платформенного метода, который вызывается в недрах общего модуля УниверсальныйОтчет. Имя этого метода:
ПостроительОтчета.НастроитьРасшифровку(<НастраиваемыйПостроитель>, <Расшифровка>)
Рассмотрим детально алгоритм, который выполняет платформа 1С при вызове этого метода под капотом:
ПостроительОтчета нового отчета, который мы собираемся открыть для детализации.Расшифровка, полученная из ячейки исходного отчета."Номенклатура") производится поиск одноименного доступного поля в настройках отбора настраиваемого построителя отчетов.Равно (или В иерархии, если поле представляет собой иерархический справочник) и присваивает значению отбора ссылку из структуры расшифровки.Именно поэтому вы не найдете в программном коде явного добавления элементов в коллекцию ПостроительОтчета.Отбор. Вся рутинная работа по сопоставлению типов данных и путей к данным делегирована платформе 1С.
Несмотря на кажущуюся простоту, при работе с расшифровкой в Построителе отчетов следует помнить о нескольких важных нюансах:
1. Обработка значений NULL.
Если в исходном запросе Построителя отчетов используются левые соединения, в полях группировок могут оказаться значения типа Null. При попытке выполнить метод НастроитьРасшифровку() с такими значениями в структуре расшифровки платформа может отработать некорректно или выдать ошибку времени выполнения. Мы рекомендуем обрабатывать такие поля на уровне запроса с помощью функции ЕСТЬNULL(), заменяя их на пустые ссылки соответствующих типов.
2. Ручная модификация структуры перед вызовом стандартного механизма.
Поскольку Расшифровка — это обычная структура, мы можем программно вмешиваться в процесс открытия нового отчета. Например, мы можем принудительно добавить в нее дополнительные параметры фильтрации или переопределить существующие до того, как управление будет передано в общий модуль:
Процедура ОбработкаРасшифровки(Расшифровка, Объект) Экспорт
Если ТипЗнч(Расшифровка) = Тип("Структура") Тогда
// Принудительно устанавливаем отбор по конкретной организации,
// даже если пользователь кликнул по строке без этой группировки
Расшифровка.Вставить("Организация", Объект.Организация);
КонецЕсли;
ДополнительныеПараметры = Неопределено;
УниверсальныйОтчет.ОбработкаРасшифровкиУниверсальногоОтчета(Расшифровка, Объект, ДополнительныеПараметры);
КонецПроцедуры
3. Отличие от Системы компоновки данных (СКД).
Помните, что данный механизм специфичен исключительно для ПостроителяОтчета. В СКД расшифровка работает принципиально иначе: вместо передачи структур данных напрямую в ячейки, СКД генерирует числовые идентификаторы, которые ссылаются на объект типа ДанныеРасшифровкиКомпоновкиДанных, хранящийся во временном хранилище. Не пытайтесь применять методы Построителя при работе с отчетами на СКД.