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

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

При разработке отчетов или печатных форм в 1С часто возникает задача объединить несколько строк табличной части документа или справочника в одну общую строку. Например, требуется получить текстовое представление вида: "Игрушка, для елки; Насос, для матраса; Кирпич, белый силикатный".

Рассмотрим, почему эту задачу нельзя решить простым запросом 1С, и проанализируем доступные обходные пути и варианты решения.

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

В языке запросов платформы 1С отсутствует аналог агрегатных функций сцепления строк (таких как GROUP_CONCAT в MySQL или STRING_AGG в PostgreSQL и MS SQL Server). Оператор конкатенации + работает исключительно для объединения значений разных колонок в рамках одной и той же текущей записи. Свернуть несколько строк одной колонки в единый текст с помощью конструкций СГРУППИРОВАТЬ ПО исключительно средствами стандартного запроса невозможно.

Способ 1. Использование Системы компоновки данных (СКД)

Если задача выполняется в рамках отчета, наиболее правильным и лаконичным решением будет использование возможностей Системы компоновки данных (СКД). Язык выражений СКД поддерживает функции работы с массивами и объединением строк.

Разберем порядок действий для настройки ресурса в СКД:

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

СоединитьСтроки(Массив(Товар + ", " + Описание), "; ")

Функция Массив() собирает все текстовые значения из группируемых записей, а функция СоединитьСтроки() объединяет их в одну строку с указанным разделителем.

Способ 2. Запрос с левым соединением (для известного количества строк)

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

Соединение лучше выполнять по ключу ссылки и полю НомерСтроки. Посмотрим на пример запроса, сцепляющего несколько строк:


ВЫБРАТЬ ПЕРВЫЕ 1
    ТЧ.Имя + ", " + ЕСТЬNULL(ТЧ1.Имя, "") + ", " + ЕСТЬNULL(ТЧ2.Имя, "") КАК СтрокаОписание
ИЗ
    Справочник.ФизическиеЛица.СоставСемьи КАК ТЧ
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ФизическиеЛица.СоставСемьи КАК ТЧ1
        ПО ТЧ.Ссылка = ТЧ1.Ссылка
            И ТЧ1.НомерСтроки = 2
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ФизическиеЛица.СоставСемьи КАК ТЧ2
        ПО ТЧ.Ссылка = ТЧ2.Ссылка
            И ТЧ2.НомерСтроки = 3
ГДЕ
    ТЧ.НомерСтроки = 1

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

Способ 3. Программная обработка на встроенном языке

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

Проанализируем пример кода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Товары.Товар.Наименование КАК Товар,
    |	Товары.Описание КАК Описание
    |ИЗ
    |	Документ.Продажа.Товары КАК Товары
    |ГДЕ
    |	Товары.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);
Выборка = Запрос.Выполнить().Выбрать();

МассивСтрок = Новый Массив;
Пока Выборка.Следующий() Цикл
    ТекстЭлемента = Выборка.Товар + ", " + Выборка.Описание;
    МассивСтрок.Добавить(ТекстЭлемента);
КонецЦикла;

ИтоговаяСтрока = СтрСоединить(МассивСтрок, "; ");

Способ 4. Хранение готовой строки в реквизите объекта

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

Заполнение реквизита выполняется в модуле объекта в обработчике события ПередЗаписью:


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

При таком подходе в любых запросах отчета или динамических списках достаточно выбрать реквизит Содержание без необходимости совершать дополнительные соединения или вычисления.

← На главную