Часто при работе с отчетами в Системе Компоновки Данных (СКД) возникает задача: сгруппировать данные по одному полю (например, по номенклатуре), а значения из другого поля (например, цвета или характеристики) собрать в одну строку через запятую. Давайте разберем, как это сделать правильно, и проанализируем частую ошибку, с которой сталкиваются разработчики.
Проблема обычно выглядит так: у нас есть исходные данные:
Номенклатура Цвет
------------------------
Товар1 Желтый
Товар1 Синий
Товар2 Красный
А получить мы хотим следующий результат:
Номенклатура Цвет
--------------------------------
Товар1 Желтый, Синий
Товар2 Красный
Интуитивно разработчик добавляет на вкладку "Ресурсы" выражение СоединитьСтроки(Цвет, ", "), но вместо ожидаемого результата получает исходную таблицу, а в общем итоге по отчету видит строку "Желтый, Синий, Красный". Выясним, почему так происходит и как это исправить.
Основная причина такого поведения в том, что по умолчанию ресурс рассчитывается для общего итога по всему отчету. СКД просто не знает, что мы хотим применять агрегатную функцию СоединитьСтроки() в контексте каждой отдельной группировки по номенклатуре. Чтобы это исправить, нужно явно указать системе, по какой группировке считать ресурс.
Этот метод является наиболее корректным и простым для решения нашей задачи. Он не требует написания сложного кода и полностью выполняется в конструкторе настроек СКД.
Разберем по шагам:
Номенклатура. Если вам не нужны детальные записи (каждый цвет на отдельной строке), можно удалить или отключить вложенную группировку "Детальные записи".СоединитьСтроки(Цвет, ", "). Можете задать для него псевдоним, например, "ВсеЦвета".Именно эта настройка указывает системе, что функцию СоединитьСтроки нужно выполнять не для всего набора данных, а для каждой группы номенклатуры в отдельности. В результате вы получите именно тот отчет, который хотели.
Для большей наглядности и контроля над данными можно использовать еще одну полезную агрегатную функцию СКД — Массив(). Эта функция сначала собирает все значения поля внутри группировки в массив, который затем можно передать в другую функцию, например, в нашу СоединитьСтроки().
Выражение в ресурсе будет выглядеть так:
СоединитьСтроки(Массив(Цвет), ", ")
Как и в первом решении, критически важно указать в колонке "Рассчитывать по..." нужную группировку ("Номенклатура"). Этот подход делает логику вычислений более явной: сначала собираем массив, потом соединяем его элементы в строку.
Дополнительная возможность: если в ваших данных могут быть дубликаты (например, "Товар1 - Желтый", "Товар1 - Желтый"), и их нужно выводить только один раз, используйте ключевое слово РАЗЛИЧНЫЕ внутри функции Массив(). Это позволит собрать только уникальные значения.
СоединитьСтроки(Массив(РАЗЛИЧНЫЕ Цвет), ", ")
В некоторых обсуждениях можно встретить более сложные конструкции с использованием функций ВычислитьВыражениеСГруппировкойМассив или ВычислитьВыражениеСГруппировкойТаблицаЗначений. Эти функции очень мощные и позволяют выполнять вычисления в контексте одной группировки, находясь в другой, но для нашей простой задачи они избыточны.
Тем не менее, полезно знать, как они работают. Например, можно создать вычисляемое поле с таким выражением:
СоединитьСтроки(ВычислитьВыражениеСГруппировкойМассив("Цвет", "Номенклатура"), ", ")
Здесь мы явно указываем, что нужно собрать массив значений поля "Цвет" в контексте группировки "Номенклатура". Этот метод может быть полезен, когда нужно вывести объединенную строку не в самой группировке, а, например, в общем итоге или в другой части отчета. Для нашей задачи первые два способа гораздо проще и эффективнее.
Еще один подход, который иногда применяют для сложных преобразований, — это подготовка данных еще до того, как они попадут в СКД. Это можно сделать с помощью пакетного запроса.
Этот способ оправдан, когда требуются очень сложные манипуляции с данными, которые невозможно или неэффективно выполнять средствами самого СКД. Для простой задачи конкатенации строк он является излишним усложнением.
Подведем итог: для объединения строк в СКД в разрезе группировки самым правильным и простым решением является использование функции СоединитьСтроки() в ресурсах с обязательным указанием нужной группировки в поле "Рассчитывать по...".