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