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