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