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

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

При работе с иерархическими справочниками на платформе 1С:Предприятие 8.3 часто возникает необходимость отсортировать папки (группы) по одному реквизиту, а элементы внутри этих папок — по совершенно другому. Например, каталоги должны выводиться по приоритету или наименованию, а находящиеся внутри них позиции — по артикулу или цене.

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

Суть проблемы и частая ошибка

Разберем типичную ситуацию: при попытке прописать конструкцию УПОРЯДОЧИТЬ ПО непосредственно в тексте запроса динамического списка платформа выбивает ошибку: «Запрос Динамического списка не должен содержать УПОРЯДОЧИТЬ ПО. Для задания упорядочения воспользуйтесь закладкой "Порядок" на закладке настройки».

Это связано с тем, что динамический список самостоятельно управляет выборкой и сортировкой данных при отображении. Чтобы задать разное правило для групп и элементов, нам нужно выгрузить специальное виртуальное поле в запросе, а саму сортировку назначить в настройках порядка.

Шаг 1. Создание вычисляемого поля в запросе

Переведем динамический список в режим использования произвольного запроса. Для этого откроем свойства динамического списка в форме и установим флаг Свободный запрос. Проанализируем текст запроса и добавим в секцию ВЫБРАТЬ условное выражение:


ВЫБРАТЬ
	СправочникНоменклатура.Ссылка КАК Ссылка,
	СправочникНоменклатура.Наименование КАК Наименование,
	СправочникНоменклатура.ЭтоГруппа КАК ЭтоГруппа,
	СправочникНоменклатура.Реквизит1 КАК Реквизит1,
	СправочникНоменклатура.Реквизит2 КАК Реквизит2,
	ВЫБОР
		КОГДА СправочникНоменклатура.ЭтоГруппа
			ТОГДА СправочникНоменклатура.Реквизит1
		ИНАЧЕ СправочникНоменклатура.Реквизит2
	КОНЕЦ КАК ПолеСортировки
ИЗ
	Справочник.Номенклатура КАК СправочникНоменклатура

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

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

После создания виртуального поля ПолеСортировки выполним следующие действия:

  1. Убедимся, что в самом тексте запроса отсутствует инструкция УПОРЯДОЧИТЬ ПО.
  2. Откроем настройки динамического списка и перейдем на закладку Порядок.
  3. Добавим поле ПолеСортировки в список сортировки и укажем направление (по возрастанию или по убыванию).

При отображении иерархии в режиме просмотра «Дерево» или «Иерархический список» платформа 1С автоматически применит данную сортировку на каждом уровне иерархии отдельно. Для папок значение поля вычислится на основе Реквизит1, а для элементов — на основе Реквизит2.

Управление сортировкой из встроенного языка

Если порядок нужно устанавливать динамически при открытии формы или по команде пользователя, выставим параметры сортировки через КомпоновщикНастроек в коде формы.

Рассмотрим пример установки сортировки в событии ПриСозданииНаСервере:


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

Ограничения и нюансы работы

Выясним важные технические особенности этого подхода, которые необходимо учитывать при разработке:

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

Альтернативный вариант оптимизации для больших справочников

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

  1. Добавим в справочник реальный реквизит ПорядокСортировки (например, типа Строка или Число).
  2. Включим для этого реквизита свойство Индексировать.
  3. В модуле объекта справочника в обработчике ПередЗаписью пропишем заполнение реквизита: для групп записываем значение Реквизит1, для элементов — Реквизит2.
  4. В динамическом списке устанавливаем обычную сортировку по индексному полю ПорядокСортировки.

Таким образом, платформа 1С будет выполнять выборку и сортировку с использованием индексов СУБД моментально без дополнительных вычислений при каждом открытии динамического списка.

← На главную