Excel это не сложно

Основные форумы => Вопросы по Excel и VBA => Тема начата: Muskin2029 от 01.07.2020, 14:17:19



Название: Вопрос по контролю ввода с помощью VBScript.RegExp
Отправлено: Muskin2029 от 01.07.2020, 14:17:19
Всем привет!
На форме имеется несколько полей TextBox для ввода чисел.
Конкретно - в поле t_OffsetY ввод контролируется так:
Код: (vb)
Private Sub t_OffsetX_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)

       With CreateObject("VBScript.RegExp")
           .Pattern = "^[-]?[1-9]?[0-9]?$"
           If Not .Test(t_OffsetX.Value & Chr(KeyAscii)) Then KeyAscii = 0
       End With

End Sub
При отсутствии начального значения в t_OffsetX (пустое поле) всё отрабатывается нормально.
При заданном начальном значении поля t_OffsetX и при переходе на это поле по Tab поле выделяется и необходимо нажать Backspace, чтобы произвести ввод.
Что необходимо добавить именно в .Pattern, чтобы не использовать Backspace, т.е. выделение затиралось бы при вводе (-) и/или чисел?


Название: Re:Вопрос по контролю ввода с помощью VBScript.RegExp
Отправлено: Дмитрий Щербаков(The_Prist) от 01.07.2020, 14:39:57
Если честно - ничего не понял. Почему нельзя использовать событие KeyDown для определения кода клавиши? И причем здесь вообще RegExp, если хотите что-то затирать клавишей?
Можете как-то иначе попробовать пояснить задачу?


Название: Re:Вопрос по контролю ввода с помощью VBScript.RegExp
Отправлено: Muskin2029 от 01.07.2020, 15:11:52
Попытаюсь попроще описать.
В поле t_OffsetX должно вводиться значение от 0 до 99, может быть со знаком -.
Это же поле t_OffsetX имеет начальное значение 20.
Если перейти на это поле по Tab, число 20 выделяется, ввод по шаблону "^[-]?[1-9]?[0-9]?$" невозможен, пока не затереть это выделение.
Почему RegExp? - да просто удобно и коротко.


Название: Re:Вопрос по контролю ввода с помощью VBScript.RegExp
Отправлено: Дмитрий Щербаков(The_Prist) от 01.07.2020, 16:00:15
имеет начальное значение 20
А зачем оно нужно, если его надо затирать в итоге? Я не очень понимаю все равно манипуляции. Почему просто не запретить ввод ненужного и оставить только ввод по шаблону? Например, так:
Код: (vb)
Private Sub t_OffsetX_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
    Dim ore As Object
    Set ore = CreateObject("VBScript.RegExp")
    With CreateObject("VBScript.RegExp")
        .Pattern = "[-]?\d{0,2}"
        If .Replace(t_OffsetX.Value & Chr(KeyAscii), "") <> "" Then KeyAscii = 0
    End With
End Sub


Название: Re:Вопрос по контролю ввода с помощью VBScript.RegExp
Отправлено: Muskin2029 от 01.07.2020, 17:37:11
А зачем оно нужно, если его надо затирать в итоге? Я не очень понимаю все равно манипуляции.
В поле t_OffsetX указано начальное значение, например, 20.
С предыдущего поля по Tab перескакиваем на t_OffsetX, число 20 полностью выделяется.
Если по каким-то условиям его менять не нужно - жмём Tab и перескакиваем на следующее поле.
Но если 20 нужно изменить, выделение нужно затереть, чтобы ввести в соответствие с шаблоном новое число.
Так как избежать этого затирания (BackSpace)?
Если не использовать RegExp (обычный ввод без контроля), то при переходе на t_OffsetX при наборе первого же символа выделение затирается автоматически.


Название: Re:Вопрос по контролю ввода с помощью VBScript.RegExp
Отправлено: Дмитрий Щербаков(The_Prist) от 01.07.2020, 18:48:07
Так как избежать этого затирания
Никак. И уж точно не при помощи RegExp. Какая разница используете Вы его или нет - если в событии Вы не предотвращаете нажатие клавиши BackSpace, то и действие её тоже нельзя предотвратить. Я изначально написал - для отслеживания нажатия клавиш используйте KeyDown. Ну вроде того:
Код: (vb)
Private Sub TextBox2_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    If KeyCode = 8 Then
        KeyCode = 0
    End If
End Sub

а что в итоге надо я все равно не понял, уж извините. Вы можете забыть про RegExp и написать каким видите правильное поведение при переходе Tab-ом на текстбокс и вводе без BackSpace и с ним данных?

P.S. Вы мой-то код пробовали? Ему вообще фиолетово как Вы там вводите - затирая сначала или нет, все обрабатывается по шаблону правильно.


Название: Re:Вопрос по контролю ввода с помощью VBScript.RegExp
Отправлено: Muskin2029 от 01.07.2020, 19:24:28
P.S. Вы мой-то код пробовали?
Ну да, его и буду использовать.
Ему вообще фиолетово как Вы там вводите - затирая сначала или нет, все обрабатывается по шаблону правильно.
У меня почему-то не фиолетово - при выделенном поле шаблон не срабатывает, приходится всё-таки затирать.
Обнаружил ещё одну неприятность.
Допустим, перепрыгиваю на это поле, там стоит число 20, выделенное. Стрелкой влево иду в начало числа, чтобы поставить минус - шаблон не срабатывает, тут уже приходится использовать Delete и всё-равно очищать всё поле.
Придётся, наверно, действительно использовать _KeyDown, хотя If-ов и по прибавится.


Название: Re:Вопрос по контролю ввода с помощью VBScript.RegExp
Отправлено: Дмитрий Щербаков(The_Prist) от 01.07.2020, 19:42:16
Стрелкой влево иду в начало числа, чтобы поставить минус - шаблон не срабатывает
логично. Вы же всегда ПОСЛЕ текста добавляете новый вводимый символ:
TextBox2.Value & Chr(KeyAscii)
Вам надо обрабатывать определение позиции вводимого символа и составлять корректную будущую строку для проверки шаблоном:
Код: (vb)
Private Sub t_OffsetX_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
    Dim ore As Object
    Dim s$, ls&, txt$
   
    Set ore = CreateObject("VBScript.RegExp")
    With CreateObject("VBScript.RegExp")
        .Pattern = "[-]?\d{0,2}"
        ls = t_OffsetX.SelStart
        txt = t_OffsetX.Value
        If ls = 0 Then
            s = Chr(KeyAscii) & txt
        Else
            s = Mid(txt, 1, ls) & Chr(KeyAscii) & Mid(txt, ls + 1, Len(txt) - 1)
        End If
        If .Replace(s, "") <> "" Then KeyAscii = 0
    End With
End Sub



Название: Re:Вопрос по контролю ввода с помощью VBScript.RegExp
Отправлено: Muskin2029 от 05.07.2020, 11:47:20
Дмитрий, спасибо за пример, однако есть моменты, когда он не срабатывает.
При первом попадании на поле t_OffsetX Tab-ом вводятся только отрицательные числа, положительные - стопор.
После ухода с этого поля, а затем возврата на него c помощье Shift+Tab или выделения его мышкой ввод любых чисел не возможен.
После небольшой паузы, написал такой вот код:
Код: (vb)
Private Sub t_OffsetX_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
   
  With CreateObject("VBScript.RegExp")
       .Pattern = "^(0|-$|-?[1-9]\d{0,2})$"
       txt = t_OffsetX.Value
       char_k = Chr(KeyAscii)
       sel_Text = t_OffsetX.SelText
       If sel_Text <> Empty Then    ' полное или частичное выделение
          If Not .Test(Replace(txt, sel_Text, char_k)) Then KeyAscii = 0
        Else                        ' выделения нет
          ls = t_OffsetX.SelStart
          If Not .Test(Mid(txt, 1, ls) & char_k & Mid(txt, ls + 1, Len(txt))) Then KeyAscii = 0
       End If
  End With

End Sub
Заменил шаблон для исключения при вводе ненужных нолей (-0, -012, 007 и т.п.).