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