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