Как вывести данные в виде дерева с итогами в динамическом списке

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

При разработке интерфейсов на платформе 1С:Предприятие 8.3 часто возникает задача отобразить данные не плоским списком, а в виде иерархии с промежуточными итогами. Классический пример — остатки товаров в разрезе складов, где в строке с номенклатурой мы хотим видеть общий остаток, а при нажатии на «плюс» — детализацию по конкретным местам хранения. Однако стандартный ДинамическийСписок накладывает определенные ограничения, так как в его основном запросе нельзя использовать конструкцию ИТОГИ.

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

Причина ограничения динамического списка

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

Решение 1: Настройка группировки в динамическом списке

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

  1. Откроем форму, на которой размещен динамический список.
  2. Перейдем в свойства реквизита Список и откроем ссылку «Настройка списка».
  3. На вкладке «Группировка» добавим поле Номенклатура.
  4. В поле «Отображение» выберем режим Иерархический список или Дерево.

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

Решение 2: Использование вложенных запросов и соединений

Чтобы «обмануть» ограничение на расчет итогов и заставить динамический список выводить сумму в строке с номенклатурой, мы можем заранее рассчитать эти итоги в основном запросе. Проанализируем пример запроса:


ВЫБРАТЬ
    ОсновнойЗапрос.Номенклатура КАК Номенклатура,
    ОсновнойЗапрос.СтруктурнаяЕдиница КАК СтруктурнаяЕдиница,
    ОсновнойЗапрос.КоличествоОстаток КАК КоличествоОстаток,
    ВложенныйИтог.ОбщийОстаток КАК ОбщийОстаток
ИЗ
    РегистрНакопления.ЗапасыНаСкладах.Остатки КАК ОсновнойЗапрос
ЛЕВОЕ СОЕДИНЕНИЕ (
    ВЫБРАТЬ
        Запасы.Номенклатура КАК Номенклатура,
        СУММА(Запасы.КоличествоОстаток) КАК ОбщийОстаток
    ИЗ
        РегистрНакопления.ЗапасыНаСкладах.Остатки КАК Запасы
    СГРУППИРОВАТЬ ПО
        Запасы.Номенклатура
) КАК ВложенныйИтог ПО ОсновнойЗапрос.Номенклатура = ВложенныйИтог.Номенклатура

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

Решение 3: Дерево значений как альтернатива

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

Рассмотрим алгоритм реализации:

  1. Создадим на форме реквизит с типом ДеревоЗначений.
  2. Добавим колонки Номенклатура, Склад, Количество.
  3. При создании формы или по кнопке «Обновить» выполним запрос с предложением ИТОГИ.
  4. Заполним дерево программно.

Для выгрузки результата запроса в дерево удобно использовать метод Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам).

Решение 4: Динамическое заполнение дерева (Оптимизация)

Часто возникает вопрос: можно ли дерево значений заполнять динамически, как список? В 1С нет встроенного «динамического дерева», но мы можем реализовать его имитацию. Это позволит работать с миллионами записей мгновенно.

Разберем логику по шагам:

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

Пример кода для обработки развертывания:


&НаКлиенте
Процедура ДеревоОстатковПриРазвертывании(Элемент, СтрокаИдентификатор, Отказ)
    СтрокаДерева = ДеревоОстатков.НайтиПоИдентификатору(СтрокаИдентификатор);
    Если СтрокаДерева.ДанныеЗагружены = Ложь Тогда
        ЗагрузитьПодчиненныеДанныеНаСервере(СтрокаДерева.Номенклатура, СтрокаИдентификатор);
    КонецЕсли;
КонецПроцедуры

Этот метод сочетает в себе визуальную мощь дерева и производительность динамического списка.

Выясним, что лучше выбрать

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

Если же дерево необходимо для интерактивного выбора (например, в подборе товаров), то выбирайте Дерево значений с динамической подгрузкой. Динамический список стоит использовать только тогда, когда вам достаточно стандартной иерархии справочника (группы и элементы) без сложных расчетов итогов «на лету».

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

← На главную