При разработке интерфейсов на управляемых формах 1С программисты часто сталкиваются с ограничением стандартного механизма поиска (вызываемого по Ctrl+F или через строку поиска). Проблема заключается в том, что платформа индексирует для быстрого поиска только те данные, которые непосредственно выведены на форму в виде колонок таблицы. Если нам необходимо осуществлять поиск по служебному полю (например, по строке, содержащей склеенные значения нескольких реквизитов или скрытые артикулы), которое не должно загромождать интерфейс пользователя, стандартные средства перестают работать.
В этой статье мы подробно разберем, почему так происходит, и проанализируем несколько эффективных способов обхода этого ограничения, от визуальных хитростей до программного расширения функционала динамического списка.
Рассмотрим внутреннюю механику работы динамического списка. Когда пользователь вводит текст в строку поиска, платформа оптимизирует запрос к базе данных, анализируя только видимые элементы оформления. Это сделано для повышения производительности: системе незачем сканировать лишние поля в базе данных, если они не представлены в интерфейсе. Даже если мы установим свойство Использовать всегда для реквизита в настройках динамического списка, это лишь заставит систему считывать данные этого поля в выборку, но не включит его в поисковый индекс клиентской формы. Таким образом, нам придется внедрять дополнительные механизмы.
Проанализируем самый простой и быстрый в реализации способ. Если платформа требует, чтобы поле было "видимым" для включения в поиск, мы можем сделать его формально видимым для системы, но фактически незаметным для человеческого глаза. Это избавит нас от написания сложного кода обработки отборов.
Разберем по шагам, как настроить такое поле:
Видимость, иначе поиск перестанет по нему работать.РастягиватьПоГоризонтали в значение Нет.Ширина в минимальное значение, например 1.Заголовок.ЦветФонаФормы или белый).В результате поле присутствует в иерархии элементов, платформа индексирует его для поиска по Ctrl+F, но пользователь видит лишь пустую область шириной в несколько пикселей, которая не мешает работе.
Если визуальная маскировка нам не подходит из-за перфекционизма в дизайне или требований к архитектуре, рассмотрим программный метод. Мы создадим собственное поле ввода для поиска и будем программно накладывать условия на динамический список.
Выясним алгоритм реализации:
СтрокаПоискаПользователя (тип Строка).ПриИзменении этого поля пропишем логику установки отбора.Посмотрим на пример кода, который позволяет искать по скрытому полю СлужебноеОписание:
&НаКлиенте
Процедура СтрокаПоискаПользователяПриИзменении(Элемент)
УстановитьПоискПоСкрытомуПолю(СтрокаПоискаПользователя);
КонецПроцедуры
&НаСервере
Процедура УстановитьПоискПоСкрытомуПолю(ЗначениеПоиска)
// Получаем текущую группу отборов или создаем новую
ГруппаОтбора = Список.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
ГруппаОтбора.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли;
ГруппаОтбора.Представление = "Пользовательский поиск";
// Удаляем предыдущие поисковые отборы, чтобы они не дублировались
Для Каждого ЭлементОтбора Из Список.Отбор.Элементы Цикл
Если ЭлементОтбора.Представление = "Пользовательский поиск" И ЭлементОтбора <> ГруппаОтбора Тогда
Список.Отбор.Элементы.Удалить(ЭлементОтбора);
КонецЕсли;
КонецЦикла;
Если ЗначениеЗаполнено(ЗначениеПоиска) Тогда
// Поиск по стандартному видимому полю (например, Наименование)
НовыйОтбор = ГруппаОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НовыйОтбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Наименование");
НовыйОтбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит;
НовыйОтбор.ПравоеЗначение = ЗначениеПоиска;
НовыйОтбор.Использование = Истина;
// Поиск по СКРЫТОМУ служебному полю
СкрытыйОтбор = ГруппаОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
СкрытыйОтбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СлужебноеОписание");
СкрытыйОтбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит;
СкрытыйОтбор.ПравоеЗначение = ЗначениеПоиска;
СкрытыйОтбор.Использование = Истина;
КонецЕсли;
КонецПроцедуры
В данном примере мы используем группу ИЛИ. Это критически важно, так как поиск должен находить совпадение либо в основном поле, либо в служебном. Обратите внимание, что для работы этого метода поле СлужебноеОписание должно быть включено в запрос динамического списка и у него должно быть установлено свойство УстановитьОбязательноеИспользование(Истина) или включен флаг Использовать всегда в настройках списка.
Рассмотрим ситуацию, когда данных очень много. Поиск по условию ПОДОБНО (содержит) может существенно замедлять работу базы данных, особенно если поле текстовое и длинное. В таких случаях целесообразно использовать механизм полнотекстового поиска платформы.
Для этого необходимо:
Полнотекстовый поиск — Использовать).Состав поиска) проверить, разрешено ли использование полнотекстового поиска.Особенность этого метода в том, что стандартная строка поиска при определенных настройках может обращаться к индексу ППИ. Если скрытое поле проиндексировано, платформа может найти данные по нему даже без вывода на форму. Однако этот метод считается "менее управляемым", так как результат зависит от актуальности индекса и внутренних алгоритмов ранжирования платформы.
Выясним роль метода УстановитьОбязательноеИспользование(). Многие начинающие разработчики путают его назначение. Если мы напишем в ПриСозданииНаСервере:
Список.УстановитьОбязательноеИспользование("СлужебноеПоле", Истина);
Это не сделает поле доступным для стандартного Ctrl+F. Этот метод гарантирует, что данные поля будут переданы с сервера на клиент, даже если поле не выведено в таблицу. Это полезно, если вы программно перехватываете стандартный поиск или используете данные в обработчиках событий (например, при активации строки). Но для включения в автоматический индекс поиска формы поле все равно должно физически присутствовать в коллекции Элементы.
Проанализировав все доступные варианты, мы можем сделать следующие выводы:
Ctrl+F.Группу ИЛИ в компоновке данных динамического списка.Помните, что избыточное количество полей, участвующих в поиске, может снижать производительность динамического списка. Старайтесь индексировать и использовать для поиска только действительно необходимые служебные данные.