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