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