Как настроить сортировку по произвольному реквизиту при быстром выборе в справочниках 1С?

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

Каждый разработчик в среде «1С:Предприятие» рано или поздно сталкивается с задачами тонкой настройки интерфейса под требования конечных пользователей. Одна из таких классических задач — управление порядком отображения данных в списках. Представим распространенную ситуацию: в нашей конфигурации есть справочник Организации. По умолчанию платформа упорядочивает его элементы по наименованию. Однако для удобства пользователей мы создали новый числовой реквизит Сорт и хотим, чтобы элементы справочника везде выстраивались в соответствии с приоритетом, указанным в этом поле.

Если мы настраиваем сортировку для полноценной формы списка справочника, то задача решается буквально в одну строку кода в событии ПередОткрытием или ПриОткрытии с использованием метода Порядок.Установить(). Но как только дело доходит до режима «Быстрого выбора» (когда пользователь нажимает кнопку выбора в поле ввода или начинает вводить текст, и перед ним открывается компактный выпадающий список), стандартная сортировка перестает работать. Список по-прежнему упорядочивается по наименованию или коду.

В этой статье мы подробно проанализируем, почему возникает это ограничение платформы, разберем обязательные подготовительные шаги в конфигураторе и рассмотрим эффективные программные способы решения проблемы как для современных управляемых форм (платформа 1С 8.3), так и для классических обычных форм (платформа 1С 8.2).

Выясняем причину ограничения платформы «1С:Предприятие»

Для того чтобы найти правильное решение, сначала разберем природу возникшей проблемы. Механизм быстрого выбора в поле ввода — это системный инструмент платформы, спроектированный для максимального быстродействия. Когда пользователь активирует быстрое нажатие или ввод по строке, платформа не создает и не инициализирует стандартную форму списка справочника. Следовательно, любые процедуры, написанные нами в модуле формы списка (например, в обработчиках ПриОткрытии или ПередОткрытием), физически не выполняются.

Платформа автоматически генерирует облегченный SQL-запрос к базе данных, получая только те поля, которые необходимы для визуального представления (ссылку и текстовое представление). Сортировка этого системного запроса жестко привязана к свойству справочника «Основное представление» (это может быть либо Наименование, либо Код). Возможность указать другое поле для автоматической сортировки при быстром выборе в свойствах метаданных конфигуратора просто отсутствует.

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

Обязательный шаг: Индексация реквизита в конфигураторе

Прежде чем приступать к написанию программного кода, необходимо настроить структуру базы данных. Любая сортировка по кастомному полю требует значительных вычислительных ресурсов СУБД. Если наш справочник содержит тысячи записей, то выполнение запросов с сортировкой по неиндексированному полю приведет к серьезному снижению производительности всей системы.

Выполним предварительную настройку реквизита по шагам:

  1. Откроем конфигуратор нашей базы данных и найдем нужный справочник (в нашем случае — Организации).
  2. Перейдем на вкладку Реквизиты и найдем наш числовой реквизит Сорт.
  3. Откроем палитру свойств этого реквизита.
  4. Найдем свойство Индексировать и установим для него значение Индексировать или Индексировать с дополнительным упорядочиванием.

Использование режима «Индексировать с дополнительным упорядочиванием» предпочтительнее, так как оно оптимизирует работу СУБД в тех случаях, когда значения реквизита Сорт у разных элементов могут совпадать. В этом случае система будет строить индекс сначала по нашему полю, а затем дополнительно по ссылке или наименованию.

Решение для управляемых форм (1С 8.3): Модуль менеджера

В современных конфигурациях на управляемых формах задача решается наиболее элегантно и глобально. Платформа 1С 8.3 предоставляет разработчикам специальное событие в модуле менеджера объекта — ОбработкаПолученияДанныхВыбора. Этот обработчик перехватывает запросы на получение данных для ввода по строке и быстрого выбора на уровне сервера для всей конфигурации.

Рассмотрим алгоритм реализации этого метода:

  1. Перейдем в конфигураторе к нашему справочнику Организации, нажмем по нему правой кнопкой мыши и выберем пункт Открыть модуль менеджера.
  2. Создадим шаблон процедуры-обработчика события ОбработкаПолученияДанныхВыбора.
  3. Внутри обработчика установим параметр СтандартнаяОбработка в значение Ложь. Это отключит стандартный системный алгоритм формирования выпадающего списка.
  4. Напишем собственный запрос к таблице справочника, в котором отберем элементы по переданной строке поиска и жестко укажем сортировку по нашему реквизиту Сорт.
  5. Выгрузим результат запроса в специальный СписокЗначений и передадим его в выходной параметр ДанныеВыбора.

Посмотрим на практический пример реализации этого обработчика в модуле менеджера:


Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)
    
    // Отключаем стандартный поиск и сортировку платформы
    СтандартнаяОбработка = Ложь;
    
    // Создаем список значений для хранения результатов выбора
    СписокРезультатов = Новый СписокЗначений;
    
    // Строим запрос для получения данных с учетом сортировки по реквизиту Сорт
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ РАЗРЕШЕННЫЕ
        |	Организации.Ссылка КАК Ссылка,
        |	Организации.Наименование КАК Представление
        |ИЗ
        |	Справочник.Организации КАК Организации
        |ГДЕ
        |	НЕ Организации.ПометкаУдаления
        |	И Организации.Наименование ПОДОБНО &СтрокаПоиска
        |
        |УПОРЯДОЧИТЬ ПО
        |	Организации.Сорт ВОЗР,
        |	Представление ВОЗР";
        
    // Если пользователь ввел текст в поле, осуществляем поиск по подстроке
    СтрокаПоиска = "%" + Параметры.СтрокаПоиска + "%";
    Запрос.УстановитьПараметр("СтрокаПоиска", СтрокаПоиска);
    
    Выборка = Запрос.Выполнить().Выбрать();
    Пока Выборка.Следующий() Цикл
        // Заполняем список выбора структурами (Значение и Текстовое представление)
        СписокРезультатов.Добавить(Выборка.Ссылка, Выборка.Представление);
    КонецЦикла;
    
    // Возвращаем сформированный нами упорядоченный список в платформу
    ДанныеВыбора = СписокРезультатов;
    
КонецПроцедуры

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

Решение для обычных форм (1С 8.2): Перехват событий элемента управления

В старых конфигурациях на базе обычных форм механизм модуля менеджера выражен слабо, и событие ОбработкаПолученияДанныхВыбора там отсутствует. В этом случае нам придется решать задачу локально на уровне конкретной формы, в которой расположено поле ввода организации.

Проанализируем ситуацию: чтобы выпадающий список при быстром выборе содержал элементы в нужном порядке, мы можем принудительно переопределить поведение элемента управления поля ввода при нажатии кнопки выбора. Для этого задействуем событие НачалоВыбораИзСписка.

Разберем по шагам, как это реализовать:

  1. Откроем форму документа или объекта, где находится наше поле ввода организации.
  2. В свойствах поля ввода найдем событие НачалоВыбораИзСписка и создадим его процедуру-обработчик в модуле формы.
  3. В коде процедуры установим параметр СтандартнаяОбработка в значение Ложь.
  4. Очистим коллекцию СписокВыбора нашего элемента управления.
  5. Выполним запрос к справочнику Организации с упорядочиванием по полю Сорт и программно заполним СписокВыбора результатами запроса.

Посмотрим на пример программного кода для обычной формы:


Процедура ОрганизацияНачалоВыбораИзСписка(Элемент, СтандартнаяОбработка)
    
    // Отключаем стандартный вывод системного списка
    СтандартнаяОбработка = Ложь;
    
    // Очищаем список выбора элемента управления перед заполнением
    Элемент.СписокВыбора.Очистить();
    
    // Формируем запрос к справочнику организаций
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Организации.Ссылка КАК Ссылка
        |ИЗ
        |	Справочник.Организации КАК Организации
        |ГДЕ
        |	НЕ Организации.ПометкаУдаления
        |УПОРЯДОЧИТЬ ПО
        |	Организации.Сорт ВОЗР";
        
    Выборка = Запрос.Выполнить().Выбрать();
    Пока Выборка.Следующий() Цикл
        // Наполняем список выбора элемента управления отсортированными ссылками
        Элемент.СписокВыбора.Добавить(Выборка.Ссылка);
    КонецЦикла;
    
КонецПроцедуры

Дополнительно, если пользователю необходим поиск по первым буквам (ввод по строке с автоподбором), мы можем перехватить событие АвтоПодборТекста у этого же поля ввода. В обработчике мы аналогично сформируем запрос к базе данных, передав введенный текст в качестве условия поиска ПОДОБНО, отсортируем результат по реквизиту Сорт и передадим список в параметры подбора.

Дополнительный сценарий: Сортировка по умолчанию в динамических списках

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

В управляемых формах списки выводятся через объект ДинамическийСписок. Задать сортировку по кастомному реквизиту по умолчанию в свойствах списка в конфигураторе напрямую невозможно. Однако мы можем легко сделать это программно при инициализации формы выбора.

Разберем по шагам, как настроить сортировку динамического списка формы выбора в событии ПриСозданииНаСервере:

  1. Откроем модуль формы выбора нашего справочника.
  2. Создадим обработчик события ПриСозданииНаСервере.
  3. Обратимся к свойству динамического списка (по умолчанию это реквизит формы с именем Список) и настроим его компоновщик настроек.
  4. Очистим текущую коллекцию элементов порядка компоновщика данных и добавим новое правило сортировки по полю Сорт.

Посмотрим на пример программного кода:


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

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

Подведем итоги

Мы подробно проанализировали проблему сортировки при быстром выборе в справочниках 1С и выяснили, что стандартное системное ограничение платформы легко обходится с помощью программных инструментов.

Для конфигураций на управляемых формах (1С 8.3) лучшим решением является переопределение события ОбработкаПолученияДанныхВыбора в модуле менеджера справочника, так как это решает задачу централизованно. Для старых решений на обычных формах (1С 8.2) спасением станет локальный перехват событий элементов управления формы (НачалоВыбораИзСписка и АвтоПодборТекста). И, конечно, никогда не забывайте индексировать сортируемые реквизиты в конфигураторе для поддержания высокой скорости работы вашей информационной базы!

← На главную