Почему в 1С при событии ОкончаниеВводаТекста возникает ошибка «не найдено» и как это исправить?

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

При разработке на управляемых формах 1С программисты часто сталкиваются с необходимостью валидации данных непосредственно в момент их ввода. Казалось бы, событие ОкончаниеВводаТекста идеально подходит для этой задачи: мы можем проверить введенную строку и, если она не удовлетворяет условиям, прервать ввод. Однако на практике установка параметра СтандартнаяОбработка = Ложь часто приводит к неожиданному поведению платформы — вместо тихого возврата к старому значению система выдает диагностическое сообщение «Объект не найден» или «Значение не найдено».

В этой статье мы подробно разберем, почему возникает эта мистическая ошибка, проанализируем внутренние механизмы работы поля ввода и рассмотрим несколько надежных способов решения проблемы.

Суть проблемы и анализ поведения платформы

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


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

В этот момент и происходит странное: система выдает ошибку поиска, хотя мы работаем с обычной строкой, а не со ссылочным типом. Выясним причину этого поведения. Когда мы устанавливаем СтандартнаяОбработка = Ложь в обработчике ОкончаниеВводаТекста, мы берем на себя ответственность за результат выбора. Платформа ожидает, что в параметре ДанныеВыбора будет передано то значение, которое должно быть подставлено в поле.

Если СтандартнаяОбработка отключена, а ДанныеВыбора остались равны Неопределено, платформа интерпретирует это как «пользовательский поиск завершен, но ничего не найдено». Именно поэтому появляется системное окно с ошибкой. Такое поведение особенно выражено, если у поля ввода включены свойства История выбора при вводе или Кнопка списка.

Решение №1: Принудительное заполнение данных выбора

Чтобы избежать сообщения об ошибке и корректно восстановить старое значение реквизита, нам нужно явно «подсказать» платформе, что выбор сделан, и этим выбором является текущее значение реквизита (которое еще не успело перезаписаться новым текстом). Посмотрим, как реализовать этот механизм:


&НаКлиенте
Процедура Реквизит1ОкончаниеВводаТекста(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, СтандартнаяОбработка)
    
    // Выполняем проверку введенного текста
    Если Текст = "123" Тогда // Пример условия
        
        // 1. Отменяем стандартный поиск платформы
        СтандартнаяОбработка = Ложь;
        
        // 2. Создаем список значений, который платформа воспримет как результат выбора
        ДанныеВыбора = Новый СписокЗначений;
        
        // 3. Добавляем текущее значение реквизита (то, что было до начала ввода)
        // Если это реквизит объекта, используем Объект.ИмяРеквизита
        ДанныеВыбора.Добавить(Объект.МобильныйТелефон); 
        
        // Теперь платформа увидит, что выбор "состоялся", и ошибка поиска не возникнет
        Сообщить("Введены некорректные данные, значение восстановлено!");
        
    КонецЕсли;
    
КонецПроцедуры

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

Решение №2: Использование события ПриИзменении (классический обход)

Если логика работы ОкончаниеВводаТекста кажется избыточной или продолжает вести себя нестабильно (например, из-за специфических настроек автоподбора), можно прибегнуть к более простому и надежному способу — проверке в событии ПриИзменении. Однако здесь есть нюанс: на момент срабатывания этого события значение в реквизите уже изменено, и нам нужно знать, что там было «до».

Разберем реализацию с использованием переменной модуля формы для хранения старого значения:


&НаКлиенте
Перем ЗначениеДоИзменения; // Переменная для хранения предыдущего состояния

&НаКлиенте
Процедура РеквизитПриАктивизации(Элемент)
    // Запоминаем значение при входе в поле
    ЗначениеДоИзменения = Объект.МобильныйТелефон;
КонецПроцедуры

&НаКлиенте
Процедура РеквизитПриИзменении(Элемент)
    Если Не ПроверкаПрошла(Объект.МобильныйТелефон) Тогда
        // Восстанавливаем из переменной
        Объект.МобильныйТелефон = ЗначениеДоИзменения;
        Сообщить("Ошибка ввода, возвращено старое значение.");
    КонецЕсли;
КонецПроцедуры

Этот метод считается более «безопасным» с точки зрения стабильности платформы, так как он не вмешивается в интерактивные процессы поиска и подбора значений, которые инициирует платформа в событии ОкончаниеВводаТекста.

Почему в одном случае работает, а в другом — нет?

Часто программисты удивляются: «Почему в справочнике Контрагенты код работает, а в справочнике Номенклатура — нет?». Проанализируем возможные причины различий в поведении:

  1. Режим выбора из списка: Если свойство РежимВыбораИзСписка установлено в значение Да, платформа ведет себя гораздо строже к параметру ДанныеВыбора.
  2. Ограничение типа: Если длина введенного текста превышает ограничение длины строкового реквизита, событие может отрабатывать некорректно или прерываться самой платформой еще до выполнения вашего кода.
  3. Серверные вызовы: Обратите внимание на важное примечание в синтакс-помощнике: в обработчике ОкончаниеВводаТекста нельзя использовать серверные методы формы с директивой компиляции &НаСервере. Даже если технически вызов проходит, это нарушает событийную модель и может приводить к «зацикливанию» сообщений об ошибках.
  4. Обновление текста редактирования: Посмотрите на свойство ОбновлениеТекстаРедактирования. Если оно установлено в значение ПриИзмененииЗначения, это может влиять на момент возникновения события завершения ввода.

Рекомендации по выводу сообщений

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

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

← На главную