При разработке сложных аналитических отчетов в Системе компоновки данных (СКД) программисты 1С часто сталкиваются с необходимостью вывода информации из нескольких независимых источников. Например, когда в одном отчете требуется показать данные по продажам, начислению заработной платы и складским остаткам. Эти наборы данных логически не связаны между собой на уровне детальных записей, но бизнес-пользователи хотят видеть сквозные расчетные показатели в итогах отчета (например: ИтогПоПродажам + ИтогПоЗарплате - ИтогПоОстаткам).
Попытка напрямую сложить ресурсы из разных несвязанных наборов данных в СКД приводит к возникновению стандартной критической ошибки: «Использование полей из не связанных наборов данных недопустимо!». Система блокирует выполнение компоновки, поскольку пытается сопоставить не связанные строки на уровне детальных записей.
В этой статье мы подробно разберем четыре проверенных архитектурных и технических метода, которые позволяют обойти это ограничение платформы и реализовать расчет сквозных итогов любой сложности.
Проанализируем наиболее изящный способ решения задачи внутри схемы СКД без написания программного кода. Вместо создания нескольких отдельных наборов данных типа «Запрос», мы объединим их под единым родителем — Набором данных — объединением.
Рассмотрим пошагово логику реализации этого метода:
ОбъединенныйНабор.Посмотрим на пример построения запроса для первого набора данных:
ВЫБРАТЬ
Продажи.Контрагент КАК Контрагент,
Продажи.СуммаОбороты КАК СуммаПродаж,
0 КАК СуммаЗатрат,
"Продажи" КАК ИдентификаторНабора
ИЗ
РегистрНакопления.Продажи.Обороты КАК Продажи
Теперь проанализируем структуру запроса для второго независимого набора данных:
ВЫБРАТЬ
Затраты.Подразделение КАК Подразделение,
0 КАК СуммаПродаж,
Затраты.СуммаОбороты КАК СуммаЗатрат,
"Затраты" КАК ИдентификаторНабора
ИЗ
РегистрНакопления.Затраты.Обороты КАК Затраты
Выясним, в чем заключается главная хитрость этого подхода. В результате объединения СКД сформирует единую плоскую таблицу в памяти. В строках, полученных из первого набора, колонка СуммаПродаж будет заполнена реальным значением, а СуммаЗатрат будет равна нулю. Во вторых строках — наоборот.
Благодаря тому, что все поля теперь формально принадлежат одному общему набору данных, мы можем на вкладке Ресурсы свободно прописать выражение любой сложности:
Сумма(СуммаПродаж) - Сумма(СуммаЗатрат)
Для корректного вывода данных в разные таблицы отчета нам останется лишь использовать отбор на уровне соответствующих группировок по полю ИдентификаторНабора.
Бывают ситуации, когда структура схемы компоновки уже сформирована, переделывать ее в объединение долго, а перекрестный итог нужен исключительно в самой нижней строке отчета («Общий итог»). В этом случае мы можем применить быстрый обходной трюк.
Разберем алгоритм настройки этого приема:
СуммарныйБаланс. Поле выражения (Expression) оставляем абсолютно пустым.Сумма(НаборПродажи.СуммаПродаж) - Сумма(НаборЗатраты.СуммаЗатрат).Выясним причину, почему это работает. СКД анализирует связи и выдает ошибку совместимости полей только тогда, когда пытается сопоставить детальные записи на уровне детальных строк или промежуточных иерархических группировок. Если мы жестко заставляем систему вычислять формулу только для финального итога отчета, СКД сначала независимо друг от друга агрегирует суммы по каждому набору данных до самого верхнего уровня, а затем просто выполняет математическую операцию над двумя готовыми числами.
Что делать, если сквозные итоги по несвязанным наборам нужны не только в общем итоге, но и внутри конкретных разрезов (группировок)? Нам поможет мощная встроенная функция языка выражений СКД — ВычислитьВыражениеСГруппировкойМассив.
Эта функция позволяет налету сворачивать данные независимых наборов во временные массивы непосредственно в момент рендеринга отчета и производить над ними любые операции.
Посмотрим на пример написания выражения для ресурса:
Сумма(ВычислитьВыражениеСГруппировкойМассив("Сумма(СуммаПродаж)", "Контрагент"))
-
Сумма(ВычислитьВыражениеСГруппировкойМассив("Сумма(СуммаЗатрат)", "Контрагент"))
Рассмотрим подробнее логику работы этой формулы. Система вычисляет итоги по каждому набору в разрезе группировки Контрагент, помещает результаты в два независимых массива в памяти, выполняет поэлементное вычитание и возвращает итоговую сумму для вывода в отчет. Ошибка связей при этом не возникает, так как сопоставление происходит через виртуальную свертку.
В наиболее тяжелых случаях, когда формулы зависят от множества внешних параметров, а макет компоновки имеет сложную нелинейную структуру, оптимальным решением является перенос расчетов на сторону встроенного языка 1С. Для этой задачи можно использовать готовый шаблон для выгрузки результата СКД в таблицу значений.
Разберем этот классический алгоритм по шагам:
Посмотрим на пример программного кода, реализующего выгрузку результата СКД в коллекцию:
// Получаем схему и настройки компоновки
СхемаКомпоновкиДанных = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
// Инициализируем макет компоновки
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки);
// Запускаем процессор компоновки
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
// Выгружаем результат СКД в Таблицу значений
ТаблицаРезультат = Новый ТаблицаЗначений;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(ТаблицаРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
// Теперь мы можем свободно рассчитать любые перекрестные итоги
Для Каждого СтрокаОтчета Из ТаблицаРезультат Цикл
СтрокаОтчета.ОбщийБаланс = СтрокаОтчета.СуммаПродаж - СтрокаОтчета.СуммаЗатрат;
КонецЦикла;
После проведения необходимых расчетов в коде, мы можем передать готовую и полностью заполненную таблицу значений в новую, упрощенную схему СКД для вывода пользователю или заполнить разработанный вручную макет табличного документа.
Используя предложенные методы, вы сможете успешно решать задачи любой сложности по агрегации разнородных данных в отчетах 1С, сохраняя высокую скорость работы системы и гибкость настроек для конечных пользователей. При необходимости можно изучить дополнительные приемы расчета сложных итогов в СКД.