При разработке пользовательских интерфейсов в 1С, таких как собственный калькулятор или поле для ввода математических выражений, часто возникает задача ограничить набор доступных символов: разрешить пользователю вводить только цифры и знаки арифметических операций (сложение, вычитание, умножение, деление), запретив буквы, пробелы и прочие знаки. Разберем особенности работы платформы, выясним ограничения стандартной маски и рассмотрим практические способы решения этой задачи в управляемых формах.
Свойство Маска у элементов формы предназначено исключительно для структурированных строк строго фиксированной длины (например, ИНН, СНИЛС, серии и номера паспорта, телефонные номера). В стандартном синтаксисе масок 1С спецсимвол # разрешает ввод цифры, знака плюс, знака минус или пробела, однако:
*) и деления (/).#.Таким образом, реализовать произвольный калькулятор исключительно средствами настройки свойства Маска невозможно. Для решения задачи необходимо использовать программную обработку событий поля ввода.
Рассмотрим наиболее стабильный подход для управляемых форм. Вместо фильтрации «на лету» при каждом нажатии клавиши (что может сбивать позицию курсора при программной замене текста), мы позволяем пользователю ввести строку целиком с клавиатуры, а затем выполняем очистку и проверку в событии ПриИзменении или ОкончаниеВводаТекста.
Посмотрим на пример функции, которая оставляет в строке только разрешенные символы (цифры от 0 до 9 и знаки +, -, *, /, .):
&НаКлиенте
Функция ОчиститьНедопустимыеСимволы(Знач ИсходныйТекст)
РазрешенныеСимволы = "0123456789+-*/.";
ОчищенныйТекст = "";
Для Индекс = 1 По СтрДлина(ИсходныйТекст) Цикл
Символ = Сред(ИсходныйТекст, Индекс, 1);
Если СтрНайти(РазрешенныеСимволы, Символ) > 0 Тогда
ОчищенныйТекст = ОчищенныйТекст + Символ;
КонецЕсли;
КонецЦикла;
Возврат ОчищенныйТекст;
КонецФункции
&НаКлиенте
Процедура ПолеВыражениеПриИзменении(Элемент)
Объект.Выражение = ОчиститьНедопустимыеСимволы(Объект.Выражение);
КонецПроцедуры
Если требуется запрещать ввод некорректных символов в реальном времени, задействуем обработчик события элемента формы ИзменениеТекстаРедактирования. В этом событии параметр Текст содержит текущее значение, введенное пользователем.
Разберем по шагам логику обработки:
Текст.Текст очищенным значением.
&НаКлиенте
Процедура ПолеВыражениеИзменениеТекстаРедактирования(Элемент, Текст, ТекстАвтоПодбора, СтандартнаяОбработка)
ОчищеннаяСтрока = ОчиститьНедопустимыеСимволы(Текст);
Если Текст <> ОчищеннаяСтрока Тогда
Текст = ОчищеннаяСтрока;
КонецЕсли;
КонецПроцедуры
Важно: при динамической замене текста в процессе ввода каретка (курсор) может перемещаться в конец строки. Если пользователь попытается отредактировать середину выражения, это может вызвать неудобство, поэтому данный метод чаще комбинируют с экранными кнопками или валидацией по завершении ввода.
После того как строка очищена от недопустимых символов и проверена, нам необходимо рассчитать результат по нажатию кнопки «Рассчитать». Проанализируем два основных метода расчета:
Вычислить(): платформа 1С умеет выполнять расчет строковых математических выражений. Так как строка предварительно прошла строгую фильтрацию и содержит только цифры и знаки операций, передача ее в функцию безопасна. Для перехвата ошибок (например, деления на ноль или некорректного синтаксиса знаков подряд) используем конструкцию Попытка ... Исключение.СтрНайти, Сред, Лев, Прав. Этот способ требует большего объема кода, но позволяет детально управлять приоритетом операций, поддержкой скобок и выдавать пользователю понятные сообщения об ошибках в конкретных позициях строки.Посмотрим на пример обработчика кнопки расчета с использованием функции Вычислить():
&НаКлиенте
Процедура КомандаРассчитать(Команда)
СтрокаВыражения = ОчиститьНедопустимыеСимволы(Объект.Выражение);
Если ПустаяСтрока(СтрокаВыражения) Тогда
Возврат;
КонецЕсли;
Попытка
Результат = Вычислить(СтрокаВыражения);
Объект.Результат = Результат;
Исключение
ПоказатьПредупреждение(, "Ошибка в математическом выражении. Проверьте правильность расстановки знаков.");
КонецПопытки;
КонецПроцедуры
Если требуется полностью исключить возможность ввода некорректных данных и сделать интерфейс интуитивным:
ТолькоПросмотр = Истина для поля отображения.onkeydown и oninput без задержек клиент-серверного взаимодействия и с полным контролем положения курсора.