Разработка и Конфигурация · 11 мин
Как сгруппировать табличную часть документа в 1С
Как сгруппировать табличную часть документа в 1С: свёртка по колонкам, запрос с СГРУППИРОВАТЬ ПО, итоги по строкам. Примеры кода, ошибки и проверка результата.
Группировка табличной части документа — типовая задача при разработке и доработке конфигураций 1С. Она возникает, когда в документе накапливаются строки с одинаковой номенклатурой, но разными количествами и суммами, и нужно получить свёрнутый список: одна позиция — одна строка с суммарными значениями. Такая же операция требуется при формировании печатных форм, расчёте итогов по складам, контрагентам или статьям затрат.
В 1С есть несколько способов решить эту задачу: метод Свернуть() таблицы значений, запрос с конструкцией СГРУППИРОВАТЬ ПО, итоги через ИТОГИ ПО, а также промежуточная выгрузка табличной части в таблицу значений с последующей обработкой. Выбор зависит от того, где выполняется обработка — на клиенте, на сервере, в запросе к базе или над уже загруженными данными.
Ниже разобраны рабочие варианты с примерами кода, условиями применения и типичными ошибками. Примеры приведены на встроенном языке 1С и применимы как к управляемым, так и к обычным формам, с оговорками по контексту выполнения.
Что значит «сгруппировать» табличную часть и когда это нужно
Под группировкой понимают объединение нескольких строк табличной части по совпадающим значениям одной или нескольких колонок с суммированием (или иной агрегацией) числовых колонок. Например, в документе «Реализация товаров и услуг» одна и та же номенклатура встречается пять раз с разным количеством — после группировки останется одна строка с общим количеством и общей суммой.
Типовые сценарии, где это требуется: печать компактной формы документа без дублирующихся позиций, расчёт итогов по группам (по складу, по контрагенту, по виду номенклатуры), подготовка данных для выгрузки во внешние системы, проверка дублей при вводе. Важно понимать: группировка не изменяет сам документ, если вы специально не записываете результат обратно — чаще всего она выполняется над копией данных.
Способ 1: метод Свернуть() таблицы значений
Самый простой вариант — выгрузить табличную часть в таблицу значений и применить метод Свернуть(). Метод принимает два параметра: строку с именами колонок-измерений (по ним группируем) и строку с именами суммируемых колонок (ресурсов).
ТЗ = Объект.Товары.Выгрузить();
ТЗ.Свернуть("Номенклатура", "Количество,Сумма");
// Теперь в ТЗ по одной строке на каждую номенклатуру
Если группировать нужно по нескольким колонкам, перечислите их через запятую в первом параметре: ТЗ.Свернуть("Номенклатура,Склад", "Количество,Сумма"). Строки объединятся только при совпадении обоих значений. Колонки, не указанные ни в измерениях, ни в ресурсах, будут удалены из таблицы — учитывайте это, если дальше нужны, например, ставки НДС или единицы измерения.
Метод Свернуть() работает и на клиенте, и на сервере, поэтому подходит для обработчиков форм. Но помните: на тонком клиенте выгрузка большой табличной части создаёт нагрузку, и при объёмах в десятки тысяч строк лучше выполнять операцию в серверной процедуре.
- 1Выгрузите табличную часть: ТЗ = Объект.Товары.Выгрузить()
- 2Определите колонки группировки и суммируемые колонки
- 3Вызовите ТЗ.Свернуть("КолонкиГрупп", "КолонкиСумм")
- 4Используйте результат: обойдите ТЗ в цикле или загрузите обратно через Объект.Товары.Загрузить(ТЗ)
- 5Проверьте итоговые суммы до и после свёртки — они должны совпасть
Способ 2: запрос с СГРУППИРОВАТЬ ПО
Если данные нужны из базы (по уже проведённым документам) или требуется соединение с другими таблицами, используйте запрос. Конструкция СГРУППИРОВАТЬ ПО объединяет строки, а агрегатные функции СУММА, КОЛИЧЕСТВО, МАКСИМУМ рассчитывают итоги.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Номенклатура КАК Номенклатура,
| СУММА(Товары.Количество) КАК Количество,
| СУММА(Товары.Сумма) КАК Сумма
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК Товары
|ГДЕ
| Товары.Ссылка = &Ссылка
|СГРУППИРОВАТЬ ПО
| Товары.Номенклатура";
Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);
Результат = Запрос.Выполнить().Выгрузить();
Запрос выполняется только на сервере. Его преимущество перед Свернуть() — возможность отбирать данные условием ГДЕ, соединять табличную часть со справочниками (например, сразу получить артикул и группу номенклатуры) и группировать по вычисляемым выражениям. Недостаток — запрос читает данные из базы, поэтому несохранённые изменения в открытой форме документа он не увидит. Для текущего редактируемого документа используйте Свернуть() над данными объекта.
Способ 3: итоги через ИТОГИ ПО и обход выборки
Когда нужна не свёртка в одну строку, а иерархия «группа — строки внутри группы» (например, для печатной формы с подзаголовками по складам), подходит конструкция ИТОГИ ПО. Запрос формирует дерево: итоговые записи по группам и детальные записи внутри них.
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Склад КАК Склад,
| Товары.Номенклатура КАК Номенклатура,
| Товары.Количество КАК Количество
|ИЗ
| Документ.ПеремещениеТоваров.Товары КАК Товары
|ГДЕ
| Товары.Ссылка = &Ссылка
|ИТОГИ
| СУММА(Количество)
|ПО
| Склад";
ВыборкаСклады = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаСклады.Следующий() Цикл
// Итог по складу
Детали = ВыборкаСклады.Выбрать();
Пока Детали.Следующий() Цикл
// Строки внутри склада
КонецЦикла;
КонецЦикла;
Этот способ оптимален для отчётов и печатных форм: вы получаете и итоги по группе, и детализацию одним запросом. Для простой свёртки без деталей он избыточен — используйте СГРУППИРОВАТЬ ПО.
Сравнение способов и критерии выбора
Три подхода решают похожие задачи, но у каждого есть область, где он уместнее остальных. Ориентируйтесь на источник данных, место выполнения кода и необходимость соединений с другими таблицами.
| Способ | Где выполняется | Источник данных | Когда выбирать |
|---|---|---|---|
| Свернуть() | Клиент и сервер | Данные объекта в памяти | Обработка открытого документа, несохранённые изменения |
| СГРУППИРОВАТЬ ПО | Только сервер | Информационная база | Нужны отборы, соединения со справочниками, данные проведённых документов |
| ИТОГИ ПО | Только сервер | Информационная база | Печатные формы и отчёты с группами и детальными строками |
Сравнение вариантов
Быстрый и простой, работает с данными формы. Ограничение: только суммирование, нет отборов и соединений.
Гибкие отборы и соединения, агрегаты СУММА, МАКСИМУМ, СРЕДНЕЕ. Ограничение: только сервер, не видит несохранённые данные.
Даёт иерархию групп и деталей одним запросом. Ограничение: сложнее обход результата, избыточен для простой свёртки.
Как проверить результат группировки
Главный контроль — сравнение итогов до и после свёртки. Сумма по колонке «Количество» и «Сумма» исходной табличной части должна точно совпасть с суммой сгруппированной таблицы. Расхождение означает, что часть строк потеряна: например, не все суммируемые колонки перечислены в ресурсах, или в группировку попали строки с пустыми значениями ключевых колонок, которые объединились в одну строку с пустым ключом.
Дополнительно проверьте количество строк: оно должно быть не больше числа уникальных комбинаций значений колонок группировки. Если после свёртки строк столько же, сколько было, — вероятно, в измерения включена колонка с уникальными значениями (например, номер строки или комментарий), и группировка фактически не сработала.
Как проверить результат
Совпадает с итогом исходной табличной части
Сумма изменилась — потеряны строки или колонки
Равно числу уникальных комбинаций ключей
Строк столько же, сколько было — ключ выбран неверно
Пустых номенклатур нет или они обработаны отдельно
Появилась строка с пустой номенклатурой и большой суммой
Типичные ошибки и ограничения
Наиболее частая ошибка — свёртка без учёта колонок, которые должны сохраниться. Если в табличной части есть ставка НДС и вы свернули только по номенклатуре, колонка «СтавкаНДС» исчезнет, а строки с разными ставками объединятся в одну, что исказит расчёт налога. Решение — включить ставку в измерения: Свернуть("Номенклатура,СтавкаНДС", "Количество,Сумма,СуммаНДС").
Вторая ошибка — попытка загрузить сгруппированную таблицу обратно в документ без контроля. Объект.Товары.Загрузить(ТЗ) полностью заменяет табличную часть: если в ТЗ пропали нужные колонки, документ будет испорчен. Перед записью убедитесь, что структура колонок соответствует табличной части, и делайте резервную копию или тестируйте на копии базы.
Третья группа проблем — группировка по представлению вместо ссылки. Если сгруппировать по строковому наименованию номенклатуры, два разных элемента справочника с одинаковым названием склеятся в одну строку. Всегда группируйте по ссылке, а наименование получайте при выводе.
Частые вопросы
Можно ли сгруппировать табличную часть без выгрузки в таблицу значений?
Напрямую у табличной части объекта метода Свернуть() нет, поэтому выгрузка через Выгрузить() обязательна для этого способа. Альтернатива — запрос к базе, но он работает только с сохранёнными данными документа.
Как сгруппировать и посчитать количество строк в каждой группе?
В запросе добавьте агрегат КОЛИЧЕСТВО(*) с группировкой по нужному полю. При свёртке таблицы значений добавьте вспомогательную числовую колонку со значением 1 в каждой строке и включите её в ресурсы — после Свернуть() в ней будет число объединённых строк.
Почему после Свернуть() пропали некоторые колонки?
Метод удаляет все колонки, не указанные ни в параметре измерений, ни в параметре ресурсов. Перечислите нужные колонки явно: ключевые — в первом параметре, суммируемые — во втором. Нечисловые колонки, которые нельзя суммировать, сохранить можно только включив их в измерения.
Как сгруппировать данные по нескольким документам сразу?
Используйте запрос с условием ГДЕ Ссылка В (&СписокДокументов) и группировкой по нужным полям. Параметру передайте массив или список значений со ссылками на документы. Метод Свернуть() для этого не подходит — он работает только с одной выгруженной таблицей.
Работает ли Свернуть() на тонком клиенте?
Да, таблица значений и метод Свернуть() доступны на тонком клиенте. Однако при больших объёмах табличной части выгрузка и обход лучше выполнять в серверной процедуре, чтобы не перегружать клиентское соединение.
Как сгруппировать строки, но сохранить порядок сортировки?
Метод Свернуть() не гарантирует исходный порядок строк. После свёртки вызовите ТЗ.Сортировать("Номенклатура") или используйте запрос с предложением УПОРЯДОЧИТЬ ПО — в запросе порядок групп задаётся явно.
Что важно запомнить
Для данных открытой формы используйте Выгрузить() и Свернуть(), для данных базы и соединений — запрос с СГРУППИРОВАТЬ ПО, для печатных форм с группами — ИТОГИ ПО. Всегда включайте в измерения колонки, влияющие на расчёты (ставка НДС, склад), и сверяйте итоги до и после группировки.