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