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

Программист 1С v8.3 (Обычные формы)
← На главную

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

Анализируем стандартные возможности платформы

Прежде чем приступать к написанию кода, проанализируем ситуацию. Платформа 1С:Предприятие 8.3 имеет встроенные механизмы для поиска по подстроке. В свойствах поля ввода (например, в табличной части документа "Заказ покупателя") существует настройка "Способ поиска при вводе по строке". Однако, как показывает практика, простое переключение этого свойства на "Любая часть" не всегда дает результат. Выясним причину: часто это связано с режимом совместимости конфигурации или отсутствием необходимых индексов в базе данных.

Если стандартная настройка не сработала, мы можем вмешаться в процесс программно. Рассмотрим первый и самый лаконичный способ — использование события АвтоПодбор.

Способ 1: Использование события АвтоПодбор

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

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

Вставьте следующий программный код (его можно подготовить через консоль кода с ИИ):


&НаКлиенте
Процедура НоменклатураАвтоПодбор(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, Ожидание, СтандартнаяОбработка)
    // Устанавливаем способ поиска по любой части слова программно
    ПараметрыПолученияДанных.СпособПоискаСтроки = СпособПоискаСтрокиПриВводеПоСтроке.ЛюбаяЧасть;
КонецПроцедуры

Важный нюанс: для того чтобы этот метод работал эффективно, убедитесь, что у реквизита "Наименование" справочника "Номенклатура" установлено свойство "Индексировать" или "Индексировать с доп. упорядочиванием". Без индекса на больших справочниках поиск может "подтормаживать".

Способ 2: Кастомный поиск через запрос и событие ОкончаниеВводаТекста

Если стандартный АвтоПодбор не дает нужной гибкости (например, нужно искать одновременно и по наименованию, и по артикулу), проанализируем ситуацию с использованием прямого запроса. Рассмотрим пример реализации в процедуре ОкончаниеВводаТекста.

Этот метод позволяет полностью контролировать выборку данных. Мы составим запрос, используя процессор схемы запроса, который будет искать вхождения текста в любой части строки с помощью оператора ПОДОБНО.


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

Рассмотрим подробнее, что происходит в этом коде. Мы добавили условие Номенклатура.ЭтоГруппа = ЛОЖЬ, чтобы в результатах не появлялись папки справочника, так как в заказы обычно подбираются только конкретные товары. Также мы использовали блок ПОДОБНО &ТекстПоиска, где параметр обрамлен символами процента. Это ключевой момент для поиска "внутри" строки.

Производительность и использование ПОДОБНО

Проанализируем техническую сторону вопроса. Использование конструкции ПОДОБНО "%Текст%" имеет существенный минус. SQL-сервер не может использовать обычные индексы, если символ процента стоит в начале строки поиска. Это заставляет систему выполнять полное сканирование таблицы (Full Scan), что на базах с 100 000+ позиций номенклатуры приведет к задержкам в несколько секунд при каждом вводе буквы.

Как мы можем оптимизировать этот процесс? Рассмотрим несколько рекомендаций:

Современный подход: ОбработкаПолученияДанныхВыбора

Если ваша конфигурация работает на управляемых формах, разберем наиболее "правильный" с точки зрения архитектуры 1С способ. Вместо того чтобы писать код в каждой форме каждого документа, мы перенесем логику поиска в модуль менеджера справочника "Номенклатура".

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


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

Посмотрим на преимущества этого подхода: во-первых, централизация кода. Вам не нужно менять десятки форм. Во-вторых, этот механизм корректно работает в интерфейсе "Такси" (решая проблемы с фокусом в форме подбора) и поддерживает асинхронность, что важно для стабильной работы тонкого клиента.

Особенности интерфейса и модальности

Выясним причину возможных ошибок, о которых упоминалось в обсуждении (сообщение №12). В старых версиях 1С часто использовались модальные окна для выбора из списка. В современных версиях платформы (8.3.15+) режим модальности по умолчанию выключен. Это значит, что метод ВыбратьИзСписка может вести себя не так, как ожидалось.

Чтобы избежать ошибок типа "Значение не является значением объектного типа", всегда проверяйте результат выбора на Неопределено (как в примере для Способа 2). Если пользователь нажал Esc или кликнул мимо списка, программа не должна пытаться присвоить пустое значение реквизиту.

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

← На главную