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

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

При разработке отчетов и печатных форм часто возникает задача вывода данных из связи «один ко многим». Например, требуется отобразить документ-основание или элемент справочника в одной строке, а в отдельном столбце перечислить через запятую все связанные с ним операции, товары или статусы из подчиненной таблицы.

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

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

В языке запросов 1С отсутствует встроенная функция строковой агрегации, аналогичная GROUP_CONCAT или STRING_AGG в реляционных СУБД (таких как MS SQL Server или PostgreSQL). Агрегатная функция СУММА() работает исключительно с числовыми типами данных. Попытка склеить строки через запятую исключительно в тексте запроса без использования дополнительных механизмов платформы не даст результата.

Кроме того, метод ТаблицаЗначений.Свернуть() суммирует данные только по числовым колонкам и не производит конкатенацию строковых полей. Чтобы объединить записи подчиненной таблицы в одну строку, применяются три основных подхода: механизмы СКД, обработка результата запроса на BSL или специальная структура левых соединений в запросе.

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

Наиболее простой и рекомендуемый метод при работе с Системой компоновки данных (СКД) — использование встроенных функций агрегации строк на вкладке Ресурсы.

Проанализируем пошагово настройку ресурса в схемы компоновки данных:

  1. Добавим в набор данных запроса поле подчиненной таблицы (например, Операция) и ключевое поле связи (например, Ссылка или ИД).
  2. Перейдем на вкладку Ресурсы.
  3. Для поля Операция в колонке Выражение напишем формулу с объединением элементов массива через разделитель:

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

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

СоединитьСтроки(ТаблицаЗначений(Различные Операция), ", ")

В настройках группировки отчета на верхнем уровне выводим данные главной таблицы, а поле Операция рассчитается автоматически для каждой строки группировки.

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

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

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


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

Решение 3: Объединение в запросе при фиксированном количестве записей

В ситуациях, когда гарантированно известно, что число подчиненных записей на одну головную строку строго ограничено (например, не более 3-х операций), склеить строки можно прямо в запросе с использованием последовательных левых соединений и функции ВЫБОР.

Выясним, как выглядит конструкция такого запроса:


ВЫБРАТЬ
	ГлавнаяТаблица.Ссылка КАК Ссылка,
	ВЫБОР
		КОГДА Подчиненная1.Операция ЕСТЬ НЕ NULL И Подчиненная2.Операция ЕСТЬ НЕ NULL
			ТОГДА Подчиненная1.Операция + ", " + Подчиненная2.Операция
		КОГДА Подчиненная1.Операция ЕСТЬ НЕ NULL
			ТОГДА Подчиненная1.Операция
		ИНАЧЕ ""
	КОНЕЦ КАК ОперацииСклеенно
ИЗ
	Справочник.ГлавныйОбъект КАК ГлавнаяТаблица
	ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ПодчиненныйОбъект КАК Подчиненная1
		ПО ГлавнаяТаблица.Ссылка = Подчиненная1.Владелец И Подчиненная1.НомерПоПорядку = 1
	ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ПодчиненныйОбъект КАК Подчиненная2
		ПО ГлавнаяТаблица.Ссылка = Подчиненная2.Владелец И Подчиненная2.НомерПоПорядку = 2

Использование функций общих модулей в СКД

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

Для этого в ресурсах указывается следующий вызов:

ИмяОбщегоМодуляСервер.СклеитьМассив(Массив(Операция))

В самом общем модуле создается функция с ключевым словом Экспорт:


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

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

← На главную