При проектировании пользовательских интерфейсов в 1С нередко возникает задача ограничить ввод числовых данных определенными рамками. Например, требуется, чтобы пользователь вводил положительное число не менее 10, у которого последняя цифра всегда должна оставаться нулем (значения 10, 20, 150, 4300 и так далее). Первое интуитивное желание разработчика в такой ситуации — настроить свойство Маска у элемента формы, задав шаблон вроде 99990. Однако на практике этот подход не дает желаемого результата. Разберем подробно, почему механизм масок не предназначен для таких сценариев и какими надежными способами можно реализовать требуемое поведение.
Проанализируем архитектурные ограничения платформы 1С:Предприятие, из-за которых настройка маски оказывается неэффективной для решения поставленной задачи:
Число, свойство Маска игнорируется платформой. За визуальное представление числовых значений отвечают свойства Формат и ФорматРедактирования, но они оперируют разделителями групп, знаками дробной части и лидирующими нулями, а не фиксированием произвольных цифр в конкретных разрядах.9999\0 требует обязательного заполнения всех позиций шаблона. Это означает, что пользователь не сможет естественным образом ввести короткое число (например, 10 или 50) без предварительного заполнения ведущих позиций пробелами или нулями.МинимальноеЗначение на уровне элемента формы способно ограничить нижний порог (например, не позволить ввести число меньше 10), однако оно не умеет контролировать шаг изменения и кратность значения.Таким образом, попытка решить задачу через стандартные декларативные свойства элемента формы заводит в тупик. Перейдем к разбору практических вариантов реализации через программный код и интерфейсные механизмы.
Рассмотрим наиболее простой и распространенный подход — программную нормализацию значения сразу после того, как пользователь завершил ввод и покинул поле. Для этого создадим обработчик события ПриИзменении на клиенте.
В коде обработчика выполним математическое округление или отсечение до десятков, а также проконтролируем минимальную границу:
&НаКлиенте
Процедура ЧисловоеПолеПриИзменении(Элемент)
// Проверяем минимальный порог
Если Объект.ЧисловоеПоле < 10 Тогда
Объект.ЧисловоеПоле = 10;
Возврат;
КонецЕсли;
// Принудительно обнуляем единицы, делая число кратным 10
Объект.ЧисловоеПоле = Цел(Объект.ЧисловоеПоле / 10) * 10;
КонецПроцедуры
Если пользователь введет 15 или 19, значение автоматически преобразуется в 10. Если требуется математическое округление до ближайшего десятка (например, чтобы 15 превращалось в 20), вместо функции Цел можно использовать функцию Окр:
&НаКлиенте
Процедура ЧисловоеПолеПриИзменении(Элемент)
Если Объект.ЧисловоеПоле < 10 Тогда
Объект.ЧисловоеПоле = 10;
Иначе
Объект.ЧисловоеПоле = Окр(Объект.ЧисловоеПоле / 10, 0) * 10;
КонецЕсли;
КонецПроцедуры
Посмотрим на более удобный для пользователя вариант интерфейса, когда число не только вводится вручную, но и может изменяться стрелками вверх и вниз. В свойствах числового поля ввода установим признак КнопкаРегулирования = Истина и назначим обработчик события Регулирование.
Разберем по шагам логику обработчика: мы перехватываем стандартное изменение (которое по умолчанию равно 1), отключаем его и прибавляем или вычитаем ровно 10:
&НаКлиенте
Процедура ЧисловоеПолеРегулирование(Элемент, Направление, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Шаг = 10;
НовоеЗначение = Объект.ЧисловоеПоле + (Направление * Шаг);
// Защита от установки значения менее 10
Если НовоеЗначение < 10 Тогда
НовоеЗначение = 10;
КонецЕсли;
Объект.ЧисловоеПоле = НовоеЗначение;
КонецПроцедуры
Параметр Направление принимает значение 1 при нажатии стрелки вверх и -1 при нажатии стрелки вниз. Данный способ отлично дополняет проверку в событии ПриИзменении, гарантируя комфортный пошаговый ввод.
Рассмотрим ситуацию, когда пользователь набирает число вручную и мы хотим подставить завершающий ноль прямо в процессе фиксации текста, еще до того, как значение запишется в реквизит формы. Для этого воспользуемся событием ОкончаниеВводаТекста.
&НаКлиенте
Процедура ЧисловоеПолеОкончаниеВводаТекста(Элемент, Текст, Значение, СтандартнаяОбработка)
ОчищенныйТекст = СокрЛП(Текст);
Если ПустаяСтрока(ОчищенныйТекст) Тогда
Возврат;
КонецЕсли;
ЧисловойТип = Новый ОписаниеТипов("Число");
ВведенноеЧисло = ЧисловойТип.ПривестиЗначение(ОчищенныйТекст);
// Если последняя цифра не 0, дописываем ноль или принудительно выравниваем
Если ВведенноеЧисло < 10 Тогда
Значение = 10;
Иначе
Значение = Цел(ВведенноеЧисло / 10) * 10;
КонецЕсли;
СтандартнаяОбработка = Ложь;
КонецПроцедуры
Установка СтандартнаяОбработка = Ложь сообщает платформе, что расчетное число из переменной Значение необходимо сразу поместить в поле без стандартного парсинга исходной строки.
Проанализируем альтернативное решение, исключающее ошибки ввода на уровне психологии восприятия интерфейса. Если последняя цифра — всегда ноль, мы можем избавить пользователя от необходимости вообще ее набирать.
ТекстПослеПоляВвода) со значением 0 либо размещаем рядом статическую надпись.При таком подходе пользователь вводит, например, 45, но в интерфейсе наглядно видит, что итоговое значение формируется как 450. Это полностью устраняет возможность некорректного ввода без единой строчки валидационного кода.
Клиентские перехваты обеспечивают удобство, но для надежности учета критически важно проверять данные перед записью объекта в базу данных. Для этого в модуле объекта или формы задействуем обработчик ОбработкаПроверкиЗаполнения.
Проверим кратность числа десяти при помощи оператора остатка от деления %:
&НаСервере
Процедура ОбработкаПроверкиЗаполненияНаСервере(Отказ, ПроверяемыеРеквизиты)
Если Объект.ЧисловоеПоле < 10 Или (Объект.ЧисловоеПоле % 10 <> 0) Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Значение поля должно быть не менее 10 и кратно 10!";
Сообщение.Поле = "Объект.ЧисловоеПоле";
Сообщение.УстановитьДанные(ЭтотОбъект);
Сообщение.Сообщить();
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Использование связки клиентского события ПриИзменении (для автоматической коррекции) и серверной валидации в ОбработкаПроверкиЗаполнения гарантирует, что в информационной базе всегда будут храниться корректные данные, соответствующие бизнес-правилам конфигурации.