Как реализовать посимвольный контроль ввода в текстовом поле на управляемой форме 1С?

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

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

Метод 1. Анализ через событие «ИзменениеТекстаРедактирования»

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

Для реализации нам понадобятся два реквизита на форме: основной текстовый реквизит (связанный с полем ввода) и скрытый вспомогательный реквизит для хранения последнего корректного значения. Назовем их ТекстПоля и ПоследнееЗначение.

Проанализируем программный код обработчика:


&НаКлиенте
Процедура ТекстПоляИзменениеТекстаРедактирования(Элемент, Текст, СтандартнаяОбработка)
    
    // Текст — это то, что юзер ПЫТАЕТСЯ ввести прямо сейчас
    // Напишем условие: разрешаем только цифры
    ДопустимыеСимволы = "0123456789";
    
    Для Индекс = 1 По СтрДлина(Текст) Цикл
        Символ = Сред(Текст, Индекс, 1);
        Если Найти(ДопустимыеСимволы, Символ) = 0 Тогда
            // Нашли недопустимый символ! Отменяем ввод.
            // Присваиваем элементу старое значение
            Элемент.ТекстРедактирования = ЭтаФорма.ПоследнееЗначение;
            
            // Важно: если мы просто поменяем текст, курсор улетит в начало.
            // Установим курсор в конец или на позицию ошибки
            Элемент.УстановитьГраницыВыделения(СтрДлина(ЭтаФорма.ПоследнееЗначение) + 1);
            Возврат;
        КонецЕсли;
    КонецЦикла;
    
    // Если всё хорошо — запоминаем текущее значение как последнее корректное
    ЭтаФорма.ПоследнееЗначение = Текст;

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

Важный нюанс: метод УстановитьГраницыВыделения критически важен. Без него работа пользователя превратится в мучение, так как после каждой блокировки символа каретка будет сбрасываться. Однако стоит учитывать, что при работе через веб-клиент или при медленном сетевом соединении пользователь все равно может заметить кратковременное появление «запрещенного» символа перед его исчезновением.

Метод 2. Использование «Поля HTML-документа» для жесткого контроля

Если нам требуется «железный» запрет, при котором запрещенный символ даже не появится в поле, стандартные средства 1С бессильны. Здесь на помощь приходит ПолеHTMLДокумента. Этот объект позволяет использовать мощь JavaScript непосредственно внутри формы 1С. Для низкоуровневого контроля нажатия клавиш также можно использовать внешнюю компоненту для перехвата ввода с клавиатуры в 1С.

Разберем по шагам, как это работает. Мы создаем на форме поле HTML и загружаем в него простую страницу с тегом input. Внутри HTML мы прописываем скрипт, который перехватывает событие нажатия клавиши (onkeypress). Если символ нам не нравится, мы вызываем event.preventDefault(), и символ просто не печатается.

Рассмотрим пример формирования такого поля:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // Генерируем HTML-код с инпутом и скриптом
    ТекстHTML = 
    "<html>
    |<body style='margin:0; padding:0; overflow:hidden;'>
    |   <input type='text' id='myInput' style='width:100%; box-sizing:border-box;'>
    |   <script>
    |       document.getElementById('myInput').onkeypress = function(e) {
    |           var charCode = (e.which) ? e.which : e.keyCode;
    |           // Разрешаем только цифры (коды 48-57)
    |           if (charCode > 31 && (charCode < 48 || charCode > 57)) {
    |               e.preventDefault();
    |               return false;
    |           }
    |       };
    |       // Передача данных в 1С при изменении
    |       document.getElementById('myInput').oninput = function() {
    |           window.location.href = 'v8:' + this.value;
    |       };
    |   </script>
    |</body>
    |</html>";
    ЭтаФорма.ПолеHTML = ТекстHTML;
КонецПроцедуры

Для получения данных обратно в 1С мы используем событие ПриНажатии (или обработку навигации) у поля HTML. Это самый производительный и «чистый» с точки зрения пользователя способ, так как он полностью имитирует поведение нативных приложений.

Метод 3. Регулярные выражения для сложной валидации

В сообщениях форума упоминалась задача: «в первом разряде только 0..2, во втором 0..5, если первый равен 1». Написание бесконечных цепочек Если...ИначеЕсли делает код нечитаемым. Проанализируем ситуацию и поймем, что здесь лучше всего применить регулярные выражения (RegExp).

Хотя в языке 1С нет встроенного объекта RegExp (до последних версий 8.3.24+), мы можем использовать COM-объект VBScript.RegExp на Windows-клиентах. Это позволит нам проверять строку целиком на каждом шаге ввода.


&НаКлиенте
Функция ТекстСоответствуетШаблону(Текст)
    РегВыражение = Новый COMОбъект("VBScript.RegExp");
    // Шаблон: первая цифра 0-2, вторая 0-5 (если всего 2 цифры)
    // Это лишь пример, паттерн можно настроить любой сложности
    РегВыражение.Pattern = "^[0-2][0-5]?$"; 
    РегВыражение.IgnoreCase = Истина;
    РегВыражение.Global = Ложь;
    Возврат РегВыражение.Test(Текст);
КонецФункции

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

Метод 4. UX-подход: «Мягкая» валидация

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

Рассмотрим альтернативный, современный подход — визуальную индикацию ошибки:

  1. В событии ПриИзменении проверяем введенное значение.
  2. Если значение некорректно, меняем свойство поля ЦветФонаПоля на бледно-красный.
  3. Используем метод ОбщегоНазначенияКлиент.СообщитьПользователю, привязывая сообщение к конкретному полю ввода. Это выведет всплывающую подсказку прямо у поля.
  4. Блокируем кнопку «Записать» или «ОК» на форме до тех пор, пока поле не станет валидным.

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

Метод 5. Разделение на несколько полей

Если структура вводимых данных жестко определена (например, код из двух частей по 2 символа), иногда проще и надежнее всего будет разбить одно текстовое поле на несколько маленьких. Для каждого маленького поля можно установить:

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

Резюме

Мы рассмотрели различные варианты реализации контроля ввода. Если вам нужна максимальная строгость и вы работаете в веб-интерфейсе, выбирайте ПолеHTMLДокумента. Если нужно быстрое решение для тонкого клиента — используйте ИзменениеТекстаРедактирования с обязательным вызовом УстановитьГраницыВыделения. Но в большинстве случаев лучшим выбором будет комбинированный подход: использование регулярных выражений для проверки и наглядная цветовая индикация ошибок для пользователя.

← На главную