При разработке отчетов на Системе компоновки данных (СКД) часто возникает необходимость вывести в макет оформления или заголовок не просто значение параметра (например, ссылку на элемент справочника Сценарии), а конкретный реквизит этого параметра (например, его дату начала — ДатаНачала). Первое интуитивное решение разработчика — написать выражение вида &Сценарий.ДатаНачала или применить приведение типов Выразить(&Сценарий, "Справочник.Сценарии").ДатаНачала прямо в вычисляемых полях или макете. Однако при попытке сохранить такую настройку СКД выдает синтаксическую ошибку.
В этой статье мы подробно разберем причины возникновения данной ошибки, проанализируем разницу в синтаксисе языков внутри СКД и рассмотрим четыре практических способа решения этой задачи без изменения структуры вашего основного запроса.
Для начала проанализируем, почему стандартные подходы вызывают синтаксические ошибки. Важно понимать, что в СКД одновременно работают два совершенно разных языка:
ВЫРАЗИТЬ(Поле КАК Тип). При выполнении этого запроса платформа автоматически генерирует SQL-код с неявным левым соединением (LEFT JOIN) к СУБД для получения реквизитов через точку.Выразить(Выражение, "ИмяТипа"). Целевой тип данных обязательно передается в виде строки в кавычках.Даже если мы напишем синтаксически корректное для СКД выражение Выразить(&Сценарий, "Справочник.Сценарии").ДатаНачала, система не сможет его рассчитать. Процессор компоновки данных при расчете выражений «на лету» не умеет неявно обращаться к базе данных для получения реквизитов параметров. Параметр для СКД — это готовое ссылочное значение, и платформа не будет генерировать дополнительный фоновый запрос к СУБД, чтобы прочитать свойства этой ссылки.
Тем не менее, решить эту задачу можно легко и элегантно. Рассмотрим доступные варианты решения.
Если ваша конфигурация построена на базе Библиотеки Стандартных Подсистем (БСП), то наиболее простым решением будет использование экспортной функции получения реквизитов объекта. Функция ЗначениеРеквизитаОбъекта из общего модуля ОбщегоНазначения работает быстро, оптимизировано и не требует изменения основного запроса отчета.
Разберем пошагово, как это настроить:
ДатаНачалаСценария.
ОбщегоНазначения.ЗначениеРеквизитаОбъекта(&Сценарий, "ДатаНачала")
После этого созданное вычисляемое поле ДатаНачалаСценария станет доступно для выбора в настройках отчета. Вы можете без проблем перетащить его в ваш макет оформления или вывести в группировку заголовка.
Предыдущий способ имеет один архитектурный нюанс: если вычисляемое поле будет выводиться в цикле (например, для каждой детальной записи отчета), вызов функции общего модуля будет происходить многократно, нагружая сервер лишними точечными запросами к базе данных. Чтобы оптимизировать производительность и получить значение реквизита ровно один раз, мы можем задействовать вспомогательный параметр СКД.
Проанализируем этот алгоритм:
ДатаНачалаСценария и укажите для него тип значения Дата.ОбщегоНазначения.ЗначениеРеквизитаОбъекта(&Сценарий, "ДатаНачала")
&ДатаНачалаСценария. Система вычислит его ровно один раз при инициализации компоновщика настроек.Что делать, если конфигурация не использует БСП или вы хотите сделать отчет максимально независимым от общего кода конфигурации? Мы можем решить задачу исключительно визуальными средствами СКД, добавив вспомогательный набор данных.
Рассмотрим этот метод подробнее:
РеквизитыПараметров).
ВЫБРАТЬ
ВЫРАЗИТЬ(&Сценарий КАК Справочник.Сценарии).ДатаНачала КАК ДатаНачалаСценария
Так как этот код пишется в наборе данных (язык запросов 1С), конструкция ВЫРАЗИТЬ здесь отработает абсолютно корректно и без ошибок. Платформа сама получит значение реквизита при выполнении компоновки. Вы получите новое поле ДатаНачалаСценария, которое сможете использовать в макетах заголовков.
Если вы разрабатываете сложный внешний отчет и хотите полностью контролировать логику заполнения параметров, получение реквизита можно вынести в программный код модуля объекта отчета.
Для этого в модуле объекта определим предопределенный обработчик события ПриКомпоновкеРезультата:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Получаем доступ к коллекции параметров компоновщика настроек
ПараметрыДанных = КомпоновщикНастроек.Настройки.ПараметрыДанных;
ПараметрСценарий = ПараметрыДанных.Элементы.Найти("Сценарий");
Если ПараметрСценарий <> Неопределено И ЗначениеЗаполнено(ПараметрСценарий.Значение) Тогда
// Безопасно получаем реквизит напрямую через точку (платформа оптимизирует обращение)
ДатаНачала = ПараметрСценарий.Значение.ДатаНачала;
// Записываем полученное значение во вспомогательный скрытый параметр СКД
ПараметрыДанных.УстановитьЗначениеПараметра("ДатаНачалаСценария", ДатаНачала);
КонецЕсли;
КонецПроцедуры
При таком подходе вам достаточно создать в схеме СКД скрытый параметр &ДатаНачалаСценария и выводить его в нужные области макета. Значение будет гарантированно заполнено кодом непосредственно перед формированием отчета.
Мы проанализировали особенности синтаксиса СКД и разобрали четыре надежных способа вывода реквизитов параметров. Выбирайте вариант, наиболее подходящий под архитектуру вашей системы и требования к производительности отчета!