Как сгруппировать данные по контрагенту и вывести список всех его документов в одну строку?

Программист 1С v8.3 (Обычные формы) 1C:Бухгалтерия Бухгалтерский учет Торговля и дистрибуция
← На главную

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

В этой статье мы подробно рассмотрим, как реализовать «сворачивание» данных с помощью механизмов запросов 1С, обхода выборок и системы компоновки данных.

Метод 1. Использование итогов в запросе и вложенных выборок

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

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


ВЫБРАТЬ
    Поступление.Контрагент КАК Контрагент,
    Поступление.ДоговорКонтрагента КАК Договор,
    Поступление.СуммаДокумента КАК СуммаДокумента,
    Поступление.НомерВходящегоДокумента КАК НомерДок,
    Поступление.ДатаВходящегоДокумента КАК ДатаДок
ИЗ
    Документ.ПоступлениеТоваровУслуг КАК Поступление
ГДЕ
    Поступление.Дата МЕЖДУ &НачалоПериода И &КонецПериода
ИТОГИ
    СУММА(СуммаДокумента)
ПО
    Контрагент,
    Договор

Обратите внимание на секцию ИТОГИ. Она позволяет нам получить иерархическую структуру данных. Теперь проанализируем, как правильно обработать этот результат в коде 1С, чтобы собрать номера документов в одну строку:


РезультатЗапроса = Запрос.Выполнить();
// Выбираем группировки по контрагентам
ВыборкаКонтрагент = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

Пока ВыборкаКонтрагент.Следующий() Цикл
    
    ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
    ОбластьСтрока.Параметры.Контрагент = ВыборкаКонтрагент.Контрагент;
    ОбластьСтрока.Параметры.Сумма = ВыборкаКонтрагент.СуммаДокумента;
    
    // Теперь получаем детальные записи по этому контрагенту
    ВыборкаДетали = ВыборкаКонтрагент.Выбрать();
    СписокДокументов = "";
    
    Пока ВыборкаДетали.Следующий() Цикл
        // Формируем строку: Номер + Дата
        ТекстДокумента = ВыборкаДетали.НомерДок + " от " + Формат(ВыборкаДетали.ДатаДок, "ДФ=dd.MM.yyyy");
        
        // Добавляем к общему списку через запятую
        СписокДокументов = СписокДокументов + ?(СписокДокументов = "", "", ", ") + ТекстДокумента;
    КонецЦикла;
    
    // Заполняем параметр в макете собранной строкой
    ОбластьСтрока.Параметры.ДокументыСписок = СписокДокументов;
    ТабДок.Вывести(ОбластьСтрока);
    
КонецЦикла;

Важный нюанс: при конкатенации строк (сложении текста) обязательно используйте проверку ?(СписокДокументов = "", "", ", "). Это позволит избежать лишней запятой в самом начале строки. Также следите за тем, чтобы поля номера или даты не были равны NULL, иначе результат сложения всей строки может стать пустым. В запросе для этого используйте функцию ЕСТЬNULL(Поле, "").

Метод 2. Агрегация строк через СКД (Система компоновки данных)

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

Выполним следующие шаги для настройки:

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

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

Метод 3. Использование функции МАССИВ в языке запросов (8.3.8+)

Для разработчиков, использующих современные версии платформы, доступна агрегатная функция МАССИВ() прямо в тексте запроса (в секции ИТОГИ). Это позволяет получить готовую коллекцию значений для каждой группировки.

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


// В тексте запроса
ИТОГИ МАССИВ(НомерВходящегоДокумента) ПО Контрагент

После выполнения такого запроса в поле НомерВходящегоДокумента на уровне группировки будет находиться не одно значение, а объект типа Массив. В коде обработки результата это выглядит очень элегантно:


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

Оформление результата в Табличном документе

Когда мы собираем много документов в одну строку, она может стать очень длинной. Чтобы отчет выглядел профессионально, рассмотрим несколько советов по оформлению макета:

Автовысота строк. Если список документов не помещается в одну строку ячейки, необходимо настроить перенос текста. В конфигураторе для соответствующей ячейки макета установите свойство "Размещение текста" в значение Переносить. После вывода области в коде программно включите автовысоту:


ТабличныйДокумент.Вывести(Область);
ТабличныйДокумент.АвтоВысотаСтроки = Истина;

Удаление лишних символов. Если вы собираете строку вручную старым способом (через Строка + ", "), в конце часто остается "хвост" из запятой и пробела. Его легко обрезать одной командой:

РезультатТекст = Лев(РезультатТекст, СтрДлина(РезультатТекст) - 2);

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

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

← На главную