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

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

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

Проблема: несколько строк вместо одной

Рассмотрим ситуацию, которую описывает автор темы. У нас есть запрос к табличной части документа, который выбирает уникальные значения. Из-за того, что значений несколько, цикл обхода результата запроса выводит в макет новую строку на каждой итерации. Наша задача — собрать все эти значения в одну переменную перед тем, как вызывать метод Вывести().

Проанализируем исходный запрос:


ВЫБРАТЬ РАЗЛИЧНЫЕ
    КонтрольНоменклатуры.ИнтересноеЗначение КАК ИнтересноеЗначение
ИЗ
    Документ.КонтрольНоменклатуры.Контроль КАК КонтрольНоменклатуры
ГДЕ
    КонтрольНоменклатуры.Ссылка = &Ссылка
СГРУППИРОВАТЬ ПО
    КонтрольНоменклатуры.ИнтересноеЗначение

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

Решение 1: Классический обход в цикле с накоплением строки

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

Разберем алгоритм по шагам:

  1. Создаем пустую переменную ИтоговаяСтрока.
  2. Запускаем цикл обхода выборки или таблицы значений.
  3. В теле цикла добавляем к переменной значение поля и запятую.
  4. После завершения цикла удаляем последнюю лишнюю запятую.

Посмотрим на пример кода:


Результат = Запрос.Выполнить().Выгрузить();
ИтоговаяСтрока = "";

Для каждого СтрокаТЧ из Результат Цикл
    // Добавляем значение и разделитель
    ИтоговаяСтрока = ИтоговаяСтрока + СтрокаТЧ.ИнтересноеЗначение + ", ";
КонецЦикла;

// Удаляем последнюю запятую и пробел (2 символа справа)
Если ЗначениеЗаполнено(ИтоговаяСтрока) Тогда
    ИтоговаяСтрока = Лев(ИтоговаяСтрока, СтрДлина(ИтоговаяСтрока) - 2);
КонецЕсли;

// Теперь выводим в макет
рИнтер.Параметры.ИнтересноеЗначение = ИтоговаяСтрока;
ТабОбщий.Вывести(рИнтер);

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

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

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

Пример реализации:


ТаблицаРезультата = Запрос.Выполнить().Выгрузить();
// Получаем массив всех значений из колонки "ИнтересноеЗначение"
МассивЗначений = ТаблицаРезультата.ВыгрузитьКолонку("ИнтересноеЗначение");

// Соединяем элементы массива в одну строку с разделителем
ИтоговаяСтрока = СтрСоединить(МассивЗначений, ", ");

рИнтер.Параметры.ИнтересноеЗначение = ИтоговаяСтрока;
ТабОбщий.Вывести(рИнтер);

Решение 3: Реализация через Систему компоновки данных (СКД)

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

Выясним, как это настроить:

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

Оптимизация: Выгрузить() против Выбрать()

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

Этот метод создает объект ВыборкаИзРезультатаЗапроса, который позволяет читать данные последовательно (курсором), не загружая весь объем данных сразу. Это критически важно при обработке тысяч строк.


Выборка = Запрос.Выполнить().Выбрать();
ИтоговаяСтрока = "";

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

рИнтер.Параметры.ИнтересноеЗначение = ИтоговаяСтрока;
ТабОбщий.Вывести(рИнтер);

Обработка типов и пустых значений

При объединении строк важно учитывать два нюанса:

1. Типизация данных. Если в поле ИнтересноеЗначение хранится не строка, а ссылка, число или дата, попытка прямого сложения может привести к ошибке. Всегда используйте функцию Строка() для приведения значения к строковому представлению.
2. Пустые значения. Если одно из значений в выборке окажется пустым, в итоговой строке могут появиться двойные запятые (например, "Яблоко, , Груша"). Чтобы этого избежать, добавим проверку ЗначениеЗаполнено() перед добавлением элемента в строку.

Проанализируем финальный, наиболее устойчивый вариант кода:


МассивДляСборки = Новый Массив;
Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    Если ЗначениеЗаполнено(Выборка.ИнтересноеЗначение) Тогда
        МассивДляСборки.Добавить(Строка(Выборка.ИнтересноеЗначение));
    КонецЕсли;
КонецЦикла;

// Используем СтрСоединить как самый надежный метод
ИтоговаяСтрока = СтрСоединить(МассивДляСборки, ", ");

Таким образом, мы разобрали все основные способы решения задачи. Выбор метода зависит от версии вашей платформы и конкретного контекста задачи (отчет СКД или программный вывод в макет). Использование СтрСоединить и предварительная сборка данных в массив является наиболее современным и "чистым" подходом в разработке на 1С.

← На главную