-
using .getElementsByName
Hey all,
i'm making a small tool to pass some data from my main form to a webpage (basically a ticket #) search for it open it (click it) & close it with provided comments, i'm using getElementByID to fetch the data from webpage & then provide necessary action (eg. send a click, set a value in textbox / combo box etc.). The problem is, when i search for the request it's "ElementID" is different as per the tkt # & hence i cannot hardcode it like the other stuff to "click" this tkt number. After some R&D i found another method : .getElementsByName but not sure how do i use it .
I'm basically stuck @ 2 things :
1. how do i get the value by GetElementsByName
2. after i get the value how do i find its "elementid" based on it's Name
My Code so far:
Code:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim ResComm, SLAComm, FetchReq As String
ResComm = txtResComm.Text
SLAComm = txtSLAComm.Text
Dim ie
ie = CreateObject("InternetExplorer.Application")
'Url = TextBox3.Text
ie.Visible = True
ie.Navigate("http://myurl.com")
Wait(ie)
With ie.Document
.getElementByID("ctl00$ContentPlaceHolder1$txtSrNumber").value = Me.txtRCNum.Text 'pass ticket # to webpage
.getElementByID("ctl00$ContentPlaceHolder1$btn_search").click() ' click on search
Threading.Thread.Sleep(3000)
Wait(ie) 'wait till search page is loaded
'
Threading.Thread.Sleep(1500)
FetchReq = .GetElementsByName(txtRCNum.Text).ToString ' <--This is where i'm trying to get the tkt #
' click ticket # hyperlink
MsgBox("req# : " & FetchReq)
Threading.Thread.Sleep(1500)
Wait(ie) ' wait till request is opened
Threading.Thread.Sleep(1500) 'wait till all request status options are fetched
.getElementByID("ctl00_ContentPlaceHolder1_ddlmacd_status").focus() 'set focus to request status drop down box
SendKeys.Send("CC") 'Twice C is for complete
Wait(ie)
'Threading.Thread.Sleep(1000)
SendKeys.Send("^A")
SendKeys.Send("{Del}")
SendKeys.Send(ResComm)
End With
End Sub
Sub Wait(ByVal IE)
'WScript = CreateObject("WScript.Shell")
Do
Threading.Thread.Sleep(500)
Loop While IE.ReadyState < 4 And IE.Busy
Do
Threading.Thread.Sleep(500)
Loop While IE.ReadyState < 4 And IE.Busy
End Sub
-
Re: using .getElementsByName
nobody ???
pls pls i'm close to completing this...
i just need to know how do i use getElementsByName & send a click to it
or
simply i need to know how do i user getelementbyid for a changing element id ?
-
Re: using .getElementsByName
Hmmm
vb Code:
WebBrowser1.Document.All("elementname").InvokeMember("click")
I know that worked for another thread I was helping with using the element name so it might work here.
-
Re: using .getElementsByName
Still no luck :(
i'm getting this error :
The server threw an exception. (Exception from HRESULT: 0x80010105 (RPC_E_SERVERFAULT))
-
Re: using .getElementsByName
can you show us the html?
getElementsByName returns an array, so if .GetElementsByName(txtRCNum.Text) is a uniquely named element, you'd use:
vb Code:
.GetElementsByName(txtRCNum.Text)(0).InnerText
-
Re: using .getElementsByName
GetElementByName works the same as GetElementByID... only it uses the NAME attribute instead of the ID attribute... So... if it has a NAME attribute, it'll work... otherwise, it may not.
To get an element, be it by ID or NAme... you need to know what value you are looking for.
-tg
-
Re: using .getElementsByName
ok, i used below & it returned me "system_#" !!! ???
Code:
FetchReq = ie.document.GetElementsByName(txtRCNum.Text).ToString
also here is the html code of the link i'm trying to click :
Code:
<a id="ctl00_ContentPlaceHolder1_requestNumber_9746128"
class="InboxColumnLinkDetail"
href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$requestNumber_9746128','')">8620410-6</a>
out of above "8620410-6" is the only info i have i do not have the "ID" since it changes everytime
-
Re: using .getElementsByName
if it changes every time, you can not use GetElementsByName. you will have to loop through the Document for each object (or object with tag name "a", or all links in the Document), and then check the object's ID, and use regex to match the ID, then get/set the value.
-
Re: using .getElementsByName
can't i use "8620410-6" (highligted below in HTML code) that is the only info i have & is displayed as hyperlink on search results page, but it's "elementid" is different
Code:
<a id="ctl00_ContentPlaceHolder1_requestNumber_9746128"
class="InboxColumnLinkDetail"
href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$requestNumber_9746128','')">8620410-6</a>
-
Re: using .getElementsByName
Well the "8620410-6" looks like the inner-text or perhaps the value of the element in question, so try doing what others have suggested and loop through the document for elements with tagname "a" then compare their inner-text to "8620410-6" and if true, you now have the element. This is assuming "8620410-6" is static.
-
Re: using .getElementsByName
cool, thx for that, cud u pls gimme overview of how that loop will look like ? i've never worked on html via vb .net before?
-
Re: using .getElementsByName
Umm I had to do something like this earlier today so I hope this will also work for you.
vb Code:
For each elem As HtmlElement in WebBrowser1.Document.GetElementsByTagName("a")
If elem.InnerText = "8620410-6" Then
'//do something
Exit For
End if
Next
Something like that I would stab a guess at.
-
Re: using .getElementsByName
bummer... it gave me below error :
Unable to cast COM object of type 'mshtml.HTMLAnchorElementClass' to class type 'System.Windows.Forms.HtmlElement'. Instances of types that represent COM components cannot be cast to types that do not represent COM components; however they can be cast to interfaces as long as the underlying COM component supports QueryInterface calls for the IID of the interface.
-
Re: using .getElementsByName
Uhhh, could show me what your current code looks like?
-
Re: using .getElementsByName
this just hit me... can i use the "getelementsbyclass" that is constant in the html code above....
btw, here's the loop code :
'For Each elem As HtmlElement In ie.Document.GetElementsByTagName("a")
If elem.InnerText = txtRCNum.Text Then
FetchReq = .getElementByID(elem.InnerText)
MsgBox("req # : " & FetchReq)
Exit For
End If
Next
-
Re: using .getElementsByName
the problem is that you're attempting to use members of HtmlDocument with a mshtml.IHtmlDocument2.
i'm not saying it's impossible, but i'd recommend you turn option strict on + cast objects explicitly.
-
Re: using .getElementsByName
Umm
vb.net Code:
'For Each elem As HtmlElement In ie.Document.GetElementsByTagName("a")
If elem.InnerText = txtRCNum.Text Then
FetchReq = .getElementByID(elem.InnerText)
MsgBox("req # : " & FetchReq)
Exit For
End If
Next
This won't work, I think you're misunderstanding the GetElementByID and InnerText properties in this case. InnerText is simply the text that the Element is holding, not an actual element. GetElementByID returns a HtmlElement. So By looping through all the htmlElements with the tag name "a", you've already got a htmlelement with the same behaviour. There is no need to attempt to "getelementbyID"
This line:
Code:
FetchReq = .getElementByID(elem.InnerText)
MsgBox("req # : " & FetchReq)
Exit For
End If
What you're trying to do is get an element by an ID that is the same as txtRCNum.Text (follow along the code logic and you'll see my point...in particular the "if elem.InnerText = txtRCNum.text")
I think you're over complicating things, if you've already got a unique htmlelement (which you have) all you need to do now is what you would do with the result of a GetElementByID
such as
Code:
elem.InvokeMember("click")
'...etc
-
Re: using .getElementsByName
yeah i think i'm freaking confused here & so close to pulling out my hair...
let me clarify this :
For Each elem As HtmlElement In ie.Document.GetElementsByTagName("a") 'Loop thru entire html page searching for all elements with tag "a"
If elem.InnerText = txtRCNum.Text Then ' within that if tag = "a" & it's inner text is txtrcnum then enter if loop
elem.InvokeMember("click") ' if condition is true click the element found
Exit For ' end for loop after the click is send
End If ' end if loop
Next
i hope so far so clear but when i run it i get following error on line # 1 (beginning of for loop):
Unable to cast COM object of type 'mshtml.HTMLAnchorElementClass' to class type 'System.Windows.Forms.HtmlElement'. Instances of types that represent COM components cannot be cast to types that do not represent COM components; however they can be cast to interfaces as long as the underlying COM component supports QueryInterface calls for the IID of the interface.
-
Re: using .getElementsByName
Well I'm lost, I wrote this exactly code up today for another project I was working on using tagnames to find elements and I never got invalid cast errors like that, what kind of object is "ie" I'm assuming it's a WebBrowser control?
-
Re: using .getElementsByName
Quote:
Originally Posted by
J-Deezy
Well I'm lost, I wrote this exactly code up today for another project I was working on using tagnames to find elements and I never got invalid cast errors like that, what kind of object is "ie" I'm assuming it's a WebBrowser control?
nope. it's a shdocvw.internetexplorer
-
Re: using .getElementsByName
/facepalm. God, the whole time I was assuming this was a standard webbrowser and was basing my code around that. My mistake. I think I'll withdraw from this thread.
-
Re: using .getElementsByName
@ .paul. : could u pls elaborate below ?
shdocvw.internetexplorer
-
Re: using .getElementsByName
Quote:
Originally Posted by
sk8er_boi
@ .paul. : could u pls elaborate below ?
shdocvw.internetexplorer
Wait if you're not using shdocw.internetexplorer...what type of control is "ie" in your form?
-
Re: using .getElementsByName
1st post:
Code:
Dim ie = CreateObject("InternetExplorer.Application")
I believe it uses shdocvw.internetexplorer underneath, so I'd try a standard WebBrowser control, unless you need more control, which you don't seem to.
-
Re: using .getElementsByName
Quote:
Originally Posted by
TTn
1st post:
Code:
Dim ie = CreateObject("InternetExplorer.Application")
I believe it uses shdocvw.internetexplorer underneath, so I'd try a standard WebBrowser control, unless you need more control, which you don't seem to.
Oops, must've missed that when I skimmed over it, my mistake. And yeah, I was going to suggest just simply crossing over to a WebBrowser control instead as it doesn't seem you actually need the interface (as you're manipulating the document "behind the scenes")
-
Re: using .getElementsByName
so how do i do it guys ??? pls pls little help here, this is the only thing stopping me from completing this tool, i've got the rest of code ready!
-
Re: using .getElementsByName
Go ahead and start by dropping a WebBrowser control onto your form.
You can use the toolbox, or dimension it like this:
Code:
Dim ie As New WebBrowser
-
Re: using .getElementsByName
hmmm..ok, wht if i add webbrowser control to my form itself ?, & then navigate within url (it's gonna be fixed anyway)
-
Re: using .getElementsByName
Yeah you can just add the webbrowser control to your form and set its visible property to false. If you use a webbrowser my above code will stop giving you COM errors :)
-
Re: using .getElementsByName
ok i've added WebBrowser control to my form, but it just won't wait till the page is loaded !!!
-
Re: using .getElementsByName
Put your fill code on the WebBrowser1_DocumentCompleted event :)
-
Re: using .getElementsByName
sorry forgot to mention .. this is wht i already did : (wbEURC is my webBrowser)
Code:
Private Sub wbEURC_DocumentComplete(ByVal pDisp As Object, ByVal URL As Object)
MsgBox("Web document is finished downloading")
With wbEURC.Document
.GetElementById("ctl00$ContentPlaceHolder1$txtSrNumber").InnerText = Me.txtRCNum.Text 'pass requst #
.GetElementById("ctl00$ContentPlaceHolder1$btn_search").RaiseEvent("Click")
' click on Go
End With
End Sub
-
Re: using .getElementsByName
It's not handling anything.
Private Sub wbEURC_DocumentComplete(ByVal pDisp As Object, ByVal URL As Object) Handles wbEURC.DocumentCompleted
that's what it should be.
-
Re: using .getElementsByName
your wbEURC_DocumentCompleted event will fire more than once while loading your webpage.
check wbEURC.readystate in the event
-
Re: using .getElementsByName
@J-Deezy : whan i add "handles wbEURC.DocumentCompleted" it gives me below error :
" Method 'Private Sub wbEURC_DocumentComplete(pDisp As Object, URL As Object)' cannot handle Event 'Public Event DocumentCompleted(sender As Object, e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs)' because they do not have the same signature "
-
Re: using .getElementsByName
@paul : is this correct ?
Code:
Private Sub wbEURC_DocumentComplete(ByVal pDisp As Object, ByVal URL As Object) Handles wbEURC.DocumentCompleted
If wbEURC.ReadyState = WebBrowserReadyState.Complete Then
MsgBox("Web document is finished downloading")
With wbEURC.Document
.GetElementById("ctl00$ContentPlaceHolder1$txtSrNumber").InnerText = Me.txtRCNum.Text 'pass requst #
'
.GetElementById("ctl00$ContentPlaceHolder1$btn_search").RaiseEvent("Click")
' click on Go
End With
End If
End Sub
-
Re: using .getElementsByName
.GetElementById("ctl00$ContentPlaceHolder1$btn_search").invokemember("Click")
-
Re: using .getElementsByName
Should look like this (different ByVals)
vb Code:
Private Sub wbEURC_DocumentCompleted(ByVal sender As Object, ByVal e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles wbEURC.DocumentCompleted
If wbEURC.ReadyState = WebBrowserReadyState.Complete Then
MsgBox("Web document is finished downloading")
With wbEURC.Document
.GetElementById("ctl00$ContentPlaceHolder1$txtSrNumber").InnerText = Me.txtRCNum.Text 'pass requst #
'
.GetElementById("ctl00$ContentPlaceHolder1$btn_search").RaiseEvent("Click")
' click on Go
End With
End If
End Sub
Does the contained code even work? I didn't think you could just change the inner text of an element, only the value.
-
Re: using .getElementsByName
Ok i've got till here...
open the page > insert the tkt # in search text box > click on "Go" (search) , i have inserted this code under wbEURC_documentcompleted event, i tried with a single tkt # & it bloody loops with single tkt # !!!
below is wht i'm using ....
Code:
Private Sub wbEURC_DocumentCompleted(ByVal sender As Object, ByVal e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles wbEURC.DocumentCompleted
If wbEURC.ReadyState = WebBrowserReadyState.Complete Then
stSbar.Text = ("Web document is finished downloading")
With wbEURC.Document
.GetElementById("ctl00$ContentPlaceHolder1$txtSrNumber").InnerText = Me.txtRCNum.Text 'pass requst #
.GetElementById("ctl00_ContentPlaceHolder1_btn_search").InvokeMember("click")' click on Go
End With
End If
End Sub
it just keeps searching the same tkt # over & over again ! how do i stopt it after 1st execution ?
-
Re: using .getElementsByName
Also is can some1 tell me wht is wrong with below code , i wrote this to freeze the execution till page is loaded :
Code:
Sub Wait(ByVal wbEURC)
While wbEURC.ReadyState = WebBrowserReadyState.Loading
Threading.Thread.Sleep(100)
End While
End Sub
OR
Code:
Sub Wait(ByVal wbEURC)
While wbEURC.ReadyState < 4
Threading.Thread.Sleep(100)
End While
End Sub
i simply need a fuction to pause the code till page is loaded with in the webbrowser control...
-
Re: using .getElementsByName
Well if thats in the main thread, you will hang your entire app permanently, as you can't sleep the thread and load the webpage asynchronously from the same thread. You'd need to create a new thread for that wait sub.
vb Code:
Dim nT As New Threading.Thread(AddressOf wait)
nT.Start()
Private Sub wait()
While WebBrowser1.ReadyState < 4
Threading.Thread.Sleep(100)
End While
'//next call after WebBrowser is finished loading
End Sub
As for only doing it once, you need to narrow down when the procedure is run on the documentcompleted event. At the moment, whenever the document finishes loading it will run. Either slip in a global boolean that you set by default to true, on the documentcompleted event check if this is true or not, and if so run it and then set the value to false to prevent further execution.
-
Re: using .getElementsByName
give me error :
Specified cast is not valid.
on line # 6
if i'm not wrong i cannot refer to form components from the thread's sub , correct ?
-
Re: using .getElementsByName
Oh yeah I forgot that there's always problems with accessing via threads, I've been meaning to have a look at documentation on that for ages.
The only (very messy) suggestion I can make to work-around not being able to access it directly is to create another global variable such as "isWbReady" (boolean) and set it to false, then create a timer with interval of 300-500 or so, and add
Code:
If WebBrowser1.ReadyState < 4 then
isWbReady = False
Else
isWbReady = True
Timer1.Stop()
End If
Then change your sub slightly to this:
Code:
Private Sub Wait()
While (isWbReady = False)
Threading.Thread.Sleep(100)
End While
'//next procedure
End Sub
You might have to turn of the "checkforillegalcrossthreadcalls" property though.
Sorry, it's really messy.
-
Re: using .getElementsByName
ok i have this :
Code:
Sub Wait(ByVal wb)
Do
Threading.Thread.Sleep(500)
Label1.Text = "Waiting..."
Me.Refresh()
Loop While wb.ReadyState < 4 Or Me.wb.IsBusy = True
End Sub
How do i make this run in a seperate thread ?
-
Re: using .getElementsByName
also i found out "links" property for htmldocument , can some 1 tell me how do i get element id's or inner text of all the links on a page ?
-
Re: using .getElementsByName
Quote:
Originally Posted by
sk8er_boi
also i found out "links" property for htmldocument , can some 1 tell me how do i get element id's or inner text of all the links on a page ?
What do you mean "links" property? You mean the tagname for links or what? And you need to stop thinking of everything in terms of elementID's as well, elementID is a means to an end...you're looking for the end result, not trying to complicate it by stepping backwards to go forwards.
-
Re: using .getElementsByName
@ J-Deezy : i really appreciate ur help (and patience ! ) , i knw i'n getting confused but i'm a rookie with vb .net & it's kinda my hobby, now i really cnt sleep peace fully until i complete this !!!
i mean using this :
http://msdn.microsoft.com/en-us/libr...ent.links.aspx
using this can i save all the links in a array & then send "click" event to the 1 i need
-
Re: using .getElementsByName
Sorry I've never used properties before and so I'm not quite sure how to use that :eek:
I thought you'd already figured out how to find your element and everything?
As for creating a thread for the wait sub, I went through that, in detail a few posts ago.