Как ограничить ввод текста и реализовать пользовательскую клавиатуру для поля ссылочного типа в 1С?

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

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

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

Ограничение ввода символов в поле ссылочного типа

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

  1. Анализируем стандартные возможности:

    Первое, что приходит на ум, это использование свойства Маска у элемента формы. Однако, как выясняется на практике, свойство Маска предназначено в первую очередь для строковых полей и в большинстве случаев не работает корректно или вообще не применяется к полям ссылочного типа. Даже если программно установить маску, ошибок не возникает, но желаемого эффекта ограничения ввода не происходит.

  2. Применяем обходной путь: Добавление типа Строка к реквизиту формы

    Для того чтобы получить возможность программно влиять на вводимый текст, нам необходимо, чтобы поле формы воспринимало вводимые символы как строковые данные. Этого можно добиться, если реквизит, на который ссылается поле формы, помимо ссылочного типа (например, СправочникСсылка.Контрагенты), будет также иметь тип Строка.

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

  3. Используем событие ИзменениеТекстаРедактирования для фильтрации ввода

    После того как наш реквизит формы сможет принимать текстовые значения (благодаря добавлению типа Строка), мы можем перехватывать каждый символ, вводимый пользователем, и фильтровать его. Для этого нам понадобится обработчик события ИзменениеТекстаРедактирования элемента формы. Этот обработчик срабатывает при любом изменении текста в поле ввода.

    Рассмотрим подробнее шаги и пример кода:

    1. Перехватываем событие: Привязываем процедуру к событию ИзменениеТекстаРедактирования для вашего поля формы.

      
      &НаКлиенте
      Процедура ПолеИзменениеТекстаРедактирования(Элемент, Текст, СтандартнаяОбработка)
          // ... ваш код обработки
      КонецПроцедуры
      
    2. Сохраняем позицию курсора: Важно запомнить текущую позицию курсора, чтобы после программного изменения текста он не "скакал", а оставался на ожидаемом месте.

      
      Перем ПозицияКурсора;
      Элемент.ПолучитьГраницыВыделения(,,,ПозицияКурсора); // Запоминаем позицию курсора
      
    3. Отключаем автоматическое обновление: Перед программным изменением текста необходимо временно отключить автоматическое обновление элемента, чтобы избежать его мерцания или некорректного поведения.

      
      Элемент.ОбновлениеТекстаРедактирования = ОбновлениеТекстаРедактирования.НеИспользовать; // Отключаем автообновление поля
      
    4. Выполняем фильтрацию текста: В этом месте мы вызываем нашу пользовательскую функцию, которая будет принимать введенный текст, удалять из него запрещенные символы и возвращать отфильтрованную строку. Результат присваиваем свойству Представление нашего объекта (или напрямую свойству поля, если оно строкового типа).

      Объект.Представление = Исправить(Текст); // Вот тут меняем вводимый текст

      Давайте создадим пример функции Исправить, которая будет оставлять только английские буквы и цифры:

      
      &НаКлиенте
      Функция Исправить(Знач Текстовка)
          Проверено = "";
          Для Каждого Символ Из СтрРазделить(Текстовка, "", Ложь) Цикл
              Если (КодСимвола(Символ) >= КодСимвола("a") И КодСимвола(Символ) <= КодСимвола("z")) ИЛИ
                 (КодСимвола(Символ) >= КодСимвола("A") И КодСимвола(Символ) <= КодСимвола("Z")) ИЛИ
                 (КодСимвола(Символ) >= КодСимвола("0") И КодСимвола(Символ) <= КодСимвола("9")) Тогда
                  Проверено = Проверено + Символ;
              КонецЕсли;
          КонецЦикла;
          Возврат Проверено;
      КонецФункции
      

      В этой функции мы перебираем каждый символ входной строки и добавляем его к результату, только если он является английской буквой (в любом регистре) или цифрой. Пробелы, знаки препинания и другие символы будут отброшены.

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

      
      Элемент.ОбновлениеТекстаРедактирования = ОбновлениеТекстаРедактирования.Авто; // Включаем обратно автообновление поля
      ОбновитьОтображениеДанных(Элемент); // Обновим отображение измененного значения
      
    6. Восстанавливаем позицию курсора: Убедимся, что курсор находится в допустимых границах новой строки и восстанавливаем его позицию.

      
      ПозицияКурсора = Мин(ПозицияКурсора, СтрДлина(Объект.Представление) + 1); // Позиция курсора должна быть от 1 до 1+Длина текста
      Элемент.УстановитьГраницыВыделения(ПозицияКурсора, ПозицияКурсора); // Снимаем выделение
      

    Таким образом, полный код процедуры будет выглядеть следующим образом:

    
    &НаКлиенте
    Процедура ПолеИзменениеТекстаРедактирования(Элемент, Текст, СтандартнаяОбработка)
        Перем ПозицияКурсора;
        Элемент.ПолучитьГраницыВыделения(,,,ПозицияКурсора); // Запоминаем позицию курсора
    
        Элемент.ОбновлениеТекстаРедактирования = ОбновлениеТекстаРедактирования.НеИспользовать; // Отключаем автообновление поля
    
        Объект.Представление = Исправить(Текст); // Вот тут меняем вводимый текст, вызывая нашу функцию фильтрации
    
        Элемент.ОбновлениеТекстаРедактирования = ОбновлениеТекстаРедактирования.Авто; // Включаем обратно автообновление поля
        ОбновитьОтображениеДанных(Элемент); // Обновим отображение измененного значения
    
        ПозицияКурсора = Мин(ПозицияКурсора, СтрДлина(Объект.Представление) + 1); // Позиция курсора должна быть от 1 до 1+Длина текста
        Элемент.УстановитьГраницыВыделения(ПозицияКурсора, ПозицияКурсора); // Снимаем выделение
    КонецПроцедуры
    
    &НаКлиенте
    Функция Исправить(Знач Текстовка)
        Проверено = "";
        Для Каждого Символ Из СтрРазделить(Текстовка, "", Ложь) Цикл
            Если (КодСимвола(Символ) >= КодСимвола("a") И КодСимвола(Символ) <= КодСимвола("z")) ИЛИ
               (КодСимвола(Символ) >= КодСимвола("A") И КодСимвола(Символ) <= КодСимвола("Z")) ИЛИ
               (КодСимвола(Символ) >= КодСимвола("0") И КодСимвола(Символ) <= КодСимвола("9")) Тогда
                Проверено = Проверено + Символ;
            КонецЕсли;
        КонецЦикла;
        Возврат Проверено;
    КонецФункции
    

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

Реализация пользовательской клавиатуры для поля ссылочного типа

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

  1. Ограничения стандартного механизма поиска:

    Критически важно понимать, что стандартный механизм быстрого поиска по строке в поле ссылочного типа работает интерактивно с вводом с обычной клавиатуры. Программное присвоение текстового значения свойству ТекстРедактирования или Представление поля не запустит этот интерактивный поиск. Это означает, что прямо "ввести" текст, который заставит 1С искать по нему, как при ручном наборе, скорее всего, не получится.

  2. Рекомендуемое решение: Собственная форма подбора

    Наиболее надежным и гибким способом реализации пользовательской клавиатуры или любого другого нестандартного механизма ввода для поля ссылочного типа является создание отдельной (пользовательской) формы подбора. Эта форма будет служить вашим кастомным интерфейсом ввода.

    1. Создаем свою форму подбора:

      Разработайте отдельную форму (например, для обработки или отчета), на которой разместите необходимые элементы управления: кнопки с цифрами (картинками), поле для отображения текущего ввода и, возможно, кнопку "ОК" или "Найти".

      В этой форме реализуйте логику:

      • При нажатии на кнопку с цифрой, добавляйте эту цифру к внутренней строковой переменной формы.
      • Отображайте эту строку в текстовом поле на вашей форме.
      • Когда пользователь закончит ввод (например, нажмет "ОК"), используйте сформированную строку для программного поиска нужного элемента справочника (например, Справочники.ВашСправочник.НайтиПоНаименованию(ВведеннаяСтрока) или НайтиПоКоду()).
      • Если элемент найден, передайте его как результат закрытия формы.
      
      // Пример функции поиска в вашей форме подбора
      &НаКлиенте
      Функция НайтиЭлементПоВведеннойСтроке(ВведеннаяСтрока)
          // Можно добавить более сложную логику, если наименование не уникально
          // или нужно искать по нескольким реквизитам.
          // Если справочник большой, возможно, потребуется поиск на сервере
          // с учетом производительности.
          НайденныйЭлемент = Справочники.Контрагенты.НайтиПоНаименованию(ВведеннаяСтрока);
          Возврат НайденныйЭлемент;
      КонецФункции
      
      // В обработчике кнопки "ОК" на вашей форме подбора:
      &НаКлиенте
      Процедура КнопкаОКНажатие(Команда)
          // Предположим, что ТекущийВвод это реквизит формы типа Строка,
          // который хранит введенные цифры, например "12".
          ВыбранныйЭлемент = НайтиЭлементПоВведеннойСтроке(ТекущийВвод);
          Если ВыбранныйЭлемент Тогда
              ЭтаФорма.Закрыть(ВыбранныйЭлемент); // Возвращаем найденную ссылку
          Иначе
              ПоказатьПредупреждение(, "Элемент с таким наименованием не найден!");
          КонецЕсли;
      КонецПроцедуры
      
    2. Вызываем свою форму подбора из основного поля:

      Чтобы вызвать вашу кастомную форму подбора вместо стандартного окна выбора справочника, используйте событие НачалоВыбора для поля ссылочного типа на вашей основной форме.

      
      &НаКлиенте
      Процедура ПолеНачалоВыбора(Элемент, СтандартнаяОбработка)
          СтандартнаяОбработка = Ложь; // Отключаем стандартное поведение выбора
      
          // Параметры для открытия вашей формы подбора, если необходимо
          // Например, передать тип справочника, для которого нужен подбор
          Параметры = Новый Структура;
          Параметры.Вставить("ТипЗначенияПоля", Элемент.ТипЗначения);
      
          // Открываем вашу форму подбора
          // Можно использовать ОткрытьФормуМодально для синхронного получения результата
          // или ОткрытьФорму и обрабатывать результат в ОбработкаВыбора
          ФормаПодбора = ОткрытьФорму("ВашаОбработка.Форма.ФормаПодбора", Параметры, Элемент, УникальныйИдентификатор());
      КонецПроцедуры
      
    3. Обрабатываем результат подбора на основной форме:

      Если вы использовали ОткрытьФорму, то результат будет возвращен в обработчик события ОбработкаВыбора вашего поля. Если же вы использовали ОткрытьФормуМодально, то результат можно получить сразу после вызова функции.

      
      &НаКлиенте
      Процедура ПолеОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
          Если ВыбранноеЗначение Тогда
              Элемент.Значение = ВыбранноеЗначение; // Присваиваем выбранную ссылку полю
          КонецЕсли;
      КонецПроцедуры
      
  3. Особенности на мобильных платформах/планшетах:

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

Итоги

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

  1. Для ограничения ввода символов: расширение типа поля формы до Строка и использование события ИзменениеТекстаРедактирования для программной фильтрации текста. Это позволяет нам вручную контролировать каждый введенный символ.

  2. Для реализации пользовательской клавиатуры: создание отдельной формы подбора, которая предоставляет кастомный интерфейс для ввода данных, а затем программно ищет и устанавливает соответствующую ссылку. Этот подход является более гибким и надежным, особенно для сенсорных устройств.

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

← На главную