Как сгруппировать и свернуть строки при выводе на печать в 1С, если в табличной части нет колонки «Количество»

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

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

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

Критическая ошибка: Изменение исходных данных документа

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

ТЧПоступление.Свернуть("ТипТехники", "НоменклатурныйНомер");

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

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

---

Способ 1. Использование временной Таблицы Значений (в оперативной памяти)

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

Проанализируем пошаговый алгоритм реализации этого метода:

  1. Создадим независимую копию табличной части с помощью метода Выгрузить(). Это обезопасит данные нашего документа.
  2. Добавим в полученную таблицу значений новую колонку Количество с типом данных «Число».
  3. Заполним созданную колонку единицами. Метод ЗаполнитьЗначения() сделает это одной быстрой операцией без использования медленных циклов.
  4. Вызовем метод Свернуть(), указав в первом параметре колонки для группировки, а во втором — колонку Количество для суммирования.

Посмотрим, как выглядит программный код этого решения:


// Шаг 1. Выгружаем данные табличной части в независимую таблицу значений
ТаблицаПечати = ТЧПоступление.Выгрузить();

// Шаг 2. Добавляем колонку для подсчета количества
ТаблицаПечати.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));

// Шаг 3. Заполняем каждую строку единицей (так как изначально колонки не было)
ТаблицаПечати.ЗаполнитьЗначения(1, "Количество");

// Шаг 4. Сворачиваем таблицу по ключевым полям, суммируя добавленное количество
ТаблицаПечати.Свернуть("ТипТехники, НоменклатурныйНомер", "Количество");

// Теперь безопасно выводим сгруппированные данные в макет печатной формы
НомерПоПорядку = 0;
Для Каждого Стр Из ТаблицаПечати Цикл
    СтрокаМакет = Макет.ПолучитьОбласть("Строка");
    НомерПоПорядку = НомерПоПорядку + 1;
    
    СтрокаМакет.Параметры.НомерСтроки = НомерПоПорядку;
    СтрокаМакет.Параметры.Наименование = Стр.ТипТехники;
    СтрокаМакет.Параметры.НоменклатурныйНомер = Стр.НоменклатурныйНомер;
    СтрокаМакет.Параметры.Затребовано = Стр.Количество;
    
    ТабДок.Вывести(СтрокаМакет);
КонецЦикла;

Этот способ интуитивно понятен и работает очень быстро, поскольку все вычисления происходят непосредственно в оперативной памяти компьютера.

---

Способ 2. Группировка данных через механизм Запросов

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

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

Разберем по шагам, как построить такой запрос:


// Инициализируем запрос
Запрос = Новый Запрос;

// Передаем табличную часть документа в качестве параметра
Запрос.УстановитьПараметр("ТабличнаяЧастьДокумента", ТЧПоступление);

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

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

НомерПоПорядку = 0;
Пока Выборка.Следующий() Цикл
    СтрокаМакет = Макет.ПолучитьОбласть("Строка");
    НомерПоПорядку = НомерПоПорядку + 1;
    
    ЗаполнитьЗначенияСвойств(СтрокаМакет.Параметры, Выборка);
    СтрокаМакет.Параметры.НомерСтроки = НомерПоПорядку;
    СтрокаМакет.Параметры.Затребовано = Выборка.Количество;
    
    ТабДок.Вывести(СтрокаМакет);
КонецЦикла;

Применение функции КОЛИЧЕСТВО(1) внутри конструкции СГРУППИРОВАТЬ ПО позволяет серверу базы данных самостоятельно рассчитать число сгруппированных строк, избавляя нас от ручного добавления колонок и заполнения их единицами.

---

Способ 3. Создание интерактивной группировки в Табличном Документе

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

Для реализации такой древовидной структуры в 1С предусмотрен встроенный механизм автогруппировки строк табличного документа.

Выясним, как программно реализовать интерактивные группы:


// Включаем автогруппировку строк перед началом вывода данных
ТабДок.НачатьАвтогруппировкуСтрок();

// Получаем уникальные (сгруппированные) типы техники
ЗапросГруппы = Новый Запрос;
ЗапросГруппы.УстановитьПараметр("ТЧ", ТЧПоступление);
ЗапросГруппы.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |	ТЧ.ТипТехники КАК ТипТехники
    |ИЗ
    |	&ТЧ КАК ТЧ";

ВыборкаГрупп = ЗапросГруппы.Выполнить().Выбрать();

Пока ВыборкаГрупп.Следующий() Цикл
    
    // Выводим строку-родитель (Уровень 1)
    ОбластьГруппа = Макет.ПолучитьОбласть("СтрокаГруппы");
    ОбластьГруппа.Параметры.Наименование = ВыборкаГрупп.ТипТехники;
    
    // Метод Вывести() принимает вторым параметром УРОВЕНЬ группировки
    ТабДок.Вывести(ОбластьГруппа, 1, "ГруппаТехники", Ложь);
    
    // Теперь выбираем детальные строки по этому типу техники
    Для Каждого СтрокаТЧ Из ТЧПоступление.НайтиСтроки(Новый Структура("ТипТехники", ВыборкаГрупп.ТипТехники)) Цикл
        
        // Выводим подчиненную детальную строку (Уровень 2)
        ОбластьДетали = Макет.ПолучитьОбласть("СтрокаДетали");
        ОбластьДетали.Параметры.НоменклатурныйНомер = СтрокаТЧ.НоменклатурныйНомер;
        
        // Указываем Уровень = 2, чтобы строка спряталась внутрь родительской группы
        ТабДок.Вывести(ОбластьДетали, 2, "Детали", Ложь);
        
    КонецЦикла;
    
КонецЦикла;

// Завершаем автогруппировку строк
ТабДок.ЗакончитьАвтогруппировкуСтрок();

// Настраиваем отображение кнопок группировки ("плюсиков") сверху, а не снизу
ТабДок.ПоложениеПроводникаГруппировокСтрок = ПоложениеПроводникаТабличногоДокумента.Верх;

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

Резюме

Выбор конкретного метода зависит от архитектуры вашей конфигурации и сложности задачи:

← На главную