简体   繁体   中英

Excel VBA: How to copy value of a field from Internet Explorer

I'm trying to access a form on internet explorer, then copy value of some fields (that I know there name and id) and the copy those value in a an Excel sheet. That's the simplify version of what I'm trying to do. So right now I'm able to open my web page, then open the subform that is included in it. But when I get to copying the value of the field I'm interested in. I'm not able to set the variable so I can then copy it back to Excel.
Here's my code below. My problem between comments.

Private Sub Open_multiple_sub_pages_from_main_page()

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

    ' 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://webpage.com/"

    ' Wait while IE loading...
    While IE.Busy
            DoEvents
    Wend

    Set objCollection = IE.Document.getElementsByTagName("input")

    i = 0
    While i < objCollection.Length
        If objCollection(i).Name = "txtUserName" Then

            ' Set text for search
            objCollection(i).Value = "1234"
        End If
        If objCollection(i).Name = "txtPwd" Then

            ' Set text for search
            objCollection(i).Value = "password"
        End If

        If objCollection(i).Type = "submit" And objCollection(i).Name = "btnSubmit" Then ' submit button if found and set
            Set objElement = objCollection(i)
        End If
        i = i + 1
    Wend
    objElement.Click    ' click button to load page

    ' Wait while IE re-loading...
    While IE.Busy
            DoEvents
    Wend

    ' Show IE
    IE.Visible = True
    Set Doc = IE.Document

    Dim links, link, value_to_copy

    Dim j As Integer                                                                    'variable to count items
    j = 0
    Set links = IE.Document.getelementbyId("dgTime").getElementsByTagName("a")
    n = links.Length
    While j <= n                                    'loop to go thru all "a" item so it loads next page
        links(j).Click
        While IE.Busy
            DoEvents
        Wend
        '------------THE PROBLEM IS HERE---------------------------
        Set value_to_copy = IE.Document.getelementbyId("mainTable").getElementsByTagName("txtProject").innerText
        '----------VALUE_TO_COPY WILL REMAIN AT "" VALUE

        IE.Document.getelementbyId("DetailToolbar1_lnkBtnSave").Click              'save
        Do While IE.Busy
            Application.Wait DateAdd("s", 1, Now)                                   'wait
        Loop
        IE.Document.getelementbyId("DetailToolbar1_lnkBtnCancel").Click            'close
        Do While IE.Busy
            Application.Wait DateAdd("s", 1, Now)                                   'wait
        Loop
        Set links = IE.Document.getelementbyId("dgTime").getElementsByTagName("a")
        j = j + 2
    Wend
End Sub

Below is the html code of the page from wich I'm trying to retrieve the "txtProject" value. In that particular case the value is "0000001". That's the value I need to copy.

<table width="100%" class="Form" id="mainTable" border="0" cellspacing="0" cellpadding="0">
    <tbody><tr id="TRCustomer">
        <td class="titleLabel"><span id="lblCustomer">
<u>C</u>lient : </span></td>
<td><input name="txtCustomer" id="txtCustomer" accesskey="C"
   language="javascript" onchange="__doPostBack('txtCustomer','')"  
   type="text"></td>
<td><a class="Button" id="lnkBtnCustomer" href="javascript:__doPostBack('lnkBtnCustomer','')">
<img id="imgCustomer" alt="" src="images/toolbar/b_preview.gif"  
   border="0"></a></td>
<td class="tdDescriptionLabel"><span class="DescriptionLabel" 
    id="lblCustomerDescription">&nbsp;</span></td>
    </tr>
<tr id="TRProject">
<td width="110" class="titleLabel">
  <span id="lblProject">Pro<u>j</u>et : </span></td>
<td width="152"><input name="txtProject" tabindex="2" id="txtProject"
    accesskey="J" language="javascript" 
    onkeypress="return LookupButton(event,'lnkBtnProject')" 
    onchange="__doPostBack('txtProject','')" type="text"
     value="0000001"></td>
<td width="20"><a class="Button" id="lnkBtnProject" 
    href="javascript:__doPostBack('lnkBtnProject','')">
    <img id="imgProject" alt="" src="images/toolbar/b_preview.gif"
    border="0"></a></td><td class="tdDescriptionLabel">
   <span class="DescriptionLabel" 

Any help will be greatly appreciated.
Tx in advance.

Within a document id should be unique, so you can use that directly:

value_to_copy = IE.Document.getelementbyId("txtProject").Value

getElementsByTagName() isn't used to locate elements by id, and in any case returns a collection of matches , not a single element, so you can't assign it's return value like that. This would be how you'd typically use it:

value_to_copy = IE.Document.getelementsbyTagName("input")(0).Value

The Set keyword is used for objects, you have here a variable. Drop Set from assignment statement. value_to_copy = IE.Document.getelementbyId("mainTable").getElementsByTagName("txtProject").innerText

The innerText property returns a String type. Which means, you don't need the keyword Set which is instead used to set a variable as a pointer to a particular object. Strings are native types, so don't use the keyword Set. Try this instead:

'------------THE PROBLEM IS HERE---------------------------
            value_to_copy = IE.Document.getelementbyId("mainTable").getElementsByTagName("txtProject").innerText
            '----------VALUE_TO_COPY WILL REMAIN AT "" VALUE

This is a subtle problem. In a nutshell, you shouldn't be using the innertext property. Instead, you want to retrieve the value of the "value" node returned by the childNodes property of the txtProject element .

The data you are retrieving is not actually "innertext." Innertext would be the text that appears between the opening and closing tags. From MSDN https://msdn.microsoft.com/en-us/library/ie/ms533899(v=vs.85).aspx :

The innerText property is valid for block elements only. By definition, elements that do not have both an opening and closing tag cannot have an innerText property.

For example, in the following snippet:

<h1>Header Text</h1>

The innertext of the <h1> tag is "Header text"

In your snippet, the tag does not actually have any inner text. You have a td element with attributes but nothing between the <td...> and the </td> :

<td width="152"><input name="txtProject" tabindex="2" id="txtProject"
accesskey="J" language="javascript" 
onkeypress="return LookupButton(event,'lnkBtnProject')" 
onchange="__doPostBack('txtProject','')" type="text"
 value="0000001"></td>'

That's why the innertext property fails. Your snippet, getElementsByTagName("txtProject") returns an Element object. Elements are collections of nodes . Your element has nodes named name , tabindex , id , accesskey , language , onkeypress , onchange , type and value . Each of these nodes has a value associated with it. You need to access the value node and query its value.

I suspect the following will work, or something like it.

set txtProject = IE.Document.getelementbyID("mainTable").getElementsByTagName("txtProject")
    ' returns a `<td..></td>` element

value_to_copy = txtProject.childNodes("value")
    'Should return the default property of the node "value".  
    'The default property should be the string "00000001".  
    'But I'm not sure so you might want to do more 
    'research on `childNodes` and `nodes`

or alternatively, but less intuitive:

value_to_copy = IE.Document.getelementbyID("mainTable") _
                           .getElementsByTagName("txtProject") _
                           .childNodes("value")

I adapted this from the following code snippet on https://msdn.microsoft.com/en-us/library/ms757053(v=vs.85).aspx . So if my suggestion above doesn't work, maybe this will help.

The following script example uses the childNodes property (collection) to return an IXMLDOMNodeList, and then iterates through the collection, displaying the value of each item's xml property.

root = xmlDoc.documentElement;
oNodeList = root.childNodes;
for (var i=0; i<oNodeList.length; i++) {
  Item = oNodeList.item(i);
  WScript.Echo(Item.xml);
  }

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