Как в СКД получить реквизит параметра без изменения запроса?

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

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

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

Выясняем причину: особенности работы языка выражений СКД

Для начала проанализируем, почему стандартные подходы вызывают синтаксические ошибки. Важно понимать, что в СКД одновременно работают два совершенно разных языка:

  1. Язык запросов 1С: используется в наборах данных (на вкладке «Наборы данных» при написании SQL-подобного запроса). Здесь для приведения типов применяется конструкция ВЫРАЗИТЬ(Поле КАК Тип). При выполнении этого запроса платформа автоматически генерирует SQL-код с неявным левым соединением (LEFT JOIN) к СУБД для получения реквизитов через точку.
  2. Язык выражений СКД: используется на вкладках «Вычисляемые поля», «Параметры» (в колонке «Выражение»), «Связи наборов данных» и непосредственно в пользовательских макетах. Синтаксис функции приведения типов здесь другой: Выразить(Выражение, "ИмяТипа"). Целевой тип данных обязательно передается в виде строки в кавычках.

Даже если мы напишем синтаксически корректное для СКД выражение Выразить(&Сценарий, "Справочник.Сценарии").ДатаНачала, система не сможет его рассчитать. Процессор компоновки данных при расчете выражений «на лету» не умеет неявно обращаться к базе данных для получения реквизитов параметров. Параметр для СКД — это готовое ссылочное значение, и платформа не будет генерировать дополнительный фоновый запрос к СУБД, чтобы прочитать свойства этой ссылки.

Тем не менее, решить эту задачу можно легко и элегантно. Рассмотрим доступные варианты решения.

Способ 1. Вызов функции общего модуля БСП в вычисляемом поле

Если ваша конфигурация построена на базе Библиотеки Стандартных Подсистем (БСП), то наиболее простым решением будет использование экспортной функции получения реквизитов объекта. Функция ЗначениеРеквизитаОбъекта из общего модуля ОбщегоНазначения работает быстро, оптимизировано и не требует изменения основного запроса отчета.

Разберем пошагово, как это настроить:

  1. Откройте схему компоновки данных и перейдите на вкладку Вычисляемые поля.
  2. Добавьте новую строку.
  3. В колонке Путь к данным укажите понятное имя поля, например, ДатаНачалаСценария.
  4. В колонке Выражение пропишите вызов функции БСП, передав туда ваш параметр и имя требуемого реквизита:

ОбщегоНазначения.ЗначениеРеквизитаОбъекта(&Сценарий, "ДатаНачала")

После этого созданное вычисляемое поле ДатаНачалаСценария станет доступно для выбора в настройках отчета. Вы можете без проблем перетащить его в ваш макет оформления или вывести в группировку заголовка.

Способ 2. Оптимизированный вариант через вспомогательный параметр

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

Проанализируем этот алгоритм:

  1. Перейдите на вкладку Параметры в схеме компоновки данных.
  2. Добавьте новый параметр с именем ДатаНачалаСценария и укажите для него тип значения Дата.
  3. В колонке Выражение для нового параметра напишите уже знакомую функцию получения реквизита:
    ОбщегоНазначения.ЗначениеРеквизитаОбъекта(&Сценарий, "ДатаНачала")
  4. Установите для этого параметра флаг Ограничение доступности. Это скроет его от конечного пользователя на форме настроек отчета.
  5. Теперь в макете оформления вашего отчета вместо вычисляемого поля вы можете напрямую вызывать параметр &ДатаНачалаСценария. Система вычислит его ровно один раз при инициализации компоновщика настроек.

Способ 3. Использование дополнительного набора данных (запроса)

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

Рассмотрим этот метод подробнее:

  1. Перейдите на вкладку Наборы данных в схеме компоновки.
  2. Добавьте новый набор данных типа Набор данных - запрос (назовите его, например, РеквизитыПараметров).
  3. В поле текста запроса напишите простейшую выборку из таблицы справочника:

ВЫБРАТЬ
    ВЫРАЗИТЬ(&Сценарий КАК Справочник.Сценарии).ДатаНачала КАК ДатаНачалаСценария

Так как этот код пишется в наборе данных (язык запросов 1С), конструкция ВЫРАЗИТЬ здесь отработает абсолютно корректно и без ошибок. Платформа сама получит значение реквизита при выполнении компоновки. Вы получите новое поле ДатаНачалаСценария, которое сможете использовать в макетах заголовков.

Способ 4. Программная инициализация в модуле объекта отчета

Если вы разрабатываете сложный внешний отчет и хотите полностью контролировать логику заполнения параметров, получение реквизита можно вынести в программный код модуля объекта отчета.

Для этого в модуле объекта определим предопределенный обработчик события ПриКомпоновкеРезультата:


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

При таком подходе вам достаточно создать в схеме СКД скрытый параметр &ДатаНачалаСценария и выводить его в нужные области макета. Значение будет гарантированно заполнено кодом непосредственно перед формированием отчета.

Мы проанализировали особенности синтаксиса СКД и разобрали четыре надежных способа вывода реквизитов параметров. Выбирайте вариант, наиболее подходящий под архитектуру вашей системы и требования к производительности отчета!

← На главную