I've been trying to figure this out for a long time... finally got it. This function allows you to specify the text a a link that you want to actvate on a webpage and it will click it for you.
Dale
Note: Requires the post 3.1.1 betas for COM support
Plain Text
$ObjIE = ObjCreate ("InternetExplorer.Application")
With $ObjIE
.Visible = True
.Navigate ("<a href='http://www.autoitscript.com/' class='bbc_url' title='' rel='norewrite'>http://www.autoitscript.com/"</a>)
While .ReadyState <> 4
Sleep(50)
WEnd
EndWith
clickLink($ObjIE, "forum", 2)
Exit
Func clickLink($obj, $searchText, $instance = 1)
; clickLink( $obj, $serachText [, $instance])
; $obj - Object Valiable pointing to an InternetExplorer.Application object
; $searchText - the text displayed on the web page for the desired link to click
; [$instance] - if the link text occurs more than once, specify which instance you want to click (numbering starts at 1)
$doc = $obj.document
$links = $doc.links
$found = 0
For $link in $links
$linkText = $link.outerText
If $linkText = $searchText Then
$found = $found + 1
if ($found = $instance) Then
$result = $link.click
ExitLoop
EndIf
EndIf
Next
EndFunc ;==>clickLink
Contributions: UDF _DateYearFirstChildren are like Farts, you can just about stand your own.Why am I not a Vegetarian?...Well...my ancestors didn't fight & evolve to the Top of the food chain for me to survive on Salad
It does not still find exact matches, though! - if i look for "Edit Post", it finds all manner of links; sure, I can specify them by picking link number, but this was not your intention? I think your matching line needs fixing, but don't know the syntax;
$doc = $obj.document $links = $doc.links $found = 0 For $link in $links $linkText = $link.outerText If ($linkText = $searchText) Then
EDIT - I thought this script had a problem; but I see it is just that I don't know how to retrieve the text items from the variables - or ? from the function; I cannot use "return" from the function to seem to get any text? Can anybody please help? *** -I will post on Support as well, thanks Best, Randall
It does not still find exact matches, though! - if i look for "Edit Post", it finds all manner of links; sure, I can specify them by picking link number, but this was not your intention?
I think your matching line needs fixing, but don't know the syntax;
Can anybody please help? It should be correct?- is it a bug?; I think this is trying to compare a link number with the text?
@radallc: I don't know why you'd get unpredictable links -- it is doing an exact match. After the "For $ link in $links" line you might want to insert something like this so you can better see what is happening: ConsoleWrite("$linkText = " & $link.outerText & @CR)
@LOULOU: regarding frames -- I haven't tested, but it is an issue. We'll have to figure out how to interate through the documents in the frameset -- drop an example of a framed page with a link you wnat here and I'll have a look.
it seems to match the "$LinkText" as equal when it is "0"; (which seems to be the button links). So Button links are included in "links" but no text retrieved, and then matched as equal despite being zero! What else....? So in the "if =" statement I can access the other links if I "And $Link<>0".
If ($linkText = $searchText) and ($linkText<>"0") Then
It is actually a button I'm trying to click right now! Randall
PS When I do get a link matched, I am not getting to the link anyway as "popup blocked"; asks for "control-click"; can we do that in this script?
OK, so I have the frames figured out. New functions here to be able to get info on Frames and to create an object variable pointing to the frame window.
Also believe there is a fix here for links that were being matched when there was no link text.
In addition, there is a new function here to click a link based on its 0 based index instead of matchine text... this allows clicking links even if they are images and have no text.
Sometimes a link requires using ctrl-click to get around a pop-up blocker... I don't know how to do that and my search has come up dry so far.
Enjoy!
Dale
Example calling script:
Plain Text
; Open browser, load a page and wait for load to complete
$ObjIE = ObjCreate ("InternetExplorer.Application")
With $ObjIE
.Visible = True
.Navigate("<a href='http://www.mme.state.va.us/' class='bbc_url' title='External link' rel='norewrite nofollow external'>http://www.mme.state.va.us/"</a>)
While .ReadyState <> 4
Sleep(50)
WEnd
EndWith
ConsoleWrite(_IE_IsFrameSet($ObjIE) & @CR)
ConsoleWrite(_IE_NumFrames($ObjIE) & @CR)
; Loop through the frames and show the URL of each
For $i = 1 To _IE_NumFrames($ObjIE)
$ObjF = _IE_FrameObj($ObjIE, $i - 1)
ConsoleWrite("Frame" & $i & " - " & $ObjF.document.location.href & @CR)
Next
; Click on the "Our Values" link in the third frame (0 based)
_IE_clickLinkText(_IE_FrameObj($ObjIE, 2), "Our Values")
; Click on the third link on the third frame
;_IE_clickLinkIndex(_IE_FrameObj($ObjIE, 2), 2)
Exit
Functions:
Plain Text
Func _IE_IsFrameSet($_obj)
; Returns 1 if the object references a FrameSet page, else 0
;
; Note: this is more reliable test for a FrameSet than checking the
; number of frames (...frames.length) because an iFrame embedded on a normal
; page is included in the frame collection
$_t = $_obj.document.body.tagName
If $_t = "FRAMESET" Then
Return 1
Else
Return 0
EndIf
EndFunc ;==>_IE_IsFrameSet
Func _IE_NumFrames($_obj)
; Returns the number of frames in a FrameSet or the number of iFrames on a normal page
Return $_obj.document.parentwindow.frames.length
EndFunc ;==>_IE_NumFrames
Func _IE_FrameObj($_obj, $_f)
; Returns an object reference to a window within the specified frame (note that frame collection is 0 based)
; This object can be used in the same manner as the InternetExplorer.Application object
If IsObj ($_obj.document.parentwindow.frames.item ($_f)) Then
Return $_obj.document.parentwindow.frames.item ($_f)
Else
Return 0
EndIf
EndFunc ;==>_IE_FrameObj
Func _IE_clickLinkText($_obj, $_l, $_i = 1)
; _IE_clickLinkText( $_obj, $_l [, $_i])
; $_obj - Object Valiable pointing to an InternetExplorer.Application object
; $_l - linkText, the text displayed on the web page for the desired link to click
; [$_i] - if the link text occurs more than once, specify which instance you want to click
; note: instance numbering starts at 1
$doc = $_obj.document
$links = $doc.links
$found = 0
For $link in $links
$linkText = $link.outerText & ""; Append empty string to prevent problem with no outerText (image) links
;ConsoleWrite("$linkText = " & $linkText & @CR)
ConsoleWrite("$linkText = " & $link.href & @CR)
If $linkText = $_l Then
$found = $found + 1
if ($found = $_i) Then
$result = $link.click
return 1
EndIf
EndIf
Next
return 0
EndFunc ;==>_IE_clickLinkText
Func _IE_clickLinkIndex($_obj, $_i)
; _IE_clickLinkText( $_obj, $_i)
; $_obj - Object Valiable pointing to an InternetExplorer.Application object
; $_i - 0 based index of the link number to click
$doc = $_obj.document
if IsObj($doc.links($_i)) Then
ConsoleWrite("$linkHref = " & $doc.links($_i).href & @CR)
$doc.links($_i).click
return 1
Else
return 0
EndIf
EndFunc ;==>_IE_clickLinkIndex
Haven't done much testing yet, but this function seems to work. I think there is more tha can be done to generalize this because many objects can return a ReadyState...
Func _IE_ReadyState($_obj)
; Returns ReadyState value for Window or Frame objects
Return $_obj.document.ReadyState
EndFunc ;==>_IE_ReadyState
Haven't done much testing yet, but this function seems to work. I think there is more tha can be done to generalize this because many objects can return a ReadyState...
Func _IE_ReadyState($_obj)
; Returns ReadyState value for Window or Frame objects
Return $_obj.document.ReadyState
EndFunc ;==>_IE_ReadyState
I'm keen to keep this developing; here's my attempt to use Scripkitty's" form as well to do a listing of
1. All links and forms if no frames at a site.
2. Same for all links and forms within frames (needs the different calls) at that site
(please try it in your original site)
Do you think the forms are likely to work in forms with frames?; do you know of a site I could test?
I'm keen to keep this developing; here's my attempt to use Scripkitty's" form as well to do a listing of
1. All links and forms if no frames at a site.
2. Same for all links and forms within frames (needs the different calls) at that site
(please try it in your original site)
Do you think the forms are likely to work in forms with frames?; do you know of a site I could test?
If you use the UDFs that I created here to create an object pointing to a Frame Window, you do not have to special-case documents with frames. I don't think it makes a lot of sense to have a set of funtions for regular documents and another for frames... just check for frames, then get the frame object and use it like a normal IE object.
Regarding forms in frames -- once you have the frame window object there is nothing special about the fact that they happen to be displayed in a frame, so there should be no issue.
I'm not sure what you mean; you have used 3 different calls for in or out of frames;
clickLink($ObjIE, "forum", 2)
_IE_clickLinkText(_IE_FrameObj($ObjIE, 2), "Our Values")
;_IE_clickLinkIndex(_IE_FrameObj($ObjIE, 2), 2)
Are you saying (assuming I want to click as chosen by a "value" of some kind) that i can simplify the code to
1. List all possible clicks or fields (eg input for user from listview box)
2. Enter or read fields or links as cchosen
whether in frame or not?
What if you wanted to click ot list all fields returnig "Virginia" whether in form or frame?
Thanks, Randall
I guess I was confused about your question. What I'm saying about frames is that the _IE_FrameObj($_obj, $_f) function can be used to get the window object for a specific frame... use that object in place of the $ObjIE references you see in most of the COM examples here and it works the same.
If you are asking about 'clicking' forms, that is is a different issue and may be what I missed in your question. None of the functions here are designed to do that -- there are better ways to work with forms.
There is a seperate form collection within each document, the form elements for each can be manipulated and the form has a submit method you can call.
The functions in this thread are primarily for <a href= types of links on a page.
I've been trying to figure this out for a long time... finally got it. This function allows you to specify the text a a link that you want to actvate on a webpage and it will click it for you.
Dale
Note: Requires the post 3.1.1 betas for COM support
Plain Text
$ObjIE = ObjCreate ("InternetExplorer.Application")
With $ObjIE
.Visible = True
.Navigate ("http://www.autoitscript.com/")
While .ReadyState <> 4
Sleep(50)
WEnd
EndWith
clickLink($ObjIE, "forum", 2)
Exit
Func clickLink($obj, $searchText, $instance = 1)
; clickLink( $obj, $serachText [, $instance])
; $obj - Object Valiable pointing to an InternetExplorer.Application object
; $searchText - the text displayed on the web page for the desired link to click
; [$instance] - if the link text occurs more than once, specify which instance you want to click (numbering starts at 1)
$doc = $obj.document
$links = $doc.links
$found = 0
For $link in $links
$linkText = $link.outerText
If $linkText = $searchText Then
$found = $found + 1
if ($found = $instance) Then
$result = $link.click
ExitLoop
EndIf
EndIf
Next
EndFunc ;==>clickLink
On mine this program does not search for the text of the name of the button, and simply touches all Links on page.
Try instead of clickLink ($ObjIE, "forum", 2)
Sorry, I'm not certain what you are saying. What is written here is primarily for <a href= links, not for graphic buttons. There is an updated set of functions later in the post that 1) fix a bug that caused an erroneous match when there was no link text (like img links) and 2) added the ability to activate a link by index rather than text.
Please try the newer functions and let me know if you still have questions or trouble.
$ObjIE = ObjCreate ("InternetExplorer.Application")
With $ObjIE
.Visible = True
.Navigate ("<a href='http://webdesign.about.com/library/weekly/n030600.htm' class='bbc_url' title='External link' rel='nofollow external'>http://webdesign.about.com/library/weekly/n030600.htm"</a>)
While .Busy
Sleep(50)
WEnd
EndWith
;Sleep(2000)
clickLink($ObjIE, "click to open")
Exit
Func clickLink($obj, $searchText, $instance = 1)
; clickLink( $obj, $serachText [, $instance])
; $obj - Object Valiable pointing to an InternetExplorer.Application object
; $searchText - the text displayed on the web page for the desired link to click
; [$instance] - if the link text occurs more than once, specify which instance you want to click (numbering starts at 1)
$doc = $obj.document
$links = $doc.links
$found = 0
For $link in $links
$linkText = $link.outerText
If StringInStr($linkText, $searchText) Then
$found = $found + 1
if ($found = $instance) Then
$result = $link.click
ExitLoop
EndIf
EndIf
Next
EndFunc ;==>clickLink
Did you see my posts on this thread, and the modified scrip by Dale in the thread; to access links in frames and forms in frames; your scrip duplicates his first one only, and therefore is no more widely applicable?....
I am optimistic we might be able to get a decent function which will click on any of the options, no matter what sort of page, including frames and forms, by search criteria.
OK, I think it's time to start working on some formal UDFs for IE Automation. I've read up on the standards and and starting some work on them. More soon.