Как вывести иерархию номенклатуры в печатной форме 1С?

Программист 1С v8.3 (Управляемые формы)
← На главную

При создании внешних печатных форм часто возникает задача не просто вывести список товаров из документа, но и сгруппировать их по папкам (иерархии) справочника Номенклатура. Это делает форму более читаемой, особенно если в заказе или реализации десятки и сотни позиций. В этой статье мы разберем несколько способов реализации этой задачи: от классического использования запросов с итогами до применения современных возможностей системы компоновки данных (СКД).

Способ 1. Использование предложения ИТОГИ ПО в запросе

Первый и самый важный шаг — это подготовка правильного запроса. Многие начинающие разработчики пытаются получить родителей номенклатуры «через точку», создавая конструкции вида Номенклатура.Родитель.Родитель. Это неэффективно, так как количество уровней вложенности может меняться, а такие обращения замедляют работу системы из-за лишних соединений в SQL.

Рассмотрим, как правильно использовать ключевое слово ИЕРАРХИЯ. Проанализируем пример кода, который позволяет получить дерево групп автоматически:


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

Запрос.УстановитьПараметр("МассивОбъектов", МассивОбъектов);
РезультатЗапроса = Запрос.Выполнить();

Использование ИТОГИ ПО Номенклатура ИЕРАРХИЯ заставляет платформу самостоятельно вычислить все родительские группы для каждой позиции товара и рассчитать по ним промежуточные суммы. Это избавляет нас от необходимости вручную перебирать дерево справочника.

Способ 2. Программный обход и группировка строк в Табличном документе

После того как данные получены, их нужно вывести в ТабличныйДокумент. Чтобы пользователь мог сворачивать и разворачивать группы (видеть те самые «плюсики»), необходимо использовать методы НачатьГруппировкуСтрок и ЗакончитьГруппировкуСтрок. Разберем по шагам, как организовать этот процесс в цикле обхода результата запроса.

Для правильного вывода иерархии мы будем использовать специальный режим обхода — ОбходРезультатаЗапроса.ПоГруппировкамСИерархией. Проанализируем следующий алгоритм:


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

Пока ВыборкаИерархия.Следующий() Цикл
    // Если это группа (папка) или промежуточный итог иерархии
    Если ВыборкаИерархия.ТипЗаписи() = ТипЗаписиЗапроса.ИтогПоИерархии Тогда
        ОбластьГруппы = Макет.ПолучитьОбласть("СтрокаГруппы");
        ОбластьГруппы.Параметры.НаименованиеГруппы = ВыборкаИерархия.Номенклатура;
        ТабДок.Вывести(ОбластьГруппы, ВыборкаИерархия.Уровень());
        
        // Начинаем визуальную группировку
        ТабДок.НачатьГруппировкуСтрок(ВыборкаИерархия.Номенклатура, Ложь);
    Иначе
        // Это детальная запись (сам товар)
        ОбластьСтроки = Макет.ПолучитьОбласть("СтрокаТаблицы");
        ОбластьСтроки.Параметры.Заполнить(ВыборкаИерархия);
        ТабДок.Вывести(ОбластьСтроки, ВыборкаИерархия.Уровень());
    КонецЕсли;
    
    // В рекурсивном или иерархическом обходе важно правильно закрывать группы
    // В данном упрощенном примере мы полагаемся на автоматическое завершение при выводе следующей группы того же уровня
КонецЦикла;

Важные моменты при работе с группировками:

  1. Уровень вложенности: Метод Вывести() вторым параметром принимает уровень (число). Это позволяет 1С автоматически определять отступы и структуру дерева.
  2. Сворачивание: Параметр Ложь в методе НачатьГруппировкуСтрок означает, что по умолчанию группа будет развернута. Если установить Истина, отчет сформируется в свернутом виде.
  3. Только просмотр: Чтобы кнопки управления группировками работали, у табличного документа должно быть установлено свойство ТабДок.ТолькоПросмотр = Истина.

Способ 3. Переход на Систему компоновки данных (СКД)

Как отмечают опытные разработчики в обсуждении, самый прогрессивный метод для вывода иерархических структур — это использование СКД. Даже если вы делаете внешнюю печатную форму, вы можете программно вызвать схему компоновки.

Почему это удобно? Рассмотрим преимущества:

Выясним, как это выглядит в коде. Вместо ручного обхода выборки мы используем ПроцессорКомпоновкиДанных:


СхемаКомпоновки = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = СхемаКомпоновки.НастройкиПоУмолчанию;

// Передаем параметры (например, массив ссылок на документы)
ПараметрСсылки = Настройки.ПараметрыДанных.Элементы.Найти("МассивОбъектов");
ПараметрСсылки.Значение = МассивОбъектов;
ПараметрСсылки.Использование = Истина;

КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновки, Настройки, ДанныеРасшифровки);

ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);

ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабличныйДокумент);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);

Дополнительная оптимизация: Транзитивное замыкание

В сложных случаях, когда стандартная иерархия 1С работает медленно или требуется специфическая логика (например, иерархия не по справочнику, а по кастомным связям), применяется метод «транзитивного замыкания». Суть его в том, чтобы создать временную таблицу, в которой для каждого элемента будут перечислены все его предки. Это позволяет строить отчеты по иерархии обычными плоскими запросами с высокой скоростью.

Проанализируем ситуацию с дополнительными реквизитами. Если вы выводите иерархию, помните, что у папок (групп) значения дополнительных реквизитов часто не заполнены. Проверяйте свойство ЭтоГруппа, чтобы в строках-заголовках не выводились пустые значения или «мусорные» данные от левых соединений.

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

← На главную