Как программно получить таблицу значений из Универсального отчета с нужными колонками группировок?

Программист 1С v8.3 (Обычные формы) Управленческий учет
← На главную

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

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

Разбор механизма работы Универсального отчета

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

Рассмотрим стандартный подход, который часто приводит к ошибке (отсутствию колонок):


ОтчетОсн = Отчеты.ДебиторскаяЗадолженностьПоСрокамДолга.Создать();
ОтчетОсн.УниверсальныйОтчет.ДатаНач = ДатаНач;
ОтчетОсн.УниверсальныйОтчет.ДатаКон = ДатаКон;
// Попытка выгрузить результат
ТЗ = ОтчетОсн.УниверсальныйОтчет.ПостроительОтчета.Результат.Выгрузить();

В данном случае ТЗ, скорее всего, будет содержать только общие итоги. Это происходит потому, что ПостроительОтчета еще не "знает", в каких разрезах нужно сгруппировать данные. Колонки аналитики в Универсальном отчете — это не просто выбранные поля, это Измерения (группировки строк).

Решение проблемы через инициализацию настроек

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

Рассмотрим правильную последовательность действий:

  1. Создаем объект отчета.
  2. Вызываем метод УстановитьНачальныеНастройки(). Это "зашьет" в построитель базовый состав полей.
  3. Программно добавляем нужные нам группировки в коллекцию ГруппировкиСтрок.

Пример модифицированного кода:


ОтчетОсн = Отчеты.ДебиторскаяЗадолженностьПоСрокамДолга.Создать();

// 1. Инициализируем стандартные настройки
ОтчетОсн.УстановитьНачальныеНастройки();

// 2. Устанавливаем периоды
ОтчетОсн.УниверсальныйОтчет.ДатаНач = НужнаяДата;
ОтчетОсн.УниверсальныйОтчет.ДатаКон = НужнаяДата;

// 3. Работаем напрямую с ПостроителемОтчета для добавления измерений
Построитель = ОтчетОсн.УниверсальныйОтчет.ПостроительОтчета;

// Очистим текущие группировки, если нужно сформировать свою структуру
Построитель.ГруппировкиСтрок.Очистить();

// Добавляем Контрагента и Договор в группировки
Построитель.ГруппировкиСтрок.Добавить("Контрагент");
Построитель.ГруппировкиСтрок.Добавить("Договор");

// 4. Обязательно проверяем ВыбранныеПоля
// Если поля уже есть в группировках, они попадут в результат.
// Но показатели (суммы) должны быть в ВыбранныхПолях.

// 5. Формируем запрос и выгружаем
Построитель.Выполнить();
ТЗ = Построитель.Результат.Выгрузить();

Важные нюансы работы с измерениями и выбранными полями

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

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


ОтчетОсн.УниверсальныйОтчет.ДобавитьГруппировку("Контрагент");
ОтчетОсн.УниверсальныйОтчет.ДобавитьГруппировку("Договор");

Почему вызов СформироватьОтчет() может быть полезен?

Иногда даже после добавления группировок Результат.Выгрузить() возвращает пустые колонки. Это может быть связано с тем, что текст запроса построителя еще не сформирован (не собраны части текста из настроек). В Универсальном отчете за это отвечает метод СформироватьОтчет().

Рассмотрим прием, который гарантирует сборку отчета:


// Создаем фиктивный табличный документ
ТабДок = Новый ТабличныйДокумент;

// Этот метод заставляет объект пересобрать текст запроса со всеми фильтрами и группировками
ОтчетОсн.УниверсальныйОтчет.СформироватьОтчет(ТабДок);

// Теперь выгружаем данные из построителя, который уже точно отработал
ТЗ = ОтчетОсн.УниверсальныйОтчет.ПостроительОтчета.Результат.Выгрузить();

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

Работа с иерархией

Если вам необходимо получить не просто плоскую таблицу, а сохранить подчиненность (например, чтобы видеть, какие договоры относятся к конкретному контрагенту), при выгрузке следует использовать параметр обхода:


// Выгрузка с сохранением структуры группировок
ТЗ = Построитель.Результат.Выгрузить(ОбходРезультатаПостроителяОтчета.ПоГруппировкам);

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

Особенности отчета «Дебиторская задолженность по срокам долга»

Выясним специфику этого конкретного отчета. Он отличается тем, что его колонки (интервалы задолженности: "1-3 дня", "4-7 дней" и т.д.) формируются динамически. Если вы программно меняете Интервал, обязательно убедитесь, что параметры построителя обновлены.

Рассмотрим, как это выглядит в коде:


ОтчетОсн.Интервал = Интервал; // Установка ссылки на справочник интервалов
// После изменения интервала или дат обязательно вызываем:
ОтчетОсн.УстановитьНачальныеНастройки(); 
// Или вручную заполняем параметры построителя, если метод выше затирает ваши настройки.

Подведем итог: для успешного получения колонок "Контрагент" и "Договор" в ТЗ из Универсального отчета, мы должны убедиться, что эти поля добавлены в ГруппировкиСтрок построителя отчета, и что сам отчет проинициализирован вызовом УстановитьНачальныеНастройки() или программным переносом логики из модуля формы в наш алгоритм.

← На главную