Как обратиться к реквизиту параметра в выражении языка компоновки данных?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов на Системе Компоновки Данных (СКД) мы часто сталкиваемся с необходимостью использовать в вычислениях свойства переданных параметров. Например, в отчет передается параметр &ЧасовойПояс (ссылка на справочник), и нам нужно в выражении получить его реквизит Смещение.

Казалось бы, решение очевидно: написать &ЧасовойПояс.Смещение. Однако на практике это приводит к ошибке "Не установлено значение параметра" (даже если вы создаете простую таблицу на СКД). Давайте разберем, почему так происходит, и рассмотрим надежные способы решения этой задачи.

Почему возникает ошибка?

Когда мы пишем в выражении СКД конструкцию вида &Параметр.Реквизит, компоновщик не воспринимает это как обращение к свойству объекта базы данных. Система считает, что Параметр.Реквизит — это имя нового, отдельного параметра, который мы забыли передать.

Попытка использовать функцию ВЫРАЗИТЬ в полях выражений (например, ВЫРАЗИТЬ(&ЧасовойПояс, "Справочник.ЧасовыеПояса").Смещение) также не работает. Это связано с тем, что для параметров компоновщик не строит автоматических связей (неявных левых соединений) с таблицами базы данных, так как параметр считается внешним значением.

Рассмотрим три способа, как обойти это ограничение.

Способ 1. Использование "фиктивного" набора данных (Рекомендуемый для гибкости)

Самый изящный способ заставить СКД видеть реквизиты параметра — это превратить параметр в поле набора данных. Как только значение становится полем, система получает доступ к его метаданным и позволяет обращаться к реквизитам через точку.

Разберем реализацию по шагам:

  1. Создадим в схеме компоновки данных новый набор данных — Запрос.
  2. В тексте запроса выберем наш параметр и дадим ему псевдоним.
    
    ВЫБРАТЬ
        &ЧасовойПояс КАК ЧасовойПоясПоле
    
  3. Теперь в настройках СКД или на вкладке "Вычисляемые поля" мы можем обращаться к полю ЧасовойПоясПоле.
  4. Конструкция ЧасовойПоясПоле.Смещение будет работать корректно, так как СКД автоматически построит запрос к справочнику для получения значения реквизита.

Важно: Если у вас основной набор данных — это внешний объект (ТЗ), то добавление набора-запроса может потребовать настройки связей между наборами. Если же основной источник — запрос, можно просто добавить выборку параметра в него.

Способ 2. Предварительное вычисление (Архитектурно правильный)

Если значение реквизита нужно для всего отчета целиком (оно не меняется от строки к строке), наиболее производительным решением будет вычислить его до формирования отчета.

Рассмотрим алгоритм действий:

  1. В модуле объекта отчета или формы (в процедуре, где формируется отчет) получаем значение реквизита программно (упростить работу с объектной моделью поможет СКДБилдер).
  2. Создаем в СКД отдельный параметр, например &СмещениеЧасовогоПояса.
  3. Передаем в этот параметр уже готовое числовое значение.

Пример кода инициализации:


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

В выражениях СКД мы будем использовать просто &СмещениеЧасовогоПояса.

Способ 3. Функции общих модулей (Если разрешено)

Если в конфигурации разрешено использование вызовов функций общих модулей в СКД (флаг "Безопасный режим" отключен или настроен соответствующим образом), можно воспользоваться стандартными функциями БСП.

В поле выражения параметра можно написать:

ОбщегоНазначения.ЗначениеРеквизитаОбъекта(&ЧасовойПояс, "Смещение")

Нюанс производительности:

Резюме

Прямое обращение через точку к реквизитам параметров (&Параметр.Реквизит) в СКД невозможно. Для решения этой задачи используйте предварительное вычисление значения в коде или включайте параметр в выборку запроса набора данных.

← На главную