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