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