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