Как организовать быстрый поиск в справочнике номенклатуры в ERP так же, как в УПП (с позиционированием вместо фильтрации)

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

Переход с обычных форм (ОФ) на управляемые (УФ) в рамках внедрения современных конфигураций семейства 1С:Предприятие 8.3 (таких как 1С:ERP, 1С:КА или 1С:УТ 11) часто вызывает шквал критики со стороны конечных пользователей. Одной из главных причин недовольства становится изменение привычного поведения поиска в списках, особенно в больших справочниках, таких как Номенклатура.

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

---

В чем разница между поиском в ОФ и УФ?

Для того чтобы решить задачу, нам необходимо четко понимать физику процессов в обеих технологиях:

  1. Обычные формы (Позиционирование): Когда пользователь находился в списке номенклатуры в УПП 1.3 на любой строке и начинал набирать текст на клавиатуре, система не скрывала другие строки. Она мгновенно находила первую подходящую строку по текущей отсортированной колонке (например, по коду, артикулу или наименованию) и переносила фокус (курсор) туда. Пользователь продолжал видеть весь контекст — элементы выше и ниже найденного. Это происходило за доли секунды, так как платформа работала с базой данных напрямую через эффективные индексы позиционирования.
  2. Управляемые формы (Фильтрация): По умолчанию в динамических списках на управляемых формах ввод символов инициирует полнотекстовый поиск или наложение жесткого отбора. Список при этом перестраивается (скрывая все строки, не удовлетворяющие условию поиска). На огромных базах данных (сотни тысяч позиций номенклатуры с множеством характеристик) такой отбор может вызывать колоссальные задержки, а главное — пользователь теряет контекст и не видит соседние товары.

Давайте рассмотрим, как можно подружить требования эргономики пользователей с архитектурными особенностями управляемой платформы 1С 8.3.

---

Способ 1. Использование штатного механизма «Строки поиска» управляемой формы

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

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

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

Как это работает на практике: Теперь пользователю не нужно предварительно щелкать мышкой в поле поиска. Находясь на любой строке списка, он может сразу начать вводить текст. Фокус ввода автоматически переместится в верхнее поле поиска, и список начнет фильтроваться.

Минусы штатного метода:

Если этот вариант категорически не устраивает пользователей, переходим к программным методам эмуляции поведения ОФ.

---

Способ 2. Программная эмуляция позиционирования (перенос курсора на строку)

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

Разберем алгоритм по шагам и напишем соответствующий код.

Шаг 1. Подготовка формы

Добавим на форму списка номенклатуры новое поле ввода. Назовем его ПолеБыстрогоПоиска (тип значения — Строка). Установим у него свойство КнопкаОчистки в значение Да.

Шаг 2. Обработка изменения текста

Для добавленного поля создадим клиентский обработчик события АвтоПодбор или ПриИзменении. В данном примере рассмотрим обработчик АвтоПодбор, так как он срабатывает по мере ввода текста пользователем, что делает поиск «живым».


&НаКлиенте
Процедура ПолеБыстрогоПоискаАвтоПодбор(Элемент, Текст, ДанныеВыбора, Ожидание, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // Чтобы не перегружать сервер частыми запросами при быстром наборе, 
    // анализируем длину введенного текста. Начинаем искать хотя бы от 3-х символов.
    Если СтрДлина(Текст) < 3 Тогда
        Возврат;
    КонецЕсли;
    
    // Вызываем серверную функцию для поиска подходящей ссылки
    НайденнаяСсылка = НайтиНоменклатуруНаСервере(Текст);
    
    Если ЗначениеЗаполнено(НайденнаяСсылка) Тогда
        // Самый важный момент: переносим курсор списка на найденный элемент,
        // при этом сам список НЕ фильтруется, сохраняя весь контекст!
        Элементы.Список.ТекущаяСтрока = НайденнаяСсылка;
    КонецЕсли;

КонецПроцедуры

Шаг 3. Реализация серверного поиска

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


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

Преимущества данного метода: Полное визуальное соответствие поведению ОФ. Список не скрывается, фокус плавно прыгает на нужную строку по мере ввода символов.

Важное ограничение: Если в динамическом списке пользователем установлена сложная ручная сортировка (например, по реквизиту, который не совпадает с логикой нашего запроса УПОРЯДОЧИТЬ ПО), то курсор прыгнет на нужный элемент, но визуально он может оказаться в середине или в конце видимой области экрана, что дезориентирует пользователя. Для идеальной работы метода логика сортировки в запросе должна совпадать с текущей сортировкой динамического списка.

---

Способ 3. Переопределение обработчика «ОбработкаПолученияДанныхВыбора»

Этот метод не меняет логику поиска в самом списке, но кардинально решает проблему быстрого и безошибочного ввода номенклатуры в документы (в табличные части). Зачастую пользователи просят «поиск как в УПП» именно потому, что им неудобно подбирать товары в документы.

Мы можем переопределить стандартный поиск 1С при вводе строки в поле выбора документа. Для этого используется обработчик в модуле менеджера справочника Номенклатура.

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

Разберем программную реализацию в модуле менеджера справочника Номенклатура:


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

Почему это эффективно: Мы полностью контролируем процесс поиска на уровне базы данных. Использование конструкции ПОДОБНО &СтрокаПоиска + "%" (процент только в конце шаблона) гарантирует, что SQL-сервер применит индекс по соответствующему полю, и выборка выполнится мгновенно, в отличие от полнотекстового поиска по середине слова.

---

Способ 4. Панель быстрого алфавитного отбора

Если справочник номенклатуры структурирован по алфавиту или пользователям важно быстро переходить к товарам на определенную букву (как это часто делалось визуально в ОФ), можно вывести на форму динамическую панель с алфавитом.

Давайте разберем, как реализовать этот эргономичный механизм:

  1. Создадим на форме горизонтальную командную панель или группу кнопок.
  2. Программно при создании формы заполним ее кнопками с буквами русского алфавита («А», «Б», «В» ... «Я»).
  3. При нажатии на кнопку будем накладывать быстрый отбор на динамический список.

Посмотрим на программную реализацию этого интерфейсного решения:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартноеОформление)
    
    // Создаем группу для кнопок алфавита
    ГруппаАлфавит = Элементы.Добавить("ГруппаАлфавит", Тип("ГруппаФормы"), Элементы.Индекс(Элементы.Список) - 1);
    ГруппаАлфавит.Вид = ВидГруппыФормы.КоманднаяПанель;
    
    // Заполняем кнопками-буквами
    АлфавитСтрока = "АБВГДЕЖЗИКЛМНОПРСТУФХЦЧШЭЮЯ";
    Для НомерСимвола = 1 По СтрДлина(АлфавитСтрока) Цикл
        Буква = Сред(АлфавитСтрока, НомерСимвола, 1);
        
        ИмяКоманды = "КомандаБуква_" + Буква;
        ИмяКнопки = "КнопкаБуква_" + Буква;
        
        // Добавляем команду формы
        НоваяКоманда = Команды.Добавить(ИмяКоманды);
        НоваяКоманда.Действие = "ОбработчикНажатияБуквы";
        НоваяКоманда.Заголовок = Буква;
        
        // Добавляем кнопку на панель
        НоваяКнопка = Элементы.Добавить(ИмяКнопки, Тип("КнопкаФормы"), ГруппаАлфавит);
        НоваяКнопка.ИмяКоманды = ИмяКоманды;
    КонецЦикла;
    
КонецПроцедуры

&НаКлиенте
Процедура ОбработчикНажатияБуквы(Команда)
    
    // Получаем букву из имени команды
    ВыбраннаяБуква = Сред(Команда.Имя, СтрДлина("КомандаБуква_") + 1);
    
    // Устанавливаем быстрый отбор по первой букве наименования
    УстановитьОтборПоПервойБукве(ВыбраннаяБуква);
    
КонецПроцедуры

&НаСервере
Процедура УстановитьОтборПоПервойБукве(Буква)
    
    // Очищаем предыдущие отборы по этому полю
    ПолеКомпоновки = Новый ПолеКомпоновкиДанных("Наименование");
    
    ГруппаОтбора = Список.КомпоновщикНастроек.Настройки.Отбор;
    ЭлементыДляУдаления = Новый Массив;
    
    Для Каждого ЭлементОтбора Из ГруппаОтбора.Элементы Цикл
        Если ЭлементОтбора.ЛевоеЗначение = ПолеКомпоновки Тогда
            ЭлементыДляУдаления.Добавить(ЭлементОтбора);
        КонецЕсли;
    КонецЦикла;
    
    Для Каждого Элемент Из ЭлементыДляУдаления Цикл
        ГруппаОтбора.Элементы.Удалить(Элемент);
    КонецЦикла;
    
    // Накладываем новый отбор вида: "Наименование ПОДОБНО Буква%"
    Если ЗначениеЗаполнено(Буква) Тогда
        НовыйЭлемент = ГруппаОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
        НовыйЭлемент.ЛевоеЗначение = ПолеКомпоновки;
        НовыйЭлемент.ВидСравнения = ВидСравненияКомпоновкиДанных.Подобно;
        НовыйЭлемент.Использование = Истина;
        НовыйЭлемент.ПравоеЗначение = Буква + "%";
    КонецЕсли;
    
КонецПроцедуры

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

---

Резюме и рекомендации

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

Комбинируя эти подходы, вы сможете сделать работу пользователей в новой системе 1С:ERP максимально комфортной, быстрой и избавленной от лишних задержек интерфейса.

← На главную