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

Программист IT и автоматизация бизнеса
← На главную

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

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

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

Рассмотрим алгоритм настройки по шагам:

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

СоединитьСтроки(Массив(Строка(Номенклатура) + " - " + Строка(Количество) + " шт."), "; ")

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

Способ 2: Функция общего модуля и вычисляемое поле

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

Для реализации этого метода выполним следующие действия:

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


Функция ПолучитьПредставлениеТабличнойЧасти(СсылкаНаОбъект) Экспорт
    Результат = "";
    ТекстЗапроса = 
    "ВЫБРАТЬ
    |   ТЧ.Номенклатура.Наименование КАК Наименование,
    |   ТЧ.Количество КАК Количество
    |ИЗ
    |   Справочник.ИмяВашегоСправочника.ИмяТабличнойЧасти КАК ТЧ
    |ГДЕ
    |   ТЧ.Ссылка = &Ссылка";
    
    Запрос = Новый Запрос(ТекстЗапроса);
    Запрос.УстановитьПараметр("Ссылка", СсылкаНаОбъект);
    Выборка = Запрос.Выполнить().Выбрать();
    
    Пока Выборка.Следующий() Цикл
        СтрокаТЧ = Выборка.Наименование + " - " + Строка(Выборка.Количество) + " шт.; ";
        Результат = Результат + СтрокаТЧ;
    КонецЦикла;
    
    Возврат Результат;
КонецФункции

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

ИмяВашегоОбщегоМодуля.ПолучитьПредставлениеТабличнойЧасти(Ссылка)

Важный нюанс: использование функций общего модуля для каждой строки отчета может существенно замедлить формирование отчета, если в нем выводятся тысячи записей. Это связано с тем, что для каждой строки будет выполняться отдельный SQL-запрос к базе данных.

Способ 3: Использование функции ВычислитьВыражениеСГруппировкойМассив

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

В выражении вычисляемого поля или ресурса можно написать:


СоединитьСтроки(ВычислитьВыражениеСГруппировкойМассив("Представление(Номенклатура) + "" - "" + Количество", "Ссылка"), ", ")

Такой подход позволяет гибко управлять контекстом вычислений. Мы указываем, какое выражение нужно вычислить (первый параметр) и в разрезе какой группировки это сделать (второй параметр). Это мощный инструмент для работы с итогами и иерархией.

Способ 4: Подготовка данных через Набор данных - объект

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

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

  1. В схеме компоновки данных создаем Набор данных - объект и называем его ТаблицаДанных. Определяем в нем колонки Объект (тип Ссылка) и СтрокаТЧ (тип Строка).
  2. В программном коде перед вызовом компоновщика формируем таблицу значений.
  3. Обходим выборку объектов, для каждого объекта формируем строку из его табличной части и записываем в таблицу.
  4. Передаем таблицу в процедуру формирования отчета через структуру ВнешниеНаборыДанных.

Пример кода подготовки данных:


ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Ссылка");
ТЗ.Колонки.Добавить("СтрокаТЧ");

// Запрос для получения всех данных одним махом
Запрос = Новый Запрос("ВЫБРАТЬ Ссылка, Номенклатура.Наименование КАК Наим, Количество ИЗ Справочник.Товары.Состав");
Выгрузка = Запрос.Выполнить().Выгрузить();

// Группировка и сборка строк в коде 1С
// (здесь может быть эффективный алгоритм обхода выгрузки)
// ... заполнение ТЗ ...

ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ТаблицаДанных", ТЗ);

СхемаКомпоновкиДанных = Отчеты.МойОтчет.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = СхемаКомпоновкиДанных.НастройкиПоУмолчанию;

КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки);

ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных);

Почему не стоит использовать функцию ПРЕДСТАВЛЕНИЕ в запросе?

Выясним причину, по которой попытки сложить строки прямо в тексте запроса часто заканчиваются неудачей. Как правильно заметили участники форума, функция ПРЕДСТАВЛЕНИЕ() в языке запросов 1С возвращает значение специального типа, которое предназначено только для вывода в отчет. С этим значением нельзя производить операции конкатенации (сложения строк) вида ПРЕДСТАВЛЕНИЕ(Поле1) + " - " + ПРЕДСТАВЛЕНИЕ(Поле2). Система выдаст ошибку несовместимых типов.

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

Резюме и рекомендации

Подведем итоги нашего анализа:

  1. Для простых случаев на платформе 8.3.6+ всегда выбирайте СоединитьСтроки в ресурсах СКД. Это самый быстрый и поддерживаемый метод.
  2. Если нужно объединять данные по сложной бизнес-логике — используйте функцию в общем модуле, но помните о производительности.
  3. Для отчетов с огромным объемом данных лучше подготовить строку заранее и передать её через Набор данных - объект.
  4. Избегайте хранения таких строк в базе данных (в реквизитах справочника) без крайней необходимости, так как это ведет к избыточности данных и необходимости контролировать их актуальность при каждом изменении табличной части.

Мы рассмотрели все основные способы формирования "строки из таблицы". Выбор конкретного метода зависит от архитектуры вашего решения и требований к скорости работы отчета.

← На главную