Как программно сформировать типовой отчет в Таблицу Значений, если результат получается пустым?

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

При разработке внешних обработок или интеграций часто возникает задача: получить данные из сложного типового отчета (например, "Себестоимость товаров", "Ведомость по товарам на складах" в 1С:ERP или УТ 11) не в виде печатной формы, а в виде ТаблицаЗначений для дальнейшей программной обработки. Однако, попытка просто получить схему компоновки данных и выполнить её "в лоб" часто приводит к тому, что результат оказывается пустым, хотя в пользовательском режиме отчет формируется корректно.

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

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

Давайте проанализируем типичный код, который пишет разработчик, пытаясь получить данные отчета. Обычно он выглядит следующим образом:


// Пример "наивного" кода, который часто возвращает пустую таблицу
СхемаКомпоновкиДанных = Отчеты.СебестоимостьТоваров.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновкиДанных));
// ... загрузка настроек и установка параметров ...

КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.ПолучитьНастройки(),,, Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));

ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки,,, Истина);

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

После выполнения этого кода переменная РезультатТЗ остается пустой или содержит только заголовки колонок. Причина кроется в архитектуре современных типовых конфигураций (ERP, КА, УТ).

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

  1. Функциональных опций (используются ли серии, характеристики, склады, проекты).
  2. Настроек пользователя (какие группировки выбраны).
  3. Версии конфигурации.

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

Решение задачи: использование логики модуля отчета

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

Шаг 1. Анализ модуля отчета

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

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

Шаг 2. Правильная инициализация настроек

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

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


// Получаем схему и настройки
СхемаКомпоновкиДанных = Отчеты.СебестоимостьТоваров.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновкиДанных));

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

// Важный момент: установка параметров
Настройки = КомпоновщикНастроек.Настройки;
ПараметрыДанных = Настройки.ПараметрыДанных;

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

Шаг 3. Модификация схемы (Самый важный этап)

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

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


// Создаем объект отчета
ОтчетОбъект = Отчеты.СебестоимостьТоваров.Создать();

// Передаем настройки в компоновщик объекта
ОтчетОбъект.КомпоновщикНастроек.ЗагрузитьНастройки(Настройки);

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

// После этого СхемаКомпоновкиДанных внутри объекта уже может быть изменена и готова к работе
СхемаГотовая = ОтчетОбъект.СхемаКомпоновкиДанных; 
// Либо настройки могут быть дополнены
НастройкиГотовые = ОтчетОбъект.КомпоновщикНастроек.ПолучитьНастройки();

Примечание: Этот метод "прогрева" через СкомпоноватьРезультат работает не всегда, так как иногда отчет сразу выводит данные и очищает память. Более надежный способ — вручную вызвать процедуры модификации текста запроса, которые вы найдете в модуле менеджера или объекта отчета.

Шаг 4. Вывод в Таблицу Значений

После того как у нас есть корректная схема (с полным текстом запроса) и настройки, выполняем стандартный вывод в коллекцию.


// Генерация макета для коллекции значений
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;

// Обратите внимание: используем Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений")
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаГотовая, НастройкиГотовые,,, Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));

ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки,,, Истина);

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

Особенности и нюансы

Рассмотрим еще несколько важных моментов, о которых стоит помнить:

  1. Внешние наборы данных. Если отчет использует внешний набор данных (передает готовую таблицу в СКД), то при инициализации ПроцессорКомпоновкиДанных необходимо передать эту структуру данных четвертым параметром. Если этого не сделать, результат будет пустым.
  2. Иерархия или плоская таблица. При выводе в ТаблицаЗначений через СКД структура таблицы будет зависеть от группировок.
    • Если в настройках есть группировки, результат может выводиться "лесенкой" (иерархически).
    • Чтобы получить плоскую таблицу (аналог Excel), нужно в настройках оставить только группировку "Детальные записи" или программно удалить все группировки перед компоновкой.
  3. ПроцессорВывода.Вывести. Это финальный метод, который заполняет переданную таблицу. Если на предыдущих этапах текст запроса в схеме не был заменен на рабочий, этот метод отработает без ошибок, но ничего не добавит в таблицу.

Итог

Чтобы программно сформировать типовой отчет в ТаблицаЗначений, недостаточно просто выполнить его схему компоновки. Необходимо убедиться, что отработал код, формирующий текст запроса (обычно находящийся в обработчике ПриКомпоновкеРезультата модуля отчета). Лучший способ — проанализировать модуль конкретного отчета и воспроизвести логику подготовки схемы перед вызовом компоновщика макета.

← На главную