Как отобразить реквизиты ссылочных полей во внешней таблице значений для Универсального отчета

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

При разработке отчетов на базе Универсального отчета (который в конфигурациях на обычных формах, таких как УПП 1.3, КА 1.1 или УТ 10.3, строится на механизме ПостроительОтчета), программисты часто сталкиваются с проблемой: если данные передаются через внешнюю ТаблицуЗначений, в настройках отчета (группировках, отборах, дополнительных полях) пропадают вложенные реквизиты ссылочных типов. Например, вы передали колонку Номенклатура, но пользователь не может выбрать в отчете Номенклатура.Артикул или Номенклатура.ВидНоменклатуры.

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

Почему Построитель отчета «не видит» реквизиты во внешней таблице?

Разберем причину такого поведения системы. Когда ПостроительОтчета работает с текстом запроса, он обращается к метаданным базы данных. Если в блоке {ВЫБРАТЬ...} указано Номенклатура.*, построитель заранее знает структуру справочника и может «вытянуть» любые его свойства.

Однако, когда мы передаем в отчет ОписаниеИсточникаДанных на основе ТаблицыЗначений, построитель работает в режиме «объекта». Он видит колонку в памяти, знает ее тип (например, СправочникСсылка.Номенклатура), но он не обучен автоматически выполнять дозапросы к базе данных для получения свойств этой ссылки, если они не описаны в структуре источника явно. Для него это просто «черный ящик» со ссылкой внутри.

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

Самый эффективный и правильный способ заставить УниверсальныйОтчет видеть реквизиты — это пропустить вашу ТаблицуЗначений через механизм запроса. Вместо прямой передачи таблицы в источник, мы поместим ее во временную таблицу внутри запроса. Рассмотрим, как это реализовать.

Проанализируем ситуацию: нам нужно передать таблицу в запрос и использовать специальные расширения языка запросов для построителя. Выполним следующие шаги:

  1. Подготовим ТаблицуЗначений с четко определенными типами колонок.
  2. Напишем текст запроса, который выбирает данные из этой таблицы.
  3. Используем конструкцию {ВЫБРАТЬ ИмяПоля.*} в тексте запроса.

Пример программного кода для реализации этого подхода:


// В процедуре установки начальных настроек или перед формированием
Процедура СформироватьОтчет(ТабличныйДокумент) Экспорт

    // 1. Получаем таблицу данных (как в вашем примере)
    ТаблицаДанных = СформироватьТаблицуДанных(); 
    
    // 2. Создаем построитель или используем встроенный в УниверсальныйОтчет
    // Важно: Построитель должен работать с ЗАПРОСОМ, а не с Таблицей напрямую
    ТекстЗапроса = "ВЫБРАТЬ
                   |    ТЗ.Контрагент КАК Контрагент,
                   |    ТЗ.Номенклатура КАК Номенклатура,
                   |    ТЗ.Склад КАК Склад,
                   |    ТЗ.Сумма КАК Сумма
                   |{ВЫБРАТЬ
                   |    Контрагент.*,
                   |    Номенклатура.*,
                   |    Склад.*,
                   |    Сумма}
                   |ИЗ
                   |    &ВнешняяТаблица КАК ТЗ";

    УниверсальныйОтчет.ПостроительОтчета.Текст = ТекстЗапроса;
    
    // 3. Передаем таблицу как параметр
    УниверсальныйОтчет.ПостроительОтчета.Параметры.Вставить("ВнешняяТаблица", ТаблицаДанных);
    
    // 4. Инициализируем настройки
    УниверсальныйОтчет.СформироватьОтчет(ТабличныйДокумент,,, ЭтотОбъект);

КонецПроцедуры

Обратите внимание на использование символа * в секции {ВЫБРАТЬ ...}. Именно эта инструкция говорит построителю отчета: "Для этого поля разреши пользователю выбирать любые доступные через точку реквизиты".

Способ 2. Программное расширение доступных полей

Если по каким-то причинам вы не хотите использовать запрос (хотя это не рекомендуется), можно попробовать программно добавить поля в свойство ДоступныеПоля объекта ПостроительОтчета. Однако этот метод гораздо сложнее, так как вам придется вручную описывать каждое вложенное поле, которое вы хотите видеть в отборах.

Рассмотрим структуру настройки через ОписаниеИсточникаДанных, которую вы приводили в коде. Вы устанавливали свойство Измерение для колонок:


ИсточникДанных = Новый ОписаниеИсточникаДанных(ТаблицаДанных);
ИсточникДанных.Колонки.Контрагент.Измерение = Истина;
ИсточникДанных.Колонки.Номенклатура.Измерение = Истина;

Чтобы реквизиты появились без запроса, вам пришлось бы добавить в ТаблицуЗначений колонки для каждого нужного реквизита (например, Номенклатура_Артикул) и заполнить их значениями. Но это неудобно для пользователя, так как поля будут "плоскими", а не древовидными.

Важные замечания по типам данных

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


Функция СформироватьТаблицуДанных()
    ВТ = Новый ТаблицаЗначений;
    
    // Обязательно создаем ОписаниеТипов для каждой ссылочной колонки
    МассивНоменклатура = Новый Массив;
    МассивНоменклатура.Добавить(Тип("СправочникСсылка.Номенклатура"));
    ОписаниеТиповНоменклатура = Новый ОписаниеТипов(МассивНоменклатура);
    
    вт.Колонки.Добавить("Номенклатура", ОписаниеТиповНоменклатура);
    вт.Колонки.Добавить("Склад", Новый ОписаниеТипов("СправочникСсылка.Склады"));
    вт.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));
    
    // Заполнение данными...
    
    Возврат ВТ;    
КонецФункции

Важный нюанс: Если вы используете УниверсальныйОтчет.СформироватьОтчет(...), убедитесь, что процедура УстановитьНачальныеНастройки() вызывается после того, как вы определили состав колонок и источник данных. В противном случае дерево доступных полей в форме настроек сформируется на основе пустых данных.

Почему "ИсточникДанных" может не работать для вложенных полей?

Проанализируем работу объекта ОписаниеИсточникаДанных. Этот объект предназначен для того, чтобы превратить обычную таблицу в "умный" источник для построителя. Он позволяет указать, что является измерением, а что — итогом (агрегатной функцией):

ИсточникДанных.Колонки.Отклонение.Итог = "СУММА(Отклонение)";

Но ОписаниеИсточникаДанных не обладает функционалом "проброса" ссылочных метаданных. Он лишь описывает текущий состав колонок. Поэтому, если ваша задача — дать пользователю возможность группировать по Номенклатура.Цвет или Контрагент.Регион, ваш путь лежит исключительно через использование Запроса к временной таблице внутри УниверсальногоОтчета.

Итоги и рекомендации

Разберем краткий алгоритм действий для исправления ситуации:

  1. Проверьте, что в ТаблицеЗначений у всех ссылочных колонок установлен строгий тип (не ЛюбаяСсылка, а конкретный справочник или документ).
  2. Вместо передачи ОписаниеИсточникаДанных(ТаблицаДанных) в построитель, назначьте построителю Текст запроса.
  3. В запросе опишите выборку из параметра (&ВнешняяТаблица).
  4. Обязательно добавьте блок {ВЫБРАТЬ...} и используйте звездочку (.*) для тех полей, чьи реквизиты нужны в отчете.
  5. Передайте саму таблицу в параметры построителя: ПостроительОтчета.Параметры.Вставить("ВнешняяТаблица", ТаблицаДанных);.

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

← На главную