Как исправить ошибку при получении макета и настроить группировку строк в табличном документе 1С?

Программист 1С v8.3 (Обычные формы) Управленческий учет IT и автоматизация бизнеса
← На главную

В процессе разработки отчетов и печатных форм в среде 1С:Предприятие разработчики часто сталкиваются с двумя взаимосвязанными задачами: корректным получением макета из контекста формы и выводом иерархических данных с возможностью сворачивания и разворачивания строк. Разберем по шагам обе эти проблемы, выясним причины их возникновения и рассмотрим правильные варианты реализации программного кода.

Причина ошибки «Значение не является значением объектного типа» при вызове ПолучитьОбласть

Проанализируем типовую ситуацию: в коде формы пишется конструкция получения макета и обращения к его именованным областям:


Макет = ПолучитьМакет("Макет");
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");

При выполнении этого кода платформа генерирует исключение: Значение не является значением объектного типа (ПолучитьОбласть). Это означает, что переменная Макет содержит не объект типа ТабличныйДокумент или ДвоичныеДанные, а значение Неопределено.

Выясним причину такого поведения в зависимости от контекста выполнения:

  1. Обычные формы и отсутствие основного реквизита: В обычных формах метод формы ПолучитьМакет() пытается найти макет, принадлежащий непосредственно самой форме. Если у формы не задан Основной реквизит (например, объект отчета или обработки с типом ОтчетОбъект или ОбработкаОбъект), форма «не знает» о макетах своего объекта метаданных и возвращает Неопределено.
  2. Работа с внешними обработками: Если обработка открыта во внешнем режиме, получение макета через метод формы без привязки к объекту завершается неудачей. Надежнее обращаться к объекту напрямую через реквизит формы: ЭтотОбъект.ПолучитьМакет("Макет") или метод ВнешОбработка.ПолучитьОбъект().
  3. Управляемые формы (клиент-сервер): На клиенте макет получить нельзя. В контексте серверной процедуры управляемой формы для доступа к макету объекта метаданных необходимо выполнить преобразование: РеквизитФормыВЗначение("Объект").ПолучитьМакет("Макет").
  4. Ошибки в имени или регистре: Если в конфигураторе имя макета написано с опечаткой, метод не вызывает синтаксическую ошибку на этапе сохранения, но в режиме предприятия вернет Неопределено. Проверить это можно простой проверкой: Если Макет = Неопределено Тогда....
  5. Общие макеты: Для макетов, расположенных в общей ветке метаданных конфигурации, следует использовать глобальный метод ПолучитьОбщийМакет("ИмяМакета").

Ошибки при группировке строк в табличном документе

После успешного получения макета возникает следующая задача: как вывести номенклатуру так, чтобы иерархические группы сворачивались и разворачивались с помощью значков «плюс» и «минус»? В исходных попытках разработчики часто совершают две критические ошибки:

  1. Помещение вызовов автогруппировки внутрь цикла: Методы ТабличныйДокумент.НачатьАвтогруппировкуСтрок() и ТабличныйДокумент.ЗакончитьАвтогруппировкуСтрок() нельзя открывать и закрывать на каждой итерации обхода. Они должны обрамлять весь цикл вывода данных целиком. То же касается и метода ПоказатьУровеньГруппировокСтрок() — он вызывается один раз в самом конце.
  2. Отсутствие иерархических итогов в запросе: Конструкция ИТОГИ ... ПО Номенклатура группирует записи только по конечным элементам. Чтобы платформа 1С построила полноценное дерево с родительскими папками, в запросе обязательно нужно указывать ключевое слово ИЕРАРХИЯ.

Правильная реализация вывода иерархических данных через Автогруппировку

Рассмотрим по шагам, как построить надежный вывод данных с автоматическим созданием уровней группировки. В табличном документе уровни строк определяются числовым значением, передаваемым вторым параметром метода Вывести().

Посмотрим на пример правильного формирования запроса и вывода строк:


ТабличныйДокумент = ЭлементыФормы.ПолеТабличногоДокумента1;
ТабличныйДокумент.Очистить();

Макет = ЭтотОбъект.ПолучитьМакет("Макет");
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьДанные = Макет.ПолучитьОбласть("Данные");
ОбластьИтоги = Макет.ПолучитьОбласть("Итоги");

ТабличныйДокумент.Вывести(ОбластьШапка);

Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|   Номенклатура,
|   КоличествоКнижн,
|   СуммаКнижн,
|   КоличествоФакт,
|   СуммаФакт
|ИЗ
|   Документ.Инвентаризация.Товары
|ГДЕ
|   Ссылка = &Документ
|ИТОГИ
|   СУММА(КоличествоКнижн),
|   СУММА(СуммаКнижн),
|   СУММА(КоличествоФакт),
|   СУММА(СуммаФакт)
|ПО
|   Номенклатура ИЕРАРХИЯ";

Запрос.УстановитьПараметр("Документ", Документ);

Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);

// Начинаем автогруппировку СТРОГО до цикла
ТабличныйДокумент.НачатьАвтогруппировкуСтрок();

Пока Выборка.Следующий() Цикл
    // Заполняем область данными текущей выборки (как группы, так и элемента)
    ОбластьДанные.Параметры.Заполнить(Выборка);
    
    // Передаем уровень выборки во второй параметр метода Вывести
    ТабличныйДокумент.Вывести(ОбластьДанные, Выборка.Уровень());
КонецЦикла;

// Заканчиваем автогруппировку СТРОГО после завершения цикла
ТабличныйДокумент.ЗакончитьАвтогруппировкуСтрок();

// Настраиваем отображение группировок и начальный уровень раскрытия
ТабличныйДокумент.ОтображатьГруппировки = Истина;
ТабличныйДокумент.ПоказатьУровеньГруппировокСтрок(1);

ТабличныйДокумент.Вывести(ОбластьИтоги);

Обратим внимание на метод Выборка.Уровень(). При обходе по группировкам с иерархией платформа автоматически возвращает глубину вложенности строки (начиная от корневых папок и заканчивая конкретным товаром). Табличный документ при включенной автогруппировке строит структуру именно на основе этого переданного уровня.

Ручное управление группировками строк

Если требуется вручную управлять тем, какие именно строки должны сворачиваться, или задавать им индивидуальные имена и начальное состояние, автогруппировку можно заменить явными методами табличного документа:

  1. ТабличныйДокумент.НачатьГруппуСтрок(ИмяГруппы, Свернута) — открывает новую группу строк перед выводом вложенных записей. Вторым параметром можно сразу передать Истина, чтобы группа по умолчанию была свернута.
  2. ТабличныйДокумент.ЗакончитьГруппуСтрок() — закрывает текущую активную группу после того, как все дочерние строки выведены.

Важно помнить, что в платформе 1С:Предприятие установлено ограничение: максимальный уровень вложенности строк в табличном документе составляет 8 уровней. При более глубокой структуре справочника избыточная вложенность не создаст новые уровни группировки.

Альтернативные способы формирования отчетов

Если отчет предполагает сложные многоуровневые группировки и нестандартное оформление, ручное написание циклов вывода строк не всегда оправдано. Разберем две эффективные альтернативы:

  1. Система компоновки данных (СКД): Является современным стандартом платформы. В СКД достаточно добавить запрос и в настройках структуры указать группировку по полю Номенклатура с типом Иерархия. Платформа сама сгенерирует макет, подсчитает итоги и организует корректные элементы управления сворачиванием строк без единой строчки программного кода.
  2. Построитель отчета: Для обычных форм эффективным решением остается ПостроительОтчета. Если передать ему текст запроса с секцией ИТОГИ ... ПО Номенклатура ИЕРАРХИЯ, вызов метода ПостроительОтчета.Вывести(ТабличныйДокумент) автоматически создаст все уровни группировок, шапку и подвал отчета.
← На главную