При разработке интерфейсов на платформе 1С:Предприятие 8.3 часто возникает задача отобразить данные не плоским списком, а в виде иерархии с промежуточными итогами. Классический пример — остатки товаров в разрезе складов, где в строке с номенклатурой мы хотим видеть общий остаток, а при нажатии на «плюс» — детализацию по конкретным местам хранения. Однако стандартный ДинамическийСписок накладывает определенные ограничения, так как в его основном запросе нельзя использовать конструкцию ИТОГИ.
В этой статье мы подробно разберем, почему стандартный подход не работает «из коробки», и рассмотрим несколько эффективных способов решения задачи: от настройки группировок до использования дерева значений с динамической подгрузкой.
Разберем ситуацию: когда мы пишем обычный запрос для отчета, использование предложения ИТОГИ ... ПО позволяет платформе автоматически сформировать древовидную структуру с рассчитанными суммами по уровням. Но ДинамическийСписок работает иначе. Его задача — быстро отображать порции данных, которые нужны пользователю в данный момент. Механизм динамического списка базируется на Системе компоновки данных (СКД), которая сама управляет выборкой. Использование ИТОГИ в тексте запроса динамического списка запрещено на уровне платформы, так как это нарушило бы логику постраничного вывода данных.
Самый простой путь, не требующий сложного кодирования, — это использование встроенных механизмов группировки СКД внутри настроек динамического списка. Рассмотрим, как это сделать по шагам:
Список и откроем ссылку «Настройка списка».Номенклатура.Иерархический список или Дерево.Проблема данного метода: По умолчанию в строке группировки (там, где товар) числовые показатели могут быть пустыми или отображаться некорректно, если не настроены ресурсы. В современных версиях платформы (начиная с 8.3.15) возможности отображения агрегатных функций в динамических списках расширились, но они все равно ограничены. Если нам нужно гарантированное отображение суммы именно в родительской строке, перейдем к следующему методу.
Чтобы «обмануть» ограничение на расчет итогов и заставить динамический список выводить сумму в строке с номенклатурой, мы можем заранее рассчитать эти итоги в основном запросе. Проанализируем пример запроса:
ВЫБРАТЬ
ОсновнойЗапрос.Номенклатура КАК Номенклатура,
ОсновнойЗапрос.СтруктурнаяЕдиница КАК СтруктурнаяЕдиница,
ОсновнойЗапрос.КоличествоОстаток КАК КоличествоОстаток,
ВложенныйИтог.ОбщийОстаток КАК ОбщийОстаток
ИЗ
РегистрНакопления.ЗапасыНаСкладах.Остатки КАК ОсновнойЗапрос
ЛЕВОЕ СОЕДИНЕНИЕ (
ВЫБРАТЬ
Запасы.Номенклатура КАК Номенклатура,
СУММА(Запасы.КоличествоОстаток) КАК ОбщийОстаток
ИЗ
РегистрНакопления.ЗапасыНаСкладах.Остатки КАК Запасы
СГРУППИРОВАТЬ ПО
Запасы.Номенклатура
) КАК ВложенныйИтог ПО ОсновнойЗапрос.Номенклатура = ВложенныйИтог.Номенклатура
В этом случае поле ОбщийОстаток будет содержать сумму по всей номенклатуре и будет доступно в каждой строке, включая строки группировки. Важно помнить: такой подход может существенно замедлить работу списка при больших объемах данных, так как при каждой прокрутке серверу придется выполнять тяжелое соединение с агрегатными функциями.
Если динамический список не позволяет добиться нужного визуального эффекта, профессиональным решением будет использование объекта ДеревоЗначений. В отличие от динамического списка, дерево значений полностью подконтрольно программисту, и в нем можно реализовать любую иерархию с любыми итогами.
Рассмотрим алгоритм реализации:
ДеревоЗначений.Номенклатура, Склад, Количество.ИТОГИ.Для выгрузки результата запроса в дерево удобно использовать метод Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам).
Часто возникает вопрос: можно ли дерево значений заполнять динамически, как список? В 1С нет встроенного «динамического дерева», но мы можем реализовать его имитацию. Это позволит работать с миллионами записей мгновенно.
Разберем логику по шагам:
ПриРазвертывании для элемента формы (таблицы дерева).Пример кода для обработки развертывания:
&НаКлиенте
Процедура ДеревоОстатковПриРазвертывании(Элемент, СтрокаИдентификатор, Отказ)
СтрокаДерева = ДеревоОстатков.НайтиПоИдентификатору(СтрокаИдентификатор);
Если СтрокаДерева.ДанныеЗагружены = Ложь Тогда
ЗагрузитьПодчиненныеДанныеНаСервере(СтрокаДерева.Номенклатура, СтрокаИдентификатор);
КонецЕсли;
КонецПроцедуры
Этот метод сочетает в себе визуальную мощь дерева и производительность динамического списка.
Проанализируем ситуацию: если ваша задача — просто показать отчет по остаткам, то лучшим решением, как советовали эксперты в обсуждении, будет использование отчета на базе СКД. Его можно встроить прямо в форму. Отчеты идеально справляются с итогами, иерархией и группировками.
Если же дерево необходимо для интерактивного выбора (например, в подборе товаров), то выбирайте Дерево значений с динамической подгрузкой. Динамический список стоит использовать только тогда, когда вам достаточно стандартной иерархии справочника (группы и элементы) без сложных расчетов итогов «на лету».
Таким образом, мы рассмотрели все основные способы вывода древовидных структур. Выбор конкретного метода зависит от требований к производительности системы и сложности иерархии ваших данных.