Как настроить маску ввода в 1С, чтобы разделители не сохранялись в базе данных и не обрезали строку

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

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

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

Выясним причину проблемы

Рассмотрим ситуацию: нам нужно ввести номер счета длиной 28 символов. Мы задаем маску вида "UUUU UUUU UUUU UUUU UUUU UUUU UUUU". В этой строке 28 знаков для ввода и 6 пробелов. Общая длина строки вместе с разделителями составляет 34 символа. Если наш реквизит в базе данных имеет длину 28, то при попытке записи платформа 1С возьмет первые 28 символов (включая пробелы), а последние 6 значащих цифр или букв будут безвозвратно потеряны.

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

Решение 1: Использование вспомогательного реквизита формы (Рекомендуемый метод)

Проанализируем самый надежный способ, который позволяет полностью разделить визуальное представление и хранение. Суть метода заключается в том, что пользователь работает не напрямую с реквизитом объекта, а со специально созданным строковым реквизитом формы достаточной длины.

Разберем по шагам:

  1. Создадим на форме новый реквизит, назовем его НомерСчетаДляВвода. Тип — Строка, длину укажем с запасом (например, 50 символов), чтобы пробелы маски точно поместились.
  2. Вынесем этот реквизит на форму и в свойствах элемента управления установим нужную маску: UUUU UUUU UUUU UUUU UUUU UUUU UUUU.
  3. Теперь нам нужно обеспечить синхронизацию данных между «чистым» реквизитом объекта (Объект.НомерСчета) и нашим полем ввода.

Рассмотрим программную реализацию в модуле формы:


&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    // При открытии формы заполняем поле ввода данными из базы
    // Здесь можно программно добавить пробелы, если нужно, 
    // но маска сама распределит символы, если в строке нет лишних знаков
    НомерСчетаДляВвода = ТекущийОбъект.НомерСчета;
КонецПроцедуры

&НаКлиенте
Процедура НомерСчетаДляВводаПриИзменении(Элемент)
    // Когда пользователь изменил данные, очищаем их от пробелов и сохраняем в объект
    ЧистоеЗначение = СтрЗаменить(НомерСчетаДляВвода, " ", "");
    Объект.НомерСчета = ЧистоеЗначение;
КонецПроцедуры

Этот метод хорош тем, что в базе данных (Объект.НомерСчета) всегда хранятся только значащие 28 символов без лишнего мусора, а пользователь видит красивую группировку при вводе.

Решение 2: Форматирование вывода в списках и отчетах

После того как мы сохранили «чистые» данные, возникает вопрос: как показать их красиво в динамическом списке (например, в списке банковских счетов), если маска там не работает так же, как в поле ввода? Если мы просто выведем колонку, пользователь увидит сплошной текст HN54J5H44HJ5645L9RGG3SOR.

Проанализируем ситуацию и воспользуемся возможностями языка запросов 1С. Мы можем программно «нарезать» строку на части и соединить их пробелами прямо в запросе динамического списка.

Посмотрим на пример запроса:


ВЫБРАТЬ
    БанковскиеСчета.Ссылка,
    БанковскиеСчета.Код,
    ПОДСТРОКА(БанковскиеСчета.НомерСчета, 1, 4) + " " + 
    ПОДСТРОКА(БанковскиеСчета.НомерСчета, 5, 4) + " " + 
    ПОДСТРОКА(БанковскиеСчета.НомерСчета, 9, 4) + " " + 
    ПОДСТРОКА(БанковскиеСчета.НомерСчета, 13, 4) + " " + 
    ПОДСТРОКА(БанковскиеСчета.НомерСчета, 17, 4) + " " + 
    ПОДСТРОКА(БанковскиеСчета.НомерСчета, 21, 4) + " " + 
    ПОДСТРОКА(БанковскиеСчета.НомерСчета, 25, 4) КАК НомерСчетаПредставление
ИЗ
    Справочник.БанковскиеСчета КАК БанковскиеСчета

Использование функции ПОДСТРОКА позволяет нам сформировать визуально приятный вид данных в любом списке или отчете, не меняя структуру хранения в БД. Это считается «лучшей практикой» (best practice) при разработке на платформе 1С, так как хранение разделителей в базе данных усложняет поиск, фильтрацию и интеграцию с внешними системами.

Решение 3: Очистка данных в событии ПриИзменении без доп. реквизитов

Если вы не хотите создавать дополнительные реквизиты формы, можно попробовать работать напрямую с реквизитом объекта, но нужно быть крайне осторожными с длиной. Чтобы это сработало, длина реквизита в метаданных должна включать длину маски с пробелами. То есть, если счет 28 символов, а с пробелами — 34, то длина реквизита в конфигураторе должна быть 34.

Однако, если вы хотите хранить 28, но использовать маску в том же поле, платформа обрежет данные до того, как сработает код записи. Единственный вариант здесь — использовать событие ПриИзменении на клиенте для немедленной очистки:


&НаКлиенте
Процедура НомерСчетаПриИзменении(Элемент)
    // Очищаем введенное значение от пробелов сразу в поле ввода
    // Но внимание: маска может сразу же вернуть их назад при потере фокуса
    Объект.НомерСчета = СтрЗаменить(Объект.НомерСчета, " ", "");
КонецПроцедуры

Недостаток этого метода: Пользователь может увидеть «скачок» текста — он ввел данные с пробелами, а после нажатия Enter пробелы исчезли (или маска наложила их снова, но уже на сдвинутый текст). Поэтому Решение 1 с разделением реквизитов является более стабильным.

Дополнительные советы по работе с масками

Рассмотрим несколько профессиональных хитростей, которые помогут сделать интерфейс еще более качественным:

Подведем итог: При работе с масками ввода в 1С всегда помните — то, что вы видите в поле с маской, является фактическим значением строки. Чтобы сохранить данные в «чистом» виде, используйте связку «Реквизит формы (с маской) + Реквизит объекта (без маски)» и очищайте строку программно с помощью СтрЗаменить.

← На главную