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