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