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