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

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

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

Почему функция СоединитьСтроки() не работает напрямую с массивом?

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

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

Способ 1. Предварительная обработка данных в коде (рекомендуемый)

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

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


// Создаем новую колонку для строкового представления
ТЗ_Данные.Колонки.Добавить("СписокДокументовСтрокой", Новый ОписаниеТипов("Строка"));

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

// Передаем подготовленную таблицу в СКД
ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ТаблицаСписка", ТЗ_Данные);

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

Способ 2. Использование функции общего модуля в вычисляемых полях

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

Выясним последовательность действий:

  1. Создадим в конфигурации общий модуль (например, РаботаСОтчетамиСервер).
  2. Установим у модуля свойства "Сервер" и "Внешнее соединение".
  3. Напишем экспортную функцию для преобразования коллекции в строку:

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

Теперь перейдем в СКД на закладку "Вычисляемые поля" и добавим новое поле. В колонке Выражение вызовем нашу функцию:

РаботаСОтчетамиСервер.ПолучитьПредставлениеМассива(ИмяКолонкиСМассивом)

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

Способ 3. Преобразование во вложенную таблицу значений

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

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

СоединитьСтроки(ИмяВложеннойТаблицы.Значение, ", ")

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

Нюансы оформления и вывода данных

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

Проанализируем настройки оформления:

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

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

← На главную