Как вывести иерархию документов в динамическом списке с помощью СКД?

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

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

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

Почему не удается построить иерархию документов в динамическом списке через СКД

Выясним причину, по которой привычный механизм отчетов не работает в динамическом списке формы:

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

Вариант 1. Отображение данных через ДеревоЗначений формы

Рассмотрим наиболее популярный способ обхода ограничения: отказ от динамического списка в пользу реквизита управляемой формы с типом ДанныеФормыДерево (в интерфейсе связывается с таблицей формы, отображаемой как дерево).

Разберем реализацию по шагам:

  1. Создадим на форме реквизит ДеревоЗадач с типом ДеревоЗначений и добавим в него необходимые колонки (например, Ссылка, Номер, Дата, Наименование).
  2. Перетащим реквизит в элементы формы, настроив отображение таблицы.
  3. На сервере получим данные иерархическим запросом или с помощью СКД, выгрузим результат в дерево значений и передадим его в реквизит формы с помощью метода ЗначениеВРеквизитФормы().

Посмотрим на пример серверной процедуры заполнения дерева с использованием механизма итогов запроса для построения иерархии:


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

Важный нюанс: при использовании дерева значений теряется механизм динамического считывания данных порциями. Если в базе содержатся десятки тысяч документов, полная выгрузка всего массива задач может существенно замедлить открытие формы. Для больших объемов данных рекомендуется использовать постраничную или ленивую подгрузку дочерних строк при активизации строки или раскрытии узла дерева.

Вариант 2. Использование связанных списков (Master-Detail)

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

Разберем архитектуру решения:

  1. Разделим экран формы на две части. В левой части разместим основной динамический список СписокКорневыхЗадач. В его запросе или фиксированном отборе укажем условие: ГДЕ Задача.РодительскаяЗадача = ЗНАЧЕНИЕ(Документ.Задача.ПустаяСсылка) Этот список будет выводить только корневые задачи верхнего уровня.
  2. В правой части формы разместим второй динамический список СписокПодчиненныхЗадач с параметром запроса &ТекущийРодитель.
  3. В обработчике события СписокКорневыхЗадачПриАктивизацииСтроки будем динамически устанавливать значение параметра для подчиненного списка:

&НаКлиенте
Процедура СписокКорневыхЗадачПриАктивизацииСтроки(Элемент)
    
    ТекущиеДанные = Элемент.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    УстановитьПараметрПодчиненногоСписка(ТекущиеДанные.Ссылка);
    
КонецПроцедуры

&НаСервере
Процедура УстановитьПараметрПодчиненногоСписка(РодительскаяСсылка)
    
    СписокПодчиненныхЗадач.Параметры.УстановитьЗначениеПараметра("ТекущийРодитель", РодительскаяСсылка);
    
КонецПроцедуры

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

Вариант 3. Архитектурное изменение метаданных

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

Документы в платформе 1С не предназначены для постоянного хранения иерархических структур. В таких ситуациях применяются следующие проектные решения:

  1. Замена документа на иерархический справочник: сущность Задача переносится в справочник с видом иерархии Иерархия элементов. В таком случае динамический список из коробки поддерживает древовидное отображение через стандартный реквизит Родитель с сохранением динамической подгрузки.
  2. Вспомогательный справочник-структура: если бизнес-логика требует именно документов для проведения по регистрам, создается вспомогательный иерархический справочник (например, СтруктураЗадач или Проекты). Динамический список строится по справочнику в виде полноценного дерева, а документы Задача ссылаются на его элементы.

Таким образом, внедрить связь наборов данных СКД непосредственно в динамический список невозможно из-за архитектурных ограничений платформы. Оптимальным решением является выбор между отображением через ДеревоЗначений (при малом объеме данных) и реорганизацией интерфейса либо метаданных (при работе с высоконагруженными базами).

← На главную