При разработке и настройке форм в 1С:Предприятии мы часто сталкиваемся с необходимостью форматирования и контроля вводимых данных с помощью масок ввода. Однако иногда маски могут вести себя неожиданно, приводя к искажению данных на форме или даже при их сохранении. В этой статье мы подробно разберем типичную проблему с маской ввода для стандартного реквизита Код справочника и предложим несколько эффективных решений.
Рассмотрим ситуацию, когда у нас есть реквизит объекта Код, для которого мы динамически устанавливаем различные маски ввода, например, "\09999.99", "\99999.99999" или "99999.999999", в зависимости от выбранного значения в поле Тип. Ожидается, что маска будет форматировать ввод, но вместо этого мы наблюдаем, как платформа самостоятельно подставляет лишние символы (например, "0" или "9") и искажает исходный код.
Давайте подробнее проанализируем, как проявляется эта проблема. Пользователи часто описывают следующие симптомы:
Код содержит правильное значение (например, "01234.56"), но на самой форме он отображается некорректно ("00123.45"). Это указывает на проблему с отображением данных на форме, а не с их хранением в базе."09999.99" предполагает определенную структуру, но введенное значение короче, платформа может автоматически дополнять его, например, нулями, что приводит к нежелательному "00500.00" вместо "05000.0".Основная причина такого поведения кроется во взаимодействии нескольких факторов:
Код (или любой другой строковый реквизит) имеет фиксированную длину, платформа 1С автоматически дополняет его пробелами до максимальной длины, если введенное значение короче. Например, если код имеет длину 8 символов, а реквизит задан с фиксированной длиной 11, то к коду будут добавлены 3 пробела в конце.9 в маске 1С означает, что можно вводить любую цифру. Если длина маски больше, чем введенное значение, и реквизит имеет фиксированную длину, он может быть дополнен пробелами, которые затем могут быть интерпретированы маской.0, хотя и не является стандартным символом маски 1С в общепринятом смысле, в контексте наблюдаемой проблемы и других систем может вести себя как обязательная цифра с заполнением нулями при отсутствии ввода. В данном случае, если маска начинается с 0 (или \0 для буквального нуля) и реквизит имеет фиксированную длину, это может приводить к принудительному добавлению лидирующих нулей.\ используется для экранирования специальных символов маски, превращая их в обычные. Например, \0 будет означать буквальный ноль, а \9 – буквальную девятку.Мы предлагаем несколько подходов для решения или обхода проблемы с некорректной работой маски ввода. Разберем каждый из них подробно.
Это наиболее прямолинейное и часто самое эффективное решение, которое позволяет устранить корневую причину – автоматическое дополнение пробелами.
Код.Код, чтобы открыть его свойства.В окне свойств реквизита обратите внимание на свойство Длина. Вероятнее всего, оно установлено в какое-то фиксированное число (например, 11). Вместо этого выберите опцию Переменная. После этого задайте МаксимальнаяДлина, которая будет соответствовать наибольшей возможной длине ваших кодов (например, 12 или 15).
Почему это помогает: Когда длина реквизита установлена как Переменная, платформа не будет автоматически дополнять значение пробелами до максимальной длины. Реквизит будет хранить ровно столько символов, сколько было введено. Таким образом, маска ввода на форме будет применяться только к фактическому значению, без "помех" в виде лишних пробелов.
Важный нюанс: В некоторых случаях пользователи отмечали, что при использовании масок, начинающихся с 0 (например, "09999.99"), решение с переменной длиной работает корректно, а при масках, начинающихся с 9 (например, "99999.99999"), могут оставаться проблемы. Это может быть связано с особенностями внутренней интерпретации символов маски платформой и их взаимодействием с пустыми символами, даже если их нет. Тем не менее, для большинства сценариев изменение длины на "Переменная" решает проблему.
Если по каким-то причинам изменение длины реквизита Код невозможно или не решает проблему полностью, можно использовать обходной путь с созданием вспомогательных реквизитов.
КодФорматированныйДляТипа1 (с нужной маской для Типа 1)КодФорматированныйДляТипа2 (с нужной маской для Типа 2)У этих вспомогательных реквизитов установите свойство Длина как Переменная и задайте соответствующую МаксимальнаяДлина.
Элементы.КодФорматированныйДляТипа1.Маска = "\09999.99";
Элементы.КодФорматированныйДляТипа2.Маска = "\99999.99999";
ПриИзменении поля Тип (или при открытии формы) динамически управляйте видимостью этих вспомогательных полей:
&НаКлиенте
Процедура ТипПриИзменении(Элемент)
Если Объект.Тип = Перечисления.ВидыКода.Тип1 Тогда
Элементы.КодФорматированныйДляТипа1.Видимость = Истина;
Элементы.КодФорматированныйДляТипа2.Видимость = Ложь;
// ... и так далее для других типов
ИначеЕсли Объект.Тип = Перечисления.ВидыКода.Тип2 Тогда
Элементы.КодФорматированныйДляТипа1.Видимость = Ложь;
Элементы.КодФорматированныйДляТипа2.Видимость = Истина;
// ...
КонецЕсли;
КонецПроцедуры
ПередЗаписьюНаСервере или ПриЗаписиНаСервере элемента справочника переносите значение из активного вспомогательного реквизита в основной реквизит Код:
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ПараметрыЗаписи)
Если Объект.Тип = Перечисления.ВидыКода.Тип1 Тогда
Объект.Код = Объект.КодФорматированныйДляТипа1;
ИначеЕсли Объект.Тип = Перечисления.ВидыКода.Тип2 Тогда
Объект.Код = Объект.КодФорматированныйДляТипа2;
КонецЕсли;
КонецПроцедуры
Преимущества: Этот подход дает полный контроль над форматированием и обходит проблемы взаимодействия маски с фиксированной длиной основного реквизита, так как маска применяется к вспомогательным реквизитам с переменной длиной.
Недостатки: Увеличивается количество реквизитов объекта и усложняется логика на форме.
Для полного контроля над вводом и форматированием числовых данных мы можем отказаться от стандартной маски и реализовать логику программно.
Код только для просмотра (свойство ТолькоПросмотр = Истина).Код добавьте кнопку Выбрать или используйте событие НачалоВыбора для поля.Выбрать или НачалоВыбора вызовите функцию для ввода числа или откройте специальную форму для ввода.
Например, для числовых кодов можно использовать ПоказатьВводЧисла:
&НаКлиенте
Процедура КодНачалоВыбора(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь; // Отменяем стандартную обработку
Перем ВведенноеЧисло;
Если ПоказатьВводЧисла(ВведенноеЧисло, "Введите код", , , 10, 2) Тогда // 10 - целая часть, 2 - дробная
// Преобразуем введенное число к нужному формату
// Например, для кода "09999.99" нам нужно 5 цифр до точки и 2 после.
Объект.Код = Формат(ВведенноеЧисло, "ЧЦ=7; ЧДЦ=2; ЧВН=; ЧГ=0");
// ЧЦ=7: общая длина числа (5 целых + точка + 2 дробных)
// ЧДЦ=2: количество знаков после запятой
// ЧВН=: выводить ведущие нули
// ЧГ=0: без группировки разрядов
КонецЕсли;
КонецПроцедуры
Формат(): Для приведения числа к строковому виду с лидирующими нулями и нужной разрядностью всегда используйте функцию Формат(). Она предоставляет гибкие возможности форматирования.
Пример использования Формат() для вывода лидирующих нулей:
// Исходное число
Число = 123.45;
// Форматирование для вывода 5 целых цифр, 2 дробных, с ведущими нулями
ФорматированнаяСтрока = Формат(Число, "ЧЦ=8; ЧДЦ=2; ЧВН=; ЧГ=0");
// Результат: "00123.45"
// Здесь ЧЦ=8 (6 цифр + точка + 2 дробных), ЧВН= (выводить ведущие нули), ЧГ=0 (без группировки)
Подробно про конструктор форматной строки вы можете узнать в документации 1С.
Преимущества: Полный контроль над процессом ввода и форматирования, возможность реализации любой сложной логики.
Недостатки: Требует большего объема программного кода и не использует стандартные возможности масок ввода.
Для эффективного решения подобных проблем мы рекомендуем придерживаться следующих практик:
Объект.Код), со значением, которое отображается на форме (Элементы.Код.Значение). Это поможет выяснить, проблема ли в хранении данных или в их отображении.Длина = Переменная с указанием максимальной длины. Фиксированная длина хороша только для абсолютно стандартных и неизменных по длине данных (например, ИНН, если он всегда 10 или 12 символов).9, #, U, X и экранирование \, поможет избежать многих проблем.СокрЛП() для устранения пробелов, если реквизит имеет фиксированную длину: Если реквизит объекта имеет фиксированную длину, даже если вы программно уберете пробелы с помощью СокрЛП() перед присвоением, платформа может автоматически добавить их снова при записи. Поэтому лучше работать с изменением свойства длины самого реквизита.Решение проблемы с маской ввода для реквизита "Код" часто сводится к правильной настройке свойства Длина самого реквизита. Выбирая Переменная длину, мы уходим от автоматического добавления пробелов, что устраняет многие артефакты при работе маски. Если же этот путь невозможен, всегда можно прибегнуть к вспомогательным реквизитам или полному программному контролю над вводом и форматированием.