Как объединить несколько строк в одну в отчете 1С

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

Разберем типичную практическую задачу: в результате запроса получается несколько строк по одному объекту (например, по клиенту и сумме взаиморасчетов), где различаются только строковые комментарии или детализирующие признаки (например, цвета, номера документов или примечания). Требуется вывести эти данные в отчете одной строкой, объединив все текстовые значения в одну ячейку через запятую.

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

Ограничения стандартного языка запросов 1С

В стандартном языке запросов 1С отсутствуют встроенные агрегатные функции для конкатенации строк (аналоги SQL-функций STRING_AGG или GROUP_CONCAT). Выполнить склеивание строк непосредственно в тексте запроса через конструкцию СГРУППИРОВАТЬ ПО невозможно, так как агрегатные функции языка запросов 1С (СУММА, МИНИМУМ, МАКСИМУМ, КОЛИЧЕСТВО, СРЕДНЕЕ) не поддерживают агрегацию строковых типов с объединением их содержимого.

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

Решение 1: Использование функции СоединитьСтроки в СКД

В Схеме компоновки данных предусмотрен штатный механизм агрегации текстовых данных — функция СоединитьСтроки. Разберем по шагам правильную настройку схемы.

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

Если оставить детальные записи в структуре настроек, отчет выведет каждую строку отдельно, а в итоговой строке группировки склеит все значения вместе. Удаление детальных записей позволяет свернуть вывод до нужного уровня.

Решение 2: Программная обработка выборки запроса без СКД

Если отчет строится без использования СКД в классическом табличном документе или данные готовятся для передачи во внешнюю систему, объединение строк выполняется на встроенном языке при обходе выборки результата запроса.

Рассмотрим пример кода с использованием функции СтрСоединить:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Взаиморасчеты.Клиент КАК Клиент,
    |   Взаиморасчеты.Сумма КАК Сумма,
    |   Взаиморасчеты.Комментарий КАК Комментарий
    |ИЗ
    |   РегистрНакопления.Взаиморасчеты КАК Взаиморасчеты
    |УПОРЯДОЧИТЬ ПО
    |   Клиент,
    |   Сумма";

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

ТекущийКлиент = Неопределено;
ТекущаяСумма = 0;
МассивКомментариев = Новый Массив;

Пока Выборка.Следующий() Цикл
    Если Выборка.Клиент <> ТекущийКлиент Или Выборка.Сумма <> ТекущаяСумма Тогда
        Если ТекущийКлиент <> Неопределено Тогда
            ИтоговыйКомментарий = СтрСоединить(МассивКомментариев, ", ");
            // Вывод строки в ТабличныйДокумент или обработка данных
        КонецЕсли;
        
        ТекущийКлиент = Выборка.Клиент;
        ТекущаяСумма = Выборка.Сумма;
        МассивКомментариев.Очистить();
    КонецЕсли;
    
    Если ЗначениеЗаполнено(Выборка.Комментарий) Тогда
        МассивКомментариев.Добавить(Выборка.Комментарий);
    КонецЕсли;
КонецЦикла;

Если ТекущийКлиент <> Неопределено Тогда
    ИтоговыйКомментарий = СтрСоединить(МассивКомментариев, ", ");
    // Вывод последней накопленной строки
КонецЕсли;

Решение 3: Свертка через Таблицу Значений

Посмотрим на альтернативный программный вариант, когда результат выгружается в объект ТаблицаЗначений:


ТаблицаИсходная = РезультатЗапроса.Выгрузить();

ТаблицаИтоговая = ТаблицаИсходная.Скопировать();
ТаблицаИтоговая.Свернуть("Клиент, Сумма");
ТаблицаИтоговая.Колонки.Добавить("Комментарий", Новый ОписаниеТипов("Строка"));

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

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

← На главную