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