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