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