简体   繁体   中英

Automate Internet Explorer: enter a value that has no “ID”

I'm trying to use excel VBA to automate the data entering on a intranet Webpage of my company. I know how to interact with values of a web page the fields have "id" like in the html code below

<input name="txtUserName" tabindex="1" id="txtUserName" type="text">  

With that kind of html code I would use something like

IE.Document.getElementbyId("txtUserName").Value = "UserName"  

The problem I'm facing is that the code associated with the field I'm trying to interact is

        <HTML><HEAD><META content="IE=5.0000" http-equiv="X-UA-Compatible">
<SCRIPT type=text/javascript>
            function ajusterFrames() {
                var iLargeurGauche = 217;
                var iLargeurDroite = 850;
                var iLargeurFenetre = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
                var iMarge = 0;
                var sCols = "";
                if (iLargeurFenetre > (iLargeurGauche + iLargeurDroite)) {
                    iMarge = (iLargeurFenetre - (iLargeurGauche + iLargeurDroite)) / 2;}
                sCols = (iLargeurGauche + iMarge) + ",*";
                document.getElementById("framesetbas").cols = sCols;
                document.getElementById("cadres").style.display = "block";}
            window.onload = ajusterFrames;
            window.onresize = ajusterFrames;
        </SCRIPT>

                            <TBODY>
                                <TR> </TR>
                                    <TR>
                                        <TD>
                                        <!--RECHERCHE-->
                                            DIV id=Projet>
                                            <!--RECHERCHE-->
                                                <CENTER>
                                                    <FIELDSET style="WIDTH: 600px" name="recherche">
                                                    <LEGEND style="FONT-SIZE: 10px; FONT-FAMILY: verdana; COLOR: #767676" name="legende_recherche">
                                                    <INPUT onclick=afficherRecherche(this.value); type=radio value=simple name=TypeRecherche>
                                                    </DIV><!------RECHERCHE AVANCÉE------------------------------------->
                                                    <DIV id=divAvancee>
                                                        <CENTER>
                                                            <TABLE cellSpacing=0 cellPadding=0 border=0>
                                                                <TBODY>
                                                                    <TR>
                                                                    <TR>
                                                                    <TR>
                                                                    <TR>
                                                                    <TR>
                                                                    <TR>
                                                                    <TD align=right>
                                                                        <FONT color=#003366 size=1 face=verdana>No Projet :</FONT></TD>

So I'm trying to modify the value of the field identify by: "txtNoProjet" Here's the code I could come up with, I tried many versions around this and still can't get it right.
UPDATED CODE TO INCLUDE SOLUTION

Private Sub entree_budget()


Dim i As Long
Dim IE As Object
Dim Doc As Object
Dim objElement As Object
Dim objCollection As Object
Dim buttonCollection As Object
Dim valeur_heure As Object

num_proj = Cells(1, 3)              'this is the value that I need to input

' Create InternetExplorer Object
Set IE = CreateObject("InternetExplorer.Application")

' You can uncoment Next line To see form results
IE.Visible = True

' Send the form data To URL As POST binary request
IE.Navigate "http://intranet.cima.ca/fr/application/paq/projets/index.asp?v1_lang=1"

' Wait while IE loading...
Do While IE.Busy
    Application.Wait DateAdd("s", 1, Now)
Loop

'UPDATED CODE BELOW

    Set links = IE.Document.frames(2).Document.getElementsByTagName("input")
         n = links.Length   
    While i < n
            If links(i).Name = "txtMotCle" Then        
                links(i).Value = num_proj
            End If  
  i = i+ 1  
Wend 

End Sub 

Can anyone help me with this?
And also if I may I will the need to click the button "search" on the bottom of the form , but I can't recognize it's syntax so I don't know how to interact with it. Could someone tell me how to click the button that has this html code?

<A href="javascript:submitForm('avancee');">
<IMG border=0 alt="Rechercher un projet" src="../../../images/fr/rechercher.gif"></A>  

UPDATED CODE SOLUTION FOR THIS IS:

Set links = IE.Document.frames(2).Document.getElementsByTagName("a")
 n = links.LengtH
i = 0
While i < n
    If links(i).href = "javascript:submitForm('avancee');" Then           
        Set objElement = links(i)
        objElement.ClicK
    End If
    i = i + 1
Wend

Thank you so much in advance for the time you'll spend answering my questions.

Edited: the input elements were contained in a frame, which is why @jeeped's answer wasn't working. getElementsByTagName("input") should have returned them. Hopefully this edit will save you from having to read through the comments to find that out. To return inputs contained in a frame, use

IE.document.frames(x).document.getElementsByTagName("input") 

where x is the index of the frame.

Original response below.

=======================================================

If it's zero-based, shouldn't you remove the -1 that's preventing the loop from running? That is, if there is one element, then the for loop would be iNPT = 0 to 0 and execute once. If there were two, then the .length would return 1 and =0 to 1 would execute twice, as expected.

I personally would probably include both Microsoft Internet Controls and Microsoft HTML Object Library in the references for the project so that I could use early binding and declare the variables, and then use a for each to iterate:

Dim inputs As MSHTML.IHTMLElementCollection
Dim inpt As MSHTML.IHTMLInputElement
Dim IE As New SHDocVw.InternetExplorer

IE.Visible = True
IE.navigate "http://intranet.cima.ca/fr/application/paq/projets/index.asp?v1_lang=1"
While IE.readyState <> READYSTATE_COMPLETE: DoEvents: Wend

Set inputs = IE.document.getElementsByTagName("input")
For Each inpt In inputs
    If inpt.Name = "txtNoProjet" Then inpt.Value = num_proj
    Next

Be aware that the HTML Object Library includes several different IHTMLElementCollections, with different numbers. In some situations you might need to use one of those instead. Also, you may need to use getAttribute to access the attribute:

If inpt.getAttribute("name") = "txtNoProjet" then inpt.Value = num_proj

The index to a collection of elements is zero-based . Assuming that there is only a single txtNoProjet you would use,

IE.Document.getElementsbyName("txtNoProjet")(0).Value = num_proj

I've had trouble with .getElementsbyName in the past. If the above does not work for you, collect all of the <input> elements and cycle through them until you find the one you want.

dim iNPT as long
for iNPT=0 to (IE.Document.getElementsbyTagName("input").length - 1)
  if IE.Document.getElementsbyTagName("input")(iNPT).name = "txtNoProjet" then
    IE.Document.getElementsbyTagName("input")(iNPT).value = num_proj
    exit for
  end if
next iNPT

One of those should get you going. The biggest problem you will run into would be duplicate names.

EDIT: addendum for clicking an image anchor

dim iIMG as long
for iIMG=0 to (IE.Document.getElementsbyTagName("img").length - 1)
  if CBool(InStr(1, IE.Document.getElementsbyTagName("img")(iIMG).src, "rechercher.gif", vbTextCompare)) then
    IE.Document.getElementsbyTagName("img")(iIMG).click
    do while IE.Busy Or IE.ReadyState <> READYSTATE_COMPLETE: Do Events: Loop
    exit for
  end if
next iIMG

I usually prefer something closer to IE.Document.getElementsbyTagName("form")(0).submit but you haven't provided enough HTML source code to write that properly. You will have to adjust that code to look into your .Frames element.

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