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

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

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


31.09.2021   Поставщик1   Товар1
31.09.2021   Поставщик1   Товар2

Наша задача — сделать так, чтобы результат выглядел следующим образом:

31.09.2021 Поставщик1 Товар1/Товар2

Рассмотрим подробнее, как именно добиться такого результата и почему это нельзя сделать обычным запросом.

Почему задачу не решить в языке запросов 1С?

Выясним причину, по которой мы не можем просто написать запрос и получить готовый склеенный текст. В стандартном языке запросов 1С отсутствует встроенная агрегатная функция (аналог STRING_AGG из классического SQL), которая позволяла бы объединять строки текстового типа в одну колонку «на лету».

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

Решение проблемы средствами СКД

Посмотрим на пример решения задачи через настройки ресурсов в СКД. Для работы со строками в компоновке предусмотрена специальная функция СоединитьСтроки. Она предназначена для того, чтобы склеивать массивы или таблицы значений в одну сплошную строку.

Синтаксис функции выглядит так:

СоединитьСтроки(Значение, РазделительЭлементов, РазделительКолонок)

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

  1. Значение — это массив или таблица значений, элементы которых мы собираемся объединить.
  2. РазделительЭлементов — символ или набор символов, которые будут вставлены между элементами (в нашей задаче это строка "/").
  3. РазделительКолонок — используется, если первым параметром передана таблица значений.

Шаг 1. Получение массива значений

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

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

СоединитьСтроки(Массив(Товар), "/")

Данное выражение соберет все товары внутри текущей группировки (например, внутри конкретного поставщика и даты) в массив, а затем склеит их через слеш.

Шаг 2. Использование сложных группировок

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

В этом случае выражение в ресурсах примет следующий вид:


СоединитьСтроки(ВычислитьВыражениеСГруппировкойМассив("Товар", "Поставщик, Дата"), "/")

Рассмотрим, что здесь происходит:

  1. Функция ВычислитьВыражениеСГруппировкойМассив собирает массив значений поля Товар.
  2. Второй параметр "Поставщик, Дата" жестко указывает контекст группировки.
  3. Внешняя функция СоединитьСтроки превращает полученный массив в единый текст с разделителем.

Альтернативное решение программным путем

Если по какой-то причине вы не используете СКД, а выводите данные программно, проанализируем, как сделать то же самое с помощью встроенного языка 1С. В таких случаях мы используем объекты СписокЗначений или ТаблицаЗначений.

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


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

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

← На главную