Как предотвратить ввод буквенно-цифровых символов в числовое поле 1С?

Программист Управленческий учет Торговля и дистрибуция
← На главную

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

Проблема автоматического маскирования платформы

Прежде всего, разберем, почему стандартные события ПриНачалеРедактирования или ПередНачаломИзменения не помогают. Дело в том, что когда данные попадают в поле (через буфер обмена или эмуляцию клавиатуры сканером), платформа выполняет приведение типов до того, как управление передается в большинство обработчиков событий. К моменту срабатывания ПриИзменении в реквизите уже лежит «очищенное» число. Проанализируем ситуацию и выработаем комплекс мер для решения этой задачи.

Способ 1. Использование события ПриИзмененииТекстаРедактирования

В управляемых формах у элементов типа «Поле ввода» есть специализированное событие ПриИзмененииТекстаРедактирования. В отличие от стандартного ПриИзменении, оно срабатывает в процессе ввода текста пользователем, еще до того, как значение будет окончательно записано в связанный реквизит и типизировано. Рассмотрим, как реализовать проверку в этом обработчике.

При вводе каждого символа или вставке строки мы можем перехватить параметр Текст и проверить его на наличие букв. Если в тексте обнаружены запрещенные символы, мы можем выдать предупреждение или программно очистить поле. Посмотрим на пример кода:


&НаКлиенте
Процедура КоличествоПриИзмененииТекстаРедактирования(Элемент, Текст, СтандартнаяОбработка)
    
    // Используем регулярное выражение или перебор для поиска букв
    ДопустимыеСимволы = "0123456789.,"; // Включая разделители дробной части
    Для Индекс = 1 По СтрДлина(Текст) Цикл
        Символ = Сред(Текст, Индекс, 1);
        Если Найти(ДопустимыеСимволы, Символ) = 0 Тогда
            Сообщить("Внимание! Обнаружены недопустимые символы в поле количества.");
            Текст = ""; // Очищаем вводимый текст
            Возврат;
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

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

Способ 2. Перевод торгового оборудования в режим внешнего события

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

Выясним причину, по которой стоит использовать драйвер:

  1. Данные передаются напрямую в платформу как ВнешнееСобытие.
  2. Фокус ввода в этот момент не имеет значения — данные попадут в специальный обработчик формы, а не в поле Количество.
  3. Исключается риск «порчи» данных механизмом приведения типов 1С.

Для реализации этого метода необходимо перенастроить сканер в режим USB-COM (обычно это делается путем сканирования специального служебного штрихкода из инструкции к устройству). После этого в 1С подключается соответствующий драйвер через Библиотеку подключаемого оборудования (БПО). В коде формы документа это будет выглядеть следующим образом:


&НаКлиенте
Процедура ВнешнееСобытие(Источник, Событие, Данные)
    
    Если Источник = "СканерШтрихкода" Тогда
        // Обрабатываем штрихкод программно, вне зависимости от того, где стоит курсор
        ОбработатьШтрихкод(Данные);
    КонецЕсли;
    
КонецПроцедуры

Способ 3. Использование префиксов и «формы перехвата»

Если нет возможности перевести сканер в режим COM-порта, можно воспользоваться методом префиксов. Большинство сканеров позволяют запрограммировать «префикс» — клавишу, которая будет нажиматься автоматически перед передачей кода. Обычно используют F7.

Разберем по шагам, как это работает:

  1. Сканер считывает код AD9281Z....
  2. Сначала он посылает в систему нажатие F7.
  3. В 1С на горячую клавишу F7 назначено действие «Открыть окно поиска».
  4. Открывается модальное окно или специализированное поле ввода.
  5. Остальные символы кода попадают уже в это окно, которое умеет правильно обрабатывать строки.

Однако здесь есть нюанс, упомянутый опытными разработчиками: на современных быстрых ПК и новых версиях платформы окно может открываться медленнее, чем сканер передает символы. В таком случае первые несколько букв все равно могут «пролететь» в поле Количество. Чтобы этого избежать, в настройках сканера рекомендуется выставлять Inter-character delay (задержку между символами) около 10–20 миллисекунд.

Способ 4. Программная «Защита от дурака» через лимиты

Проанализируем ситуацию: даже если нам не удалось предотвратить ввод, мы обязаны предотвратить пробитие чека. Это реализуется на уровне бизнес-логики в модуле объекта или в обработчике перед записью документа. Рассмотрим пример установки ограничений:


&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    
    Для Каждого СтрокаТЧ Из ТекущийОбъект.Товары Цикл
        // Проверяем аномальное количество
        Если СтрокаТЧ.Количество > 100 Тогда 
            // 100 - это условный порог, который редко превышается в рознице
            Сообщение = Новый СообщениеПользователю;
            Сообщение.Текст = "Количество в строке " + СтрокаТЧ.НомерСтроки + " подозрительно большое!";
            Сообщение.Поле = "Объект.Товары[" + (СтрокаТЧ.НомерСтроки - 1) + "].Количество";
            Сообщение.Сообщить();
            // Можно либо просто предупредить, либо установить Отказ = Истина
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

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

Способ 5. Использование строкового реквизита на форме

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

Алгоритм действий:

  1. Создаем на форме строковый элемент управления.
  2. В событии ПриИзменении этого элемента проверяем строку.
  3. Если в строке есть буквы — выдаем ошибку.
  4. Если только цифры — преобразуем функцией Число() и записываем в истинный числовой реквизит объекта.

Это гарантирует, что платформа не сделает «молчаливое» преобразование, так как для строкового поля любой ввод является валидным, и вы получите данные в первозданном виде (включая буквы ADZ...).

Резюме

Мы проанализировали несколько методов борьбы с автоматическим преобразованием типов. Самым надежным решением является использование драйверов торгового оборудования и режима ВнешнееСобытие. Вторым по эффективности методом можно считать использование события ПриИзмененииТекстаРедактирования для оперативного контроля ввода. Комбинация этих методов вместе с установкой логических лимитов на количество и сумму в документе позволит полностью исключить риск пробития ошибочных чеков из-за случайного сканирования дисконтных карт.

← На главную