Возможно ли объединить два отчета СКД в один, не переписывая сложные запросы?

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

При разработке отчетов в системе «1С:Предприятие 8» часто возникает ситуация, когда необходимо объединить данные из двух уже существующих и настроенных отчетов. Например, у нас есть детальный отчет по продажам контрагентам и сложный отчёт по оплатам с запутанной бизнес-логикой. Мы разберем, как объединить эти данные в одну форму, минимизируя трудозатраты на переписывание программного кода и запросов.

Вариант 1. Использование «Набора данных — объект» для программного вызова

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

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

  1. В основном отчете создаем Набор данных - объект и даем ему имя, например, ТаблицаОплат.
  2. В модуле объекта основного отчета, в процедуре ПриКомпоновкеРезультата, мы программно инициализируем второй отчет.
  3. Вызываем выполнение второго отчета и выгружаем его результат в таблицу значений.
  4. Передаем эту таблицу в процессор компоновки через структуру ВнешниеНаборыДанных.

Пример кода для реализации такого подхода в модуле объекта:


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

Вариант 2. Механизм вложенных отчетов в СКД

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

Рассмотрим пошагово, как это настроить:

  1. Откроем основную схему компоновки (Продажи).
  2. Перейдем на закладку Настройки.
  3. В дереве настроек нажмем правой кнопкой мыши и выберем Новый вложенный отчет.
  4. В появившемся окне укажем схему компоновки нашего сложного отчета по оплатам.
  5. Настроим связи: на закладке Настройки вложенного отчета укажем соответствие параметров. Например, Параметр.Контрагент вложенного отчета должен быть равен полю Контрагент основного отчета.

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

Вариант 3. Объединение наборов данных (Union)

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

В конструкторе СКД мы создаем один родительский узел типа «Объединение», а внутрь него помещаем два разных Набора данных - запрос. Один запрос выбирает продажи, второй — оплаты. Важно, чтобы поля в обоих запросах имели идентичные псевдонимы, например: Контрагент, СуммаОборот, Период. В этом случае СКД самостоятельно выполнит группировку данных, и если по одному контрагенту есть и продажи, и оплаты, они «схлопнутся» в одну строку отчета.

Вариант 4. Связи наборов данных (Join) в памяти СКД

Рассмотрим ситуацию, когда нам нужно связать два независимых запроса по ключевому полю. Мы можем добавить в СКД два Набора данных - запрос и настроить их связь на закладке Связи наборов данных.

Однако здесь стоит учитывать технические особенности платформы 1С:

Как избежать ошибок при расчете итогов?

Выясним причину возможного «раздвоения» сумм при объединении сложных данных. Если мы связали продажи и оплаты, и у одного контрагента пять документов оплаты на одну реализацию, сумма реализации может суммироваться пять раз в общих итогах. Чтобы этого избежать, разберем использование функции ВычислитьВыражениеСГруппировкойМассив в ресурсах СКД. При необходимости можно ознакомиться с примерами отчетов СКД со сложными выражениями компоновки и программной обработкой.

Вместо простого Сумма(СуммаПродажи) в поле ресурса следует прописать выражение, которое сначала сгруппирует данные по уникальному идентификатору (например, по регистратору или контрагенту), а затем просуммирует их:

Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(СуммаПродажи)", "Контрагент"))

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

Использование Менеджера временных таблиц для оптимизации

Проанализируем ситуацию, когда сложные запросы должны обмениваться промежуточными данными. Если мы решили все же перенести текст сложного запроса в новый отчет, мы можем использовать Менеджер временных таблиц. Это позволит нам в первом наборе данных подготовить выборку, поместить ее во временную таблицу, а во втором наборе — обратиться к ней по имени. Для этого в коде модуля необходимо инициализировать менеджер и передать его в параметры запросов СКД через КомпоновщикНастроек или напрямую в Запрос внутри набора данных.

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

← На главную