Как объединить дублирующиеся строки в СКД и вывести значения свойств в одну ячейку

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

При разработке отчетов на Системе компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда к основной таблице (например, справочнику «Оборудование») необходимо присоединить дополнительные сведения из регистров (например, свойства или характеристики). Если у одного объекта несколько свойств, то при использовании обычного Левого соединения в запросе строки основного объекта начинают дублироваться — по одной строке на каждое свойство. Это портит визуальную структуру отчета и затрудняет анализ данных.

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

Причина возникновения проблемы

Разберем ситуацию: в запросе мы соединяем таблицу оборудования с таблицей его характеристик. Если у станка есть три характеристики (мощность, габариты, год выпуска), SQL-запрос вернет три записи для этого станка. СКД по умолчанию выведет их как три отдельные строки. Наша задача — заставить компоновщик сгруппировать эти строки, а значения характеристик «склеить» в одну строку.

Способ 1: Использование функций «СоединитьСтроки» и «Массив» в ресурсах

Это самый распространенный и эффективный метод. Он позволяет превратить колонку с данными в агрегированное поле. Рассмотрим по шагам, как это реализовать:

  1. Откройте схему компоновки данных и перейдите на закладку «Вычисляемые поля». Если поле со свойствами уже есть в запросе, этот шаг можно пропустить, но иногда полезно создать отдельное поле для трансформации.
  2. Перейдите на закладку «Ресурсы».
  3. Добавьте поле (например, ЗначениеСвойства) в список ресурсов.
  4. В колонке «Выражение» напишите следующую конструкцию:

СоединитьСтроки(Массив(Различные ЗначениеСвойства), "; ")

Проанализируем, что делает эта формула:

Важный нюанс: Чтобы строки перестали дублироваться, это поле не должно быть указано в настройках группировки отчета. Оно должно находиться только в «Выбранных полях». Если вы добавите «Свойство» в группировки, СКД будет обязана создать под каждое значение отдельную ветку или строку.

Способ 2: Настройка расчета ресурсов по группировкам

Иногда при использовании иерархии (как в случае с цехами и оборудованием) функция СоединитьСтроки начинает вести себя некорректно, собирая данные со всех уровней в одну кучу. Чтобы этого избежать, проанализируем настройки колонки «Рассчитывать по...» в ресурсах.

Укажите конкретную группировку (например, Ссылка или НаименованиеОборудования), для которой должен выполняться сбор строк. Это ограничит область действия функции текущим элементом и не позволит свойствам «всплывать» на уровень выше (например, в итоги по Цеху), если это не требуется по задаче.

Способ 3: Использование двух наборов данных

Если левое соединение в одном запросе слишком сильно усложняет структуру или приводит к рекурсивным ошибкам (особенно при работе с иерархией), рассмотрим вариант разделения данных на два набора.

  1. НаборДанных1 (Запрос): Выбираем только основные данные (Оборудование, Подразделение).
  2. НаборДанных2 (Запрос): Выбираем Свойства и Объекты из соответствующего регистра сведений.
  3. На закладке «Связи наборов данных» устанавливаем связь:
    • Источник связи: НаборДанных1
    • Приемник связи: НаборДанных2
    • Условие связи: Ссылка = Объект
    • Параметры: указываем связь по полям.

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

Способ 4: Сложная агрегация через функции общих модулей

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

Сначала создадим функцию в общем модуле (с флагом «Сервер», «Внешнее соединение»):


Функция СклеитьДанные(МассивЗначений) Экспорт
    Результат = "";
    Для Каждого ТекЗначение Из МассивЗначений Цикл
        Если ЗначениеЗаполнено(ТекЗначение) Тогда
            Результат = Результат + ?(Результат = "", "", ", ") + СокрЛП(ТекЗначение);
        КонецЕсли;
    КонецЦикла;
    Возврат Результат;
КонецФункции

Затем в схеме СКД в поле ресурса укажем:

ИмяВашегоОбщегоМодуля.СклеитьДанные(Массив(Различные МоеПоле))

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

Работа с иерархией (рекурсией)

Как упоминалось в обсуждении, при использовании иерархических связей (когда объект ссылается сам на себя) могут возникнуть сложности. Если ваш отчет построен на связи набора данных с самим собой для получения вложенности (Цех -> Участок -> Оборудование), убедитесь, что:

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

Подведем итог: Для объединения строк в одну ячейку наиболее правильным и современным методом является сочетание функции СоединитьСтроки(Массив(...)) в ресурсах и вынос свойств в отдельный набор данных с последующей связью на уровне СКД. Это сохраняет производительность запроса и обеспечивает чистоту данных без лишних дублей.

← На главную