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

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

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

Шаг 1. Понимание архитектуры иерархии в динамических списках

Проанализируем ситуацию: в справочниках иерархия строится легко и естественно, так как платформа предоставляет системный реквизит Родитель. В документах такого стандартного реквизита нет, поэтому динамический список по умолчанию не понимает, как строить дерево. Чтобы научить его этому, нам потребуется самостоятельно указать поле, которое будет выполнять роль родителя. В нашем случае логично использовать реквизит, указывающий на документ-основание. То есть для документа прихода (Покупки) родителем будет пустое значение, а для документа расхода (Продажи) родителем будет ссылка на документ Покупки.

Шаг 2. Формирование текста запроса

Для того чтобы вывести разные типы документов в один список и выстроить между ними связь, рассмотрим использование конструкции ОБЪЕДИНИТЬ ВСЕ в запросе динамического списка. Для этого отлично подойдет инструмент для быстрого анализа данных. Нам нужно создать вычисляемое поле, которое мы назовем, например, РодительскаяСсылка.

Посмотрим на пример базового запроса, который решает эту задачу (проверить его работу поможет консоль запросов):


ВЫБРАТЬ
    ДокументПокупка.Ссылка КАК Ссылка,
    ДокументПокупка.Дата КАК Дата,
    ДокументПокупка.Номер КАК Номер,
    ЗНАЧЕНИЕ(Документ.Покупка.ПустаяСсылка) КАК РодительскаяСсылка
ИЗ
    Документ.Покупка КАК ДокументПокупка

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    ДокументПродажа.Ссылка КАК Ссылка,
    ДокументПродажа.Дата КАК Дата,
    ДокументПродажа.Номер КАК Номер,
    ДокументПродажа.ДокументОснование КАК РодительскаяСсылка
ИЗ
    Документ.Продажа КАК ДокументПродажа

Важное замечание: проконтролируйте, чтобы типы данных в колонках Ссылка и РодительскаяСсылка были совместимы. Если у документа продажи реквизит ДокументОснование имеет составной тип, лучше выразить его явно (через функцию ВЫРАЗИТЬ), чтобы платформа точно понимала, что это ссылка на документ Покупки.

Шаг 3. Настройка свойств динамического списка

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

  1. Откройте свойства таблицы на форме (элемента формы, связанного с динамическим списком), в этом вам может помочь конструктор управляемых форм.
  2. Найдите свойство РежимОтображения и измените его со значения «Список» на «Дерево». Благодаря этому в начале строк, имеющих подчиненные записи, появится «плюсик».
  3. Откройте свойства самого реквизита формы (динамического списка). Найдите критически важное свойство ПолеРодителя. Установите в него наше созданное вычисляемое поле РодительскаяСсылка.
  4. Очистите свойство «Основная таблица» динамического списка. При использовании объединения нескольких таблиц документов указание основной таблицы приведет к ошибкам работы иерархии.

Шаг 4. Ограничения и проблемы производительности

Выясним причину, по которой опытные разработчики часто отказываются от построения полноценного дерева из документов в динамических списках. Главная проблема — это производительность. Динамический список очень плохо работает с иерархией, построенной на основе UNION-запросов и документов.

Посмотрим подробнее на механизм работы платформы: в обычном режиме «Список» данные считываются порциями (динамическое считывание), что обеспечивает мгновенную отрисовку формы даже при миллионах записей. Однако в режиме «Дерево» при раскрытии узлов или попытке сортировки платформа вынуждена анализировать огромные массивы данных для выстраивания связей «родитель-потомок». По мере роста базы форма будет открываться и работать всё медленнее.

Также проанализируем проблему сортировки. При отображении в виде дерева стандартная сортировка по дате может работать непривычно: сначала платформа отсортирует «родителей» (Покупки), а внутри них — «детей» (Продажи). Если покупка была совершена год назад, а закрывающая продажа сегодня, то продажа всё равно будет визуально "приклеена" к старой покупке, что может нарушить хронологическое восприятие списка пользователем.

Альтернативное решение 1: Использование механизма группировки

Если полноценное дерево работает медленно, рассмотрим более легкий вариант — использование встроенной настройки динамического списка «Группировка».

Зайдите в пользовательские настройки динамического списка, перейдите на вкладку «Группировка» и добавьте поле, по которому документы будут объединяться. Например, можно сгруппировать список по реквизиту ДокументОснование. Это не создаст классического дерева из ссылок на документы, но сформирует визуальные узлы-папки (строки группировки), внутри которых будут лежать нужные нам документы. Этот механизм работает значительно быстрее и стабильнее.

Альтернативное решение 2: Вывод данных в колонки

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

Измените запрос динамического списка, соединив таблицу Покупок с таблицей Продаж (ЛЕВОЕ СОЕДИНЕНИЕ по реквизиту основания). Выведите номер и дату продажи в соседних колонках рядом с данными покупки. Это обеспечит максимальную производительность, удобную сортировку и мгновенную визуальную оценку того, закрыта ли сделка.

Альтернативное решение 3: Программное Дерево Значений

Если структура связей слишком сложная (например, одна продажа закрывает десять покупок, или цепочка документов состоит из 3-4 уровней), стандартный динамический список может не справиться. В этой ситуации рассмотрим использование объекта ДеревоЗначений.

Вам потребуется написать алгоритм в серверном модуле формы, который выполняет нужный запрос, формирует в оперативной памяти сервера ДеревоЗначений, обходит выборку, выстраивая строки и подчиненные строки, а затем загружает результат в реквизит формы типа «Дерево значений». Главный минус этого подхода — потеря преимуществ динамического списка: вам придется самостоятельно реализовывать кнопки обновления списка, пагинацию (если записей слишком много) и учитывать расход оперативной памяти на сервере.

Подводя итог, можно сказать: реализовать иерархию документов в динамическом списке можно с помощью настройки поля родителя и UNION-запроса. Однако перед внедрением этого решения обязательно оцените объемы данных в вашей базе и рассмотрите более быстрые альтернативы (группировки или плоские таблицы).

← На главную