Как объединить строковые данные в группировках СКД

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

При разработке отчетов в Системе компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда необходимо вывести строковые значения из детальных записей в одну строку при группировке. Типичный пример: в отчете по контрагенту нужно перечислить все его номера телефонов или все категории товаров, которые он заказывал, через запятую. По умолчанию СКД пытается применять к строкам математические правила или просто выводит первое попавшееся значение, что приводит к некорректным результатам (например, вместо "111, 222" мы видим "1" или пустоту). Разберем детально, как решить эту задачу правильно.

Почему СКД не «складывает» строки автоматически?

Проанализируем ситуацию: если поле добавлено в список ресурсов, СКД по умолчанию предлагает агрегатную функцию Сумма. Для числовых данных это работает идеально, но для строк операция суммирования не определена однозначно. В некоторых случаях система пытается привести строку к числу, и если строка начинается с цифр, результатом может стать «1» или «0», что и наблюдал автор темы. Если же тип данных во внешнем наборе определен нечетко, СКД может просто растеряться при выборе алгоритма объединения. Наша задача — явно указать системе, как именно нужно обрабатывать эти строки при схлопывании записей в группировку.

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

Начиная с версии платформы 8.2.14, в СКД появилась мощная встроенная функция СоединитьСтроки(). Это наиболее «красивое» и производительное решение, которое работает непосредственно в движке компоновки. Рассмотрим, как её настроить.

Перейдем на закладку «Ресурсы» в схеме компоновки данных. Для нужного строкового поля в колонке «Выражение» необходимо прописать следующий синтаксис:

СоединитьСтроки(ИмяВашегоПоля, ", ", "ИмяВашегоПоля Возр")

Разберем параметры этой функции подробнее:

  1. Выражение: Это само поле, которое мы хотим склеить. Можно использовать ключевое слово Различные, чтобы избежать дублей (например, СоединитьСтроки(Различные Номенклатура)).
  2. Разделитель: Строка, которая будет вставлена между значениями. Чаще всего это запятая с пробелом ", " или перенос строки.
  3. Выражение упорядочивания: Позволяет задать порядок, в котором строки будут соединяться. Это важно, если важна хронология или алфавитный порядок.

Способ 2: Агрегация через Массив() и функции общих модулей

Если вы работаете на очень старой платформе (ниже 8.2.14) или вам нужна специфическая логика обработки (например, фильтрация пустых строк или особое форматирование), можно воспользоваться связкой системной функции Массив() и собственного кода. Выясним причину, почему это удобно: функция Массив() собирает все значения детальных записей в группе в одну коллекцию, которую потом можно передать в 1С-код.

Шаг 1. Создадим в общем модуле (например, РаботаСОтчетами) экспортную функцию. Модуль должен иметь флаги «Сервер» и «Вызов сервера».


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

Шаг 2. В СКД на закладке «Ресурсы» для нашего поля пропишем выражение:

РаботаСОтчетами.СклеитьСтрокиИзМассива(Массив(ИмяПоля), "; ")

Этот метод дает полный контроль над процессом. Мы можем добавлять условия, обрезать строки или даже менять цвет текста внутри функции (если возвращать форматированную строку).

Способ 3: Обработка данных во внешнем наборе (до СКД)

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


// Пример свертки таблицы перед передачей в СКД
ТЗДанные.Свернуть("Контрагент", "Сумма"); // Но строки так не свернуть!
// Придется обходить циклом:
ТЗ_Итог = ТЗДанные.СкопироватьКолонки();
Для Каждого СтрГруппировки Из ТЗ_Группы Цикл
    НоваяСтр = ТЗ_Итог.Добавить();
    ЗаполнитьЗначенияСвойств(НоваяСтр, СтрГруппировки);
    // Находим все записи и склеиваем строки вручную
    МассивСтрок = ТЗДанные.НайтиСтроки(Новый Структура("Контрагент", СтрГруппировки.Контрагент));
    Для Каждого СтрДетальная Из МассивСтрок Цикл
        НоваяСтр.Телефоны = НоваяСтр.Телефоны + ?(ПустаяСтрока(НоваяСтр.Телефоны), "", ", ") + СтрДетальная.Телефон;
    КонецЦикла;
КонецЦикла;

Однако, как отметил автор темы, этот подход убивает гибкость СКД. Если бухгалтер захочет изменить группировку, ваш программный код перестанет соответствовать новой структуре отчета. Поэтому использование ресурсов СКД (Способ 1 и 2) является более предпочтительным.

Важные нюансы и ограничения

Рассмотрим подробнее несколько критических моментов, которые могут испортить результат:

Проанализируем еще одну проблему: порядок строк. Если вы используете СоединитьСтроки(), обязательно указывайте третий параметр (выражение упорядочивания). Без него порядок склейки может меняться от запуска к запуску, что сделает отчет нестабильным и неудобным для сравнения.

Таким образом, мы разобрали основные инструменты для работы со строковыми агрегатами. В современных реалиях рекомендуется всегда использовать функцию СоединитьСтроки() как наиболее надежный и простой в поддержке инструмент.

← На главную