Как программно развернуть все группировки в динамическом списке на управляемых формах

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

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

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

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

Метод Элементы.Список.Развернуть(ИдентификаторСтроки) требует передачи конкретного идентификатора. Если список сгруппирован, идентификатором строки группировки обычно выступает значение поля, по которому выполнена группировка (например, ссылка на контрагента или конкретное значение перечисления). Выясним, как эффективно использовать штатные и программные средства для решения задачи развертывания.

Способ 1. Использование свойств элемента формы (штатный метод)

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

  1. Найдем в дереве элементов формы нужную таблицу, связанную с динамическим списком.
  2. В палитре свойств найдем раздел Отображение.
  3. Установим свойство Отображение в значение Дерево.
  4. Установим свойство НачальноеОтображениеДерева в значение Раскрывать все уровни.

Рассмотрим нюанс: это свойство отлично работает при первичной инициализации списка. Если пользователь в процессе работы нажимает кнопку «Обновить», платформа старается сохранить текущее состояние веток. Если же происходит изменение состава группировок, свойство НачальноеОтображениеДерева может сработать повторно, обеспечив нужный результат без написания кода.

Способ 2. Программное управление через метод Развернуть()

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


&НаКлиенте
Процедура МойСписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
    // ВыбраннаяСтрока — это и есть идентификатор, который понимает метод Развернуть
    Если Не Элементы.МойСписок.Развернут(ВыбраннаяСтрока) Тогда
        Элементы.МойСписок.Развернуть(ВыбраннаяСтрока);
    Иначе
        Элементы.МойСписок.Свернуть(ВыбраннаяСтрока);
    КонецЕсли;
КонецПроцедуры

Здесь важно понимать, что ВыбраннаяСтрока в динамическом списке — это ключ записи (обычно ссылка) или значение группировки. Если мы хотим развернуть список полностью программно, нам нужно знать все эти ключи.

Способ 3. Получение идентификаторов группировок через СКД

Если задача стоит максимально остро — «развернуть все уровни программно в любой момент времени», — нам придется выяснить, какие именно группы сейчас сформированы в списке. Поскольку на клиенте итерация невозможна, выполним расчет на сервере, используя компоновщик настроек динамического списка. Для упрощения программной работы с объектами СКД можно использовать модуль-обёртку над объектной моделью СКД.

Проанализируем алгоритм действий: 1. Получим текущие настройки компоновщика (отборы, параметры, группировки). 2. Выполним запрос динамического списка на сервере через схему компоновки данных. 3. Выгрузим результат в дерево значений. 4. Обойдем дерево значений и соберем все значения группировочных полей в массив. 5. Передадим этот массив на клиент и в цикле вызовем метод Развернуть().

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


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

&НаСервере
Процедура СобратьЗначенияГруппировок(СтрокиДерева, МассивИдентификаторов)
    Для Каждого Строка Из СтрокиДерева Цикл
        // Предположим, группировка идет по первой колонке
        Если Строка.Строки.Количество() > 0 Тогда
            МассивИдентификаторов.Добавить(Строка[0]); // Добавляем значение группировки
            СобратьЗначенияГруппировок(Строка.Строки, МассивИдентификаторов);
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

После получения массива идентификаторов на клиенте останется лишь вызвать цикл:


&НаКлиенте
Процедура РазвернутьВсеГруппировки()
    Идентификаторы = ПолучитьИдентификаторыГруппировок();
    Для Каждого Ид Из Идентификаторы Цикл
        Элементы.Список.Развернуть(Ид, Истина); // Истина — развернуть с подчиненными
    КонецЦикла;
КонецПроцедуры

Важные ограничения и рекомендации

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

Полезные советы:

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

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

← На главную