简体   繁体   中英

Web automation login input box trouble

I'm trying to automate a few things around the office and this program is supposed to log into our insurance companies website and pull information for use by payroll. Here is the function I use to input values in the webpage.

Public Function SetElement(Doc As HTMLDocument, MType As String, SelState As String, _
vInPut As Variant, Optional aIndex As Long = 0, Optional milSec As Long = 0) As Long
SetElement = 0
Sleep milSec
On Error GoTo Failed
Select Case MType
    Case "I": Doc.getElementById(SelState).Value = vInPut: SetElement = 1
    Case "N": Doc.getElementsByName(SelState)(aIndex).Value = vInPut: SetElement = 1
    Case "C": Doc.getElementsByClassName(SelState)(aIndex).Value = vInPut: SetElement = 1
    Case "T": Doc.getElementsByTagName(SelState)(aIndex).Value = vInPut: SetElement = 1
    Case "Q": Doc.querySelector(SelState).Value = vInPut: SetElement = 1
End Select
Failed:
End Function

Here is the function call as it appears in the main sub

i = 0: Do While i = 0
    i = SetElement(Doc, "N", "loginEmail", lcLogin, 0, 500)
Loop

The correct username get put into the text box on the webpage, but when the code clicks the login button red text appears under the username and password asking me to put a username (same issue for the password box too).

Here is the website HTML for the input box

<input name="loginEmail" class="form-control gbx-unmasked ng-pristine ng-valid ng-touched" id="loginEmail" aria-label="Email" type="email" maxlength="64" placeholder="" value="" data-dl='{"event":"change","da_track":"true","interaction_only":"true"}' _ngcontent-qql-c18="" autocapitalize="off" autocomplete="off" autocorrect="off">

If I click the input box and type in a single character and delete it in either the username or password boxes the website behaves as if it now has the correct values. If i had to make an educated guess this has something to do with the "data-dl='{"event":"change","da_track":"true","interaction_only":"true"}" bit of code.

found a good HTML formatter so here is the entire code for the input box.

<div class="col-xs-12 no-padding" _ngcontent-upe-c11="">
<primary-form-text-input
    class="ng-touched ng-dirty ng-valid"
    _ngcontent-upe-c11=""
    CustomGridClass="email-field"
    formControlName="loginEmail"
    inputId="loginEmail"
    inputPlaceholder=""
    inputType="email"
    isAutoFocus="true"
    labelName="Email"
    maxlength="64"
    ngDefaultControl=""
    textType="text"
    _nghost-upe-c14=""
>
    <div class="row form-group has-feedback" _ngcontent-upe-c14="">
        <!---->
        <app-tertiary-page-label _ngcontent-upe-c14="" _nghost-upe-c17="">
            <div _ngcontent-upe-c17="">
                <label class="control-label" for="loginEmail" _ngcontent-upe-c17=""><em _ngcontent-upe-c17=""></em>Email </label>
            </div>
        </app-tertiary-page-label>
        <div class="email-field" _ngcontent-upe-c14="">
            <primary-text-input _ngcontent-upe-c14="" _nghost-upe-c18="">
                <div style="position: relative;" _ngcontent-upe-c18="">
                    <!---->
                    <input
                        name="loginEmail"
                        class="form-control gbx-unmasked ng-touched ng-dirty ng-valid"
                        id="loginEmail"
                        aria-label="Email"
                        type="email"
                        maxlength="64"
                        placeholder=""
                        value="test@temail.com"
                        data-dl='{"event":"change","da_track":"true","interaction_only":"true"}'
                        _ngcontent-upe-c18=""
                        autocapitalize="off"
                        autocomplete="off"
                        autocorrect="off"
                    />
                    <!----><!----><!---->
                    <span class="eye-span" hidden="" _ngcontent-upe-c18="">
                        <!---->
                        <em
                            class="icon icon-view icon-2x"
                            ondragstart="return false"
                            ondrop="return false"
                            data-dl='{"event":"mousedown","da_track":"true","event_type":"Link Click","event_id":"Show Password"}'
                            _ngcontent-upe-c18=""
                            alt="Show password"
                        ></em>
                        <!---->
                    </span>
                </div>
            </primary-text-input>
        </div>
        <div class="col-xs-12 no-padding gotham-book" _ngcontent-upe-c14="">
            <!---->
            <span class="icon icon-attention form-control-feedback" aria-hidden="true" _ngcontent-upe-c14=""></span>
            <!---->
        </div>
    </div>
</primary-form-text-input>

UPDATE: I think I found the jscript function

                function ar(e) {
                return r["ɵvid"](0, [(e()(), r["ɵeld"](0, 0, [[1, 0], ["name", 1]], null, 6, "input", [["autocapitalize", "off"], ["autocomplete", "off"], ["autocorrect", "off"], ["data-dl", '{"event":"change","da_track":"true","interaction_only":"true"}']], [[8, "type", 0], [8, "placeholder", 0], [8, "id", 0], [8, "name", 0], [1, "maxlength", 0], [1, "minlength", 0], [1, "max", 0], [8, "className", 0], [1, "aria-label", 0], [1, "value", 0], [8, "readOnly", 0], [2, "ng-untouched", null], [2, "ng-touched", null], [2, "ng-pristine", null], [2, "ng-dirty", null], [2, "ng-valid", null], [2, "ng-invalid", null], [2, "ng-pending", null]], [[null, "blur"], [null, "focus"], [null, "input"], [null, "compositionstart"], [null, "compositionend"]], (function (e, t, n) {
                                    var i = !0,
                                    o = e.component;
                                    return "input" === t && (i = !1 !== r["ɵnov"](e, 1)._handleInput(n.target.value) && i),
                                    "blur" === t && (i = !1 !== r["ɵnov"](e, 1).onTouched() && i),
                                    "compositionstart" === t && (i = !1 !== r["ɵnov"](e, 1)._compositionStart() && i),
                                    "compositionend" === t && (i = !1 !== r["ɵnov"](e, 1)._compositionEnd(n.target.value) && i),
                                    "blur" === t && (i = !1 !== o.onChange(n, r["ɵnov"](e, 0).value) && i),
                                    "focus" === t && (i = !1 !== o.onFocusFunction() && i),
                                    i
                                }), null, null)), r["ɵdid"](1, 16384, null, 0, Jn.DefaultValueAccessor, [r.Renderer2, r.ElementRef, [2, Jn.COMPOSITION_BUFFER_MODE]], null, null), r["ɵprd"](1024, null, Jn.NG_VALUE_ACCESSOR, (function (e) {
                                return [e]
                            }), [Jn.DefaultValueAccessor]), r["ɵdid"](3, 540672, null, 0, Jn.FormControlDirective, [[8, null], [8, null], [6, Jn.NG_VALUE_ACCESSOR], [2, Jn["ɵangular_packages_forms_forms_q"]]], {
                            form: [0, "form"]
                        }, null), r["ɵprd"](2048, null, Jn.NgControl, null, [Jn.FormControlDirective]), r["ɵdid"](5, 16384, null, 0, Jn.NgControlStatus, [[4, Jn.NgControl]], null, null), r["ɵdid"](6, 4210688, null, 0, Kn, [Qn, er, r.ElementRef, $n], null, null)], (function (e, t) {
                        e(t, 3, 0, t.component.controls)
                    }), (function (e, t) {
                        var n = t.component;
                        e(t, 0, 1, [n.inputType, n.inputPlaceholder, n.inputId, n.inputId, n.maxlength, n.minlength, n.max, r["ɵinlineInterpolate"](7, "form-control ", "password" === n.inputType ? "set-password-eye-align" : "", " ", "loginPassword" === n.inputId ? "login-password-star" : "", " ", "email" === n.inputId || "securityCode" === n.inputId ? "gbx-unmasked" : "", "", "emailControl" === n.inputId ? "gbx-unmasked" : "", "", "loginEmail" === n.inputId ? "gbx-unmasked" : "", "", "firstName" === n.inputId ? "gbx-unmasked" : "", "", "lastName" === n.inputId ? "gbx-unmasked" : "", ""), n.labelName, n.inputValue, n.readOnlyCondition, r["ɵnov"](t, 5).ngClassUntouched, r["ɵnov"](t, 5).ngClassTouched, r["ɵnov"](t, 5).ngClassPristine, r["ɵnov"](t, 5).ngClassDirty, r["ɵnov"](t, 5).ngClassValid, r["ɵnov"](t, 5).ngClassInvalid, r["ɵnov"](t, 5).ngClassPending])
                    }))
            }

How do I call it?

I just remembered that this is a public website.

Here is the link .

I got it working with the help of Zwenn's old answer. Here is the solution I came up with after adapting his code.

Sub login
Dim IE As Object
Dim doc As HTMLDocument
Dim i As Long
Dim aLogin As String
Dim aPsw As String

'Set the login details here
aLogin = "*****"
aPsw = "*****"

'Create a new instance of IE
Set IE = CreateObject("InternetExplorer.application")
'Set to true if you want to watch whats happening and false if you want it to run in the background
IE.Visible = True

'navigate to the website
IE.navigate "https://account.thehartford.com/customer/#/login?appid=EE"

'wait for the website to load
Do While IE.Busy: DoEvents: Loop

'Shorten IE.document to doc, because I'm lazy
Set doc = IE.document

'I've found wrapping interactions with websites into their own generic functions with error handling
'to be the most reliable method of web automation.  Someone please tell me if this approach
'has a drawback I'm not aware of.

'Here we trigger the comstart event, input values and trigger compend; for bother the user names and password.
'Then we click the login button.  The case statement ensures everything happens in the correct order.
i = 0
Do While i <= 6
    Select Case i
        Case 0: i = i + TriggerEvent(doc, "I", "loginPassword", "compositionstart", 0, 200)
        Case 1: i = i + SetElement(doc, "I", "loginEmail", aLogin, 0, 100)
        Case 2: i = i + TriggerEvent(doc, "I", "loginEmail", "compositionend", 0, 100)
        Case 3: i = i + TriggerEvent(doc, "I", "loginEmail", "compositionstart", 0, 200)
        Case 4: i = i + SetElement(doc, "I", "loginPassword", aPsw, 0, 100)
        Case 5: i = i + TriggerEvent(doc, "I", "loginPassword", "compositionend", 0, 100)
        Case 6: i = i + ClickElement(doc, "I", "btNext", 0, 200)
    End Select
Loop
End Sub

Here is the function that triggers the event.

'A function to trigger an event on a webpage. MType specifies which method you use to identify the element on the webpage,
'SelStatement specifies the text that identifies the element, Event type tells the function which event to trigger
Public Function TriggerEvent(doc As HTMLDocument, MType As String, SelState As String, eventType As String, Optional aIndex As Long = 0, Optional milSec As Long = 100) As Long
    Dim theEvent As Object
    Dim htmlElementWithEvent As Object
    Sleep millSec
    TriggerEvent = 0
    On Error GoTo Failed
    Select Case MType
        Case "I": Set htmlElementWithEvent = doc.getElementById(SelState): TriggerEvent = 1
        Case "N": Set htmlElementWithEvent = doc.getElementsByName(SelState)(aIndex): TriggerEvent = 1
        Case "C": Set htmlElementWithEvent = doc.getElementsByClassName(SelState)(aIndex): TriggerEvent = 1
        Case "T": Set htmlElementWithEvent = doc.getElementsByTagName(SelState)(aIndex): TriggerEvent = 1
        Case "Q": Set htmlElementWithEvent = doc.querySelector(SelState): TriggerEvent = 1
    End Select
    htmlElementWithEvent.Focus
    Set theEvent = doc.createEvent("HTMLEvents")
    theEvent.initEvent eventType, True, False
    htmlElementWithEvent.dispatchEvent theEvent
Failed:
End Function

And for completeness sake here is the click function.

'Adds built in error handling and delay to common click methods.  Requires declaring 
the sleep function from kernel32 lib
Public Function ClickElement(doc As HTMLDocument, MType As String, SelState As String, 
Optional aIndex As Long = 0, Optional milSec As Long = 0) As Long
'Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
ClickElement = 0
Sleep milSec
On Error GoTo Failed
Select Case MType
    Case "I": doc.getElementById(SelState).Click: ClickElement = 1
    Case "N": doc.getElementsByName(SelState)(aIndex).Click: ClickElement = 1
    Case "C": doc.getElementsByClassName(SelState)(aIndex).Click: ClickElement = 1
    Case "T": doc.getElementsByTagName(SelState)(aIndex).Click: ClickElement = 1
    Case "Q": doc.querySelector(SelState).Click: ClickElement = 1
End Select
Failed:
End Function

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM