Как добавить ссылку на регистр в пользовательских полях СКД

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

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

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

Почему нельзя обращаться к регистрам напрямую в пользовательских полях?

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

  1. Выполнение запроса (DataSet): Система обращается к базе данных и получает плоскую таблицу с результатом.
  2. Компоновка данных: На этом этапе вычисляются ресурсы, рассчитываются вычисляемые и пользовательские поля.
  3. Вывод: Формирование итогового документа (табличного документа).

Важный момент: пользовательские поля и вычисляемые поля обрабатываются уже на втором этапе, когда данные из базы уже получены. На этом шаге СКД «видит» только те поля, которые были выбраны в тексте запроса или добавлены как параметры. Система не может инициировать новый запрос к базе данных для каждой строки, чтобы «сходить» в регистр сведений. Именно поэтому синтаксис РегистрСведений.ИмяРегистра, работающий в языке запросов, не работает в языке выражений СКД.

Решение 1: Использование механизма характеристик (самый элегантный способ)

Если нам нужно добавить данные из регистра (например, паспортные данные или контактную информацию) к объекту, который уже есть в отчете (например, к Справочнику.ФизическиеЛица), лучше всего использовать встроенный механизм характеристик. Это позволит пользователю самому выбирать нужные поля из регистра так, будто они являются реквизитами самого справочника.

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

  1. Откроем вкладку «Наборы данных» и выберем наш запрос.
  2. В верхней части окна найдем кнопку «Характеристики».
  3. Добавим новую строку и заполним параметры для связи со справочником ФизическиеЛица:
    • Тип объекта: СправочникСсылка.ФизическиеЛица.
    • Источник видов характеристик: выберем таблицу (например, сам справочник или регистр).
    • Источник значений: РегистрСведений.ДокументыФизическихЛиц.
    • Связь объекта: поле ФизЛицо (из регистра).
    • Связь вида: здесь можно указать вид документа.
    • Значение: поле Номер или Серия.

После такой настройки в списке доступных полей отчета у поля Физическое лицо появятся «виртуальные» дочерние поля из регистра. СКД сама добавит необходимое ЛЕВОЕ СОЕДИНЕНИЕ в итоговый запрос к базе данных, обеспечив максимальную производительность.

Решение 2: Использование функций общих модулей

Если изменение схемы компоновки или использование характеристик по каким-то причинам невозможно, мы можем прибегнуть к вызову функции общего модуля прямо из выражения пользовательского поля. Это позволяет обойти ограничение на использование запросов в выражениях.

Проанализируем алгоритм действий:

1. Создадим в конфигураторе общий модуль (например, РаботаСОтчетами). В свойствах модуля обязательно должны быть установлены галочки «Сервер» и «Внешнее соединение».

2. Напишем экспортную функцию, которая будет получать данные из регистра:


Функция ПолучитьНомерДокументаФизЛица(ФизЛицоСсылка) Экспорт
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ДокументыФизическихЛицСрезПоследних.Номер КАК Номер
        |ИЗ
        |   РегистрСведений.ДокументыФизическихЛиц.СрезПоследних(, ФизЛицо = &ФизЛицо) КАК ДокументыФизическихЛицСрезПоследних";
    
    Запрос.УстановитьПараметр("ФизЛицо", ФизЛицоСсылка);
    
    Выборка = Запрос.Выполнить().Выбрать();
    Если Выборка.Следующий() Тогда
        Возврат Выборка.Номер;
    КонецЕсли;
    
    Возврат "Нет данных";
    
КонецФункции

3. Теперь в режиме 1С:Предприятие в настройках пользовательского поля мы можем написать следующее выражение:

РаботаСОтчетами.ПолучитьНомерДокументаФизЛица([Физическое лицо])

Внимание: помните, что этот метод может существенно замедлить формирование отчета, если в нем много строк. Функция будет вызываться для каждой строки результата отдельно (так называемая проблема N+1 запросов).

Решение 3: Изменение основного запроса (DataSet)

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

Рассмотрим пример запроса в СКД:


ВЫБРАТЬ
    Продажи.ФизическоеЛицо КАК ФизическоеЛицо,
    Продажи.СуммаОбороти КАК Сумма,
    ЕСТЬNULL(Документы.Номер, "---") КАК НомерПаспорта
ИЗ
    РегистрНакопления.Продажи.Обороты КАК Продажи
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ДокументыФизическихЛиц.СрезПоследних КАК Документы
        ПО Продажи.ФизическоеЛицо = Документы.ФизЛицо

После того как поле НомерПаспорта добавлено в основной запрос, оно становится доступным в пользовательских полях. Теперь выражение, которое пытался написать автор вопроса, будет выглядеть корректно и просто:

ВЫБОР КОГДА [НомерПаспорта] <> "---" ТОГДА [НомерПаспорта] ИНАЧЕ "Не заполнен" КОНЕЦ

Разбор типичных ошибок при использовании операторов ВЫРАЗИТЬ и ССЫЛКА

Посмотрим на ситуацию из Сообщения 2, где пользователь пытается применить ВЫРАЗИТЬ к регистру. Важно понимать разницу:

Ни один из этих операторов не может «превратить» ссылку на физическое лицо в запись регистра сведений. Они работают только в рамках иерархии типов и существующих связей в базе данных.

Резюме

Для реализации связи с регистром в пользовательских полях СКД рекомендуем придерживаться следующей логики:

  1. Если вы разработчик отчета — используйте ЛЕВОЕ СОЕДИНЕНИЕ в основном запросе. Это самый производительный метод.
  2. Если вы хотите дать пользователю гибкость выбора разных полей из связанных регистров — настройте Характеристики в схеме.
  3. Если вам нужно быстро решить задачу «здесь и сейчас» без изменения структуры сложного запроса — используйте функцию общего модуля, но помните о возможной потере скорости формирования отчета.
← На главную