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