Как реализовать быстрый ввод склада по части кода в обычных формах 1С:УПП 1.3?

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

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

В управляемом интерфейсе для этих целей предусмотрено стандартное событие ОбработкаПолученияДанныхВыбора в модуле менеджера объекта, а также настройка свойства СпособПоискаСтрокиПриВводеПоСтроке.ЛюбаяЧасть. Однако в обычном приложении эти механизмы не работают, из-за чего попытки перехватить ввод на уровне модуля менеджера не дают результата. Разберем по шагам, почему так происходит и какими способами можно реализовать быстрый ввод по коду в обычном приложении 1С.

Анализ причин: почему не срабатывает ОбработкаПолученияДанныхВыбора

Выясним причину, по которой стандартные подходы управляемых форм дают сбой в толстом клиенте обычного приложения:

  1. Ограничение платформы: событие ОбработкаПолученияДанныхВыбора модуля менеджера и метод ПолучитьДанныеВыбора вызываются только в тонком/веб-клиенте и на управляемых формах. В обычном приложении при вводе текста в поле платформа выполняет поиск напрямую по метаданным справочника («Ввод по строке»), минуя модуль менеджера.
  2. Поиск только по началу строки: в обычных формах встроенный автопоиск работает строго по началу строки с учетом всех лидирующих нулей и символов. Если код элемента в базе выглядит как УТ-00000123, то при вводе пользователем 123 стандартный механизм не найдет соответствие.
  3. Различия в событиях элементов формы: состав параметров событий полей ввода в обычных и управляемых формах различается. В обычном приложении список подсказок не передается через параметр ДанныеВыбора события автоподбора.

Вариант 1. Перехват события АвтоПодборТекста в форме документа

Рассмотрим вариант, предложенный в обсуждении. Мы перехватываем ввод символов непосредственно в поле ввода формы с помощью события АвтоПодборТекста, выполняем запрос к справочнику по маске и предлагаем пользователю интерактивный выбор через список значений.

Посмотрим на пример реализации обработчика события в модуле формы документа:


Процедура СкладОрдерАвтоПодборТекста(Элемент, Текст, ТекстАвтоПодбора, СтандартнаяОбработка)

    // Проверяем, что пользователь ввел хотя бы один символ
    Если ПустаяСтрока(Текст) Тогда
        Возврат;
    КонецЕсли;

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

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

Вариант 2. Использование события ОкончаниеВводаТекста (Рекомендуемый)

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

Разберем по шагам логику работы данного события:

  1. Событие срабатывает только один раз — когда пользователь нажал клавишу Enter или перевел фокус на другой элемент.
  2. Если найдено единственное соответствие, значение устанавливается сразу в параметр Значение без открытия дополнительных диалогов.
  3. Если найдено несколько подходящих складов, пользователю открывается выпадающий список для уточнения.

Посмотрим на пример программной реализации:


Процедура СкладОрдерОкончаниеВводаТекста(Элемент, Текст, Значение, СтандартнаяОбработка)

    Если ПустаяСтрока(Текст) Тогда
        Возврат;
    КонецЕсли;

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

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

Вариант 3. Нормализация кода с лидирующими нулями

Если в информационной базе все коды имеют фиксированную длину и различаются только числовой частью (без поиска по произвольной подстроке в середине), оптимальным решением с точки зрения быстродействия будет дополнение введенного числа лидирующими нулями до нужной длины.

Рассмотрим подробнее: поиск по условию ПОДОБНО "%..." с символом процента в начале строки не позволяет СУБД использовать индекс по полю Код, что на больших справочниках может приводить к замедлению. Поиск методом НайтиПоКоду использует кластерный индекс и выполняется мгновенно.

Посмотрим на пример кода с нормализацией введенного значения:


Процедура СкладОрдерОкончаниеВводаТекста(Элемент, Текст, Значение, СтандартнаяОбработка)

    ЧисловойКод = 0;
    Попытка
        ЧисловойКод = Число(СокрЛП(Текст));
    Исключение
        Возврат; // Введен нечисловой текст, передаем управление платформе
    КонецПопытки;

    ДлинаКода = Метаданные.Справочники.Склады.ДлинаКода;
    
    // Формируем код с лидирующими нулями без пробелов-разделителей
    СформированныйКод = Формат(ЧисловойКод, "ЧЦ=" + ДлинаКода + "; ЧВН=; ЧГ=");
    
    НайденныйСклад = Справочники.Склады.НайтиПоКоду(СформированныйКод);
    
    Если ЗначениеЗаполнено(НайденныйСклад) Тогда
        Значение = НайденныйСклад;
        СтандартнаяОбработка = Ложь;
    КонецЕсли;

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

Резюме: для реализации быстрого подбора в обычных формах 1С следует переносить логику поиска в модуль формы документа, используя события ОкончаниеВводаТекста или АвтоПодборТекста в сочетании с методом ВыбратьИзСписка.

← На главную