uezo / TinySeleniumVBA

A tiny Selenium wrapper written in pure VBA
MIT License
60 stars 16 forks source link

Modify method. SetValue #18

Open ghost opened 3 years ago

ghost commented 3 years ago

Python Seleniumの send_keys メソッドを参考にして、SetValue で特殊キーを扱えるようにしてみました。 Pythonは引数の数を固定していないので Excel VBA の ParamArray でトライしましたが、WebDriver.cls と WebElement.cls での両立は私の技量ではできませんでした。そこで WebDriver.cls と WebElement.cls 共に、入力に先立ってクリアする/しない の引数(Optional ClearBeforeTyping As Boolean = True)を加えました。 また JsonConverter.bas で特殊キーの場合は \ をエスケープしない様にする必要がありました。

WebDriver.cls

'Set of special keys codes.     '2021/8/13 add ishi
Public Enum Keys
    NULL_key = &H0&                 '\ue000
    CANCEL_key = &H1&               '\ue001
    HELP_key = &H2&                 '\ue002
    BACKSPACE_key = &H3&            '\ue003
    BACK_SPACE_key = BACKSPACE_key
    TAB_key = &H4&                  '\ue004
    CLEAR_key = &H5&                '\ue005
    RETURN_key = &H6&               '\ue006
    ENTER_key = &H7&                '\ue007
    SHIFT_key = &H8&                '\ue008
    LEFT_SHIFT_key = SHIFT_key
    CONTROL_key = &H9&              '\ue009
    LEFT_CONTROL_key = CONTROL_key
    ALT_key = &HA&                  '\ue00a
    LEFT_ALT_key = ALT_key
    PAUSE_key = &HB&                '\ue00b
    ESCAPE_key = &HC&               '\ue00c
    SPACE_key = &HD&                '\ue00d
    PAGE_UP_key = &HE&              '\ue00e
    PAGE_DOWN_key = &HF&            '\ue00f
    END_key = &H10&                 '\ue010
    HOME_key = &H11&                '\ue011
    LEFT_key = &H12&                '\ue012
    ARROW_LEFT_key = LEFT_key
    UP_key = &H13&                  '\ue013
    ARROW_UP_key = UP_key
    RIGHT_key = &H14&               '\ue014
    ARROW_RIGHT_key = RIGHT_key
    DOWN_key = &H15&                '\ue015
    ARROW_DOWN_key = DOWN_key
    INSERT_key = &H16&              '\ue016
    DELETE_key = &H17&              '\ue017
    SEMICOLON_key = &H18&           '\ue018
    EQUALS_key = &H19&              '\ue019
    'number pad keys
    NUMPAD0_key = &H1A&             '\ue01a
    NUMPAD1_key = &H1B&             '\ue01b
    NUMPAD2_key = &H1C&             '\ue01c
    NUMPAD3_key = &H1D&             '\ue01d
    NUMPAD4_key = &H1E&             '\ue01e
    NUMPAD5_key = &H1F&             '\ue01f
    NUMPAD6_key = &H20&             '\ue020
    NUMPAD7_key = &H21&             '\ue021
    NUMPAD8_key = &H22&             '\ue022
    NUMPAD9_key = &H23&             '\ue023
    MULTIPLY_key = &H24&            '\ue024
    ADD_key = &H25&                 '\ue025
    SEPARATOR_key = &H26&           '\ue026
    SUBTRACT_key = &H27&            '\ue027
    DECIMAL_key = &H28&             '\ue028
    DIVIDE_key = &H29&              '\ue029
    'function  keys
    F1_key = &H31&                  '\ue031
    F2_key = &H32&                  '\ue032
    F3_key = &H33&                  '\ue033
    F4_key = &H34&                  '\ue034
    F5_key = &H35&                  '\ue035
    F6_key = &H36&                  '\ue036
    F7_key = &H37&                  '\ue037
    F8_key = &H38&                  '\ue038
    F9_key = &H39&                  '\ue039
    F10_key = &H3A&                 '\ue03a
    F11_key = &H3B&                 '\ue03b
    F12_key = &H3C&                 '\ue03c

    META_key = &H3D&                '\ue03d
    COMMAND_key = &H3D&             '\ue03d

    [_Min0] = NULL_key - 1
    [_Max0] = DIVIDE_key + 1
    [_Min1] = F1_key - 1
    [_Max1] = COMMAND_key + 1
End Enum
' Set value to element extended     '2021/8/13 chg ishi
' ( special keys codes support )
Public Sub SetValue(ElementId As String, _
                    text As Variant, _
                    Optional ClearBeforeTyping As Boolean = True, _
                    Optional ByVal sessionid As String = vbNullString)
    Dim data As New Dictionary
    If sessionid <> vbNullString Then
        data.Add "sessionId", sessionid
    End If
    data.Add "id", ElementId

    Dim i As Integer
    Dim KeyCode As String
    Dim value As String
    Dim chars() As String
    If TypeName(text) = "Long" Then
        If Keys.[_Min0] < CLng(text) And CLng(text) < Keys.[_Max0] Or _
           Keys.[_Min1] < CLng(text) And CLng(text) < Keys.[_Max1] Then
            KeyCode = "\ue0" & Right("0" & LCase(Hex(CLng(text))), 2)
            value = KeyCode
            ReDim Preserve chars(0)
            chars(0) = KeyCode
        Else
            value = CStr(text)
            ReDim chars(Len(text) - 1)
            For i = 0 To UBound(chars)
                chars(i) = Mid(text, i + 1, 1)
            Next
        End If
    Else
        value = CStr(text)
        ReDim chars(Len(text) - 1)
        For i = 0 To UBound(chars)
            chars(i) = Mid(text, i + 1, 1)
        Next
    End If

    data.Add "text", value
    data.Add "value", chars

    If ClearBeforeTyping = True Then Execute CMD_CLEAR_ELEMENT, data
    Execute CMD_SEND_KEYS_TO_ELEMENT, data
End Sub

WebElement.cls

' Set value to element              '2021/8/13 chg ishi
Public Sub SetValue(text As Variant, _
                    Optional ClearBeforeTyping As Boolean = True)
    Driver_.SetValue ElementId_, text, ClearBeforeTyping, SessionId_
End Sub

JsonConverter.bas
 Private Function json_Encode に対して、特殊キーの場合は \ をエスケープしない様にする必要がありました。  特殊キーの判定は甘いかもしれません。

        Case 92
            ' \ -> 92 -> \\
            json_Char = "\\"
            ' 2021/8/13 add ishi
            If VBA.Len(json_Text) = 6 Then
                If VBA.Mid$(json_Text, json_Index, 4) = "\ue0" Then
                    json_Char = "\"         'Special key codes are not escaped.
                End If
            End If
        Case 47

=========================================================== 動作確認  下記の場合、このような動きになります。    ”54321” ⇒ "5432" ⇒ "542" ⇒ "42" ⇒ "42ABC" ⇒ 次のinputへタブ移動

    Set objElm = objDrv.FindElement(By.CssSelector, <input tagのSelector値> )
    objElm.SetValue "54321"
    objElm.SetValue Keys.BACKSPACE_key, False
    objElm.SetValue Keys.LEFT_key, False
    objElm.SetValue Keys.LEFT_key, False
    objElm.SetValue Keys.DELETE_key, False
    objElm.SetValue Keys.LEFT_key, False
    objElm.SetValue Keys.LEFT_key, False
    objElm.SetValue Keys.DELETE_key, False
    objElm.SetValue "ABC", False
    objElm.SetValue Keys.TAB_key, False
GCuser99 commented 2 years ago

Nice job! See this discussion SendKeys Method.