Как сгруппировать данные по контрагентам и просуммировать итоги для вывода в макет 1С

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

При разработке отчетов или печатных форм в 1С часто возникает задача «схлопнуть» несколько строк в одну. Например, если у одного контрагента есть три заказа, мы не всегда хотим видеть три отдельные строки в макете. Зачастую требуется вывести одну общую строку: Вася — 3 заказа — общая сумма 1000 руб. Разберем подробно, как это реализовать программно, используя механизмы запросов и возможности табличного документа.

Анализ проблемы: почему данные не группируются?

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

Способ 1: Группировка на уровне запроса (СГРУППИРОВАТЬ ПО)

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

Посмотрим на пример правильного построения запроса, где мы хотим получить общие данные по контрагенту, количество его заказов и общую сумму:


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

Запрос.УстановитьПараметр("ДатаМаршрута", ВыбраннаяДата);
РезультатЗапроса = Запрос.Выполнить();

Важные моменты этого решения:

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

Способ 2: Использование иерархических итогов (ИТОГИ ПО)

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

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


Запрос.Текст = 
    "ВЫБРАТЬ
    |	ЗаказПокупателя.Контрагент КАК Контрагент,
    |	ЗаказПокупателя.Ссылка КАК Заказ,
    |	ЗаказПокупателя.СуммаДокумента КАК Сумма
    |ИЗ
    |	Документ.ЗаказПокупателя КАК ЗаказПокупателя
    |ИТОГИ
    |	СУММА(Сумма)
    |ПО
    |	Контрагент";

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

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

Особенности работы с макетом и шаблонами

При выводе данных в ТабличныйДокумент часто требуется скомпоновать несколько параметров в одной ячейке (например: «Вася (Тел: 123)»). Рассмотрим, как это сделать правильно:

  1. Тип заполнения «Шаблон»: В свойствах ячейки макета установите значение «Шаблон». В самой ячейке напишите текст вида: [Контрагент] (заявок: [КоличествоЗаказов]). При выводе области система автоматически подставит значения параметров внутрь квадратных скобок.
  2. Программное объединение: Если логика склейки строк сложная, лучше подготовить данные в коде перед заполнением параметров области.
    
    Область.Параметры.ИнфоОЗаказе = Строка(Выборка.Контрагент) + " сумм: " + Выборка.СуммаИтого;
    
  3. Группировки строк в макете: Чтобы пользователь мог сворачивать и разворачивать группы в печатной форме, используйте методы ТабДок.НачатьГруппуСтрок() и ТабДок.ЗакончитьГруппуСтрок(). Это добавит привычные значки «плюс» и «минус» слева от строк.

Решение проблемы с ТЧ «Товары»

Выясним причину, по которой у автора вопроса не получалось сгруппировать данные. В исходном запросе выбиралась табличная часть ЗаказПокупателя.Товары. Когда вы выбираете строки товаров, количество записей в результате запроса становится равным количеству всех товаров во всех заказах. Группировать такие данные по Контрагенту крайне сложно, если вам все еще нужны детали товаров.

Рекомендация: если вам нужно вывести только итоги по заказам (без перечисления номенклатуры), делайте запрос к шапке документа (Документ.ЗаказПокупателя). Если же нужно и то, и другое — используйте временные таблицы. Сначала соберите сгруппированные данные по контрагентам во временную таблицу, а затем соедините её с детальными данными товаров.

Подведем итог: для качественной группировки в макете всегда стремитесь максимально агрегировать данные на уровне запроса с помощью СГРУППИРОВАТЬ ПО. Это не только упростит код обхода, но и значительно ускорит формирование отчета.

← На главную