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