After having built out a shell for the Internet Explorer
(IE) object in a class module, we are now ready to start adding some useful
functionality. It is important to note that without adding these methods the IE
Agent will not be able to perform any functions other than being created as the
actual IE object is hidden behind the IE Agent (see my previous post about
setting up an IE Agent).
Some key features we will focus on is wrapping up code
blocks inside methods that would normally have to be written out every time you
would call the basic IE methods on the reference IE object discussed
previously. Other methods will focus around navigating the DOM, opening up
tabs, and opening up webpages.
Adding Basic Browsing Functionality
Some of the basic functions of IE are 1) opening web pages,
2) opening web pages in new tabs, 3) changing the state of the webpage through
clicking on buttons, table cells, etc., and 4) downloading files from a remote
server. Each of these functions are performed in a browser via mouseclicks and
keyboard input. But during automation you cannot do any of these things using a
mouse or a keyboard. Thus we are given a framework from which we can do all of
these things programmatically.
Opening Web Pages
The most basic function of the browser is to open a webpage.
This is a relatively straightforward event for someone using a browser, and so
it is also fairly straightforward for automation. However, there are some
issues that a human will be able to overcome intuitively that a script
automation must account for, such as waiting for a page to load.
To begin, pull up the IEAgent we developed in the previous
post. Since IE needs to load the page completely before any actions can occur,
it is necessary to write a wait method. Add this code to your module below:
Sub waitForLoad()
'pauses the exection of the code until the webpage has loaded
Do
If Not ie.Busy And ie.ReadyState = 4 Then
application.Wait (Now + TimeValue("00:00:01"))
If Not ie.Busy And ie.ReadyState = 4 Then
Exit Do
End If
End If
DoEvents
Loop
End Sub
'pauses the exection of the code until the webpage has loaded
Do
If Not ie.Busy And ie.ReadyState = 4 Then
application.Wait (Now + TimeValue("00:00:01"))
If Not ie.Busy And ie.ReadyState = 4 Then
Exit Do
End If
End If
DoEvents
Loop
End Sub
The above code enters a loop that checks the state of IE
every millisecond (which is an eternity in computer time) and won’t give up
control of the program until IE is ready. Note that the IE object was defined
during the setup of the IEAgent. This function will be used multiple times
within the IEAgent as well as in the parts of a script where the IEAgent is
used.
Next we will add a method that will accept an URL Address and
then opens the page. This will employ the previous method so that nothing will
happen to the page until it is fully loaded.
Sub openpage(url As String)
'opens the specified url in internet explorer
ie.navigate url
waitForLoad
End Sub
'opens the specified url in internet explorer
ie.navigate url
waitForLoad
End Sub
The function called on the IE object (navigate) is a
predefined function written by Microsoft to aid developers. You don’t have to
worry at all about what is going on underneath, just know that it will open any
page that you normally would through regular browsing. It then calls the
waitForLoad function, thus allowing the page to be in a ready state before any
other functions are called.
Advanced Page Loading
Microsoft has provided many ways for someone to write code
to automate a process. This is nice as it lends itself to be highly extendable
to other areas, but it also means that some things aren’t available in one
method that is available in another. The following is a means to open up a
webpage using what is called a shell object. For most uses the previous version
will suffice, but use of the shell opens up possibilities such as opening
multiple windows or tabs at once. Other advantages include using an already
open instance of IE by grabbing it’s handle (handles discussed in previous post).
Don’t worry about knowing what a shell is or how it is
implemented, but if you want to do some of these things, then adding this code
is necessary. My suggestion is to add it as it is not a whole lot of code and
will give your code more flexibility to work in the future.
To start, add these two lines above the variables defined at
the top of the IEAgent.
Private Declare Sub Sleep Lib "kernel32" (ByVal
dwMilliseconds As Long)
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
The top of your IEAgent should now look something like this:
These are additional APIs used to provide access to the
shell objects built in to Windows and to provide a function to stall the
execution of the program. These have many parameters that are needed, but the
provided example will do the job in opening up additional tabs within an
instance of IE.
Sub openPageInTab(url as String, newHandle as long)
Sleep 1000
ShellExecute newHandle, "open", url, vbNullString, vbNullString, vbMaximizedFocus
End Sub
Sleep 1000
ShellExecute newHandle, "open", url, vbNullString, vbNullString, vbMaximizedFocus
End Sub
This article
provides additional information on the ShellExecute function. For our purposes,
this will take a URL and open up a tab in the browser with the given handle. To
open up a new tab using the IEAgent, you will call this code as follows:
openPageInTab(“www.google.com” , handle)
The url will lead to google.com, and the handle is the
handle defined at the top of the IEAgent as shown in the picture above.
Remember that this handle was set upon creation of the IEAgent, so you don’t
have to worry about getting the handle in any way. Simply place the handle
variable into this method’s parameter and it will open a tab inside the IE browser.
Note that if you want to open up a URL in another instance
of a browser (say you wanted to use Firefox or Google Chrome), you can call
that browser using this function and open up the tabs in that browser. This is
not always a good practice to do as it breaks a concept called encapsulation
in some ways, but for our purposes we will leave this option open. Because our
task is automating processes, it may be necessary to occasionally open up
another browser for whatever reason. Therefore we keep this method here as it
doesn’t make much sense to make a separate module to do this. This is an
example of when good form gives way to practical design.
Other Basic IE Functions
Part of automating processes is deciding what parts of the
process the user needs to see. Microsoft has developed a means to turn off
window visibility for IE, allowing you to navigate in IE without the user ever
seeing the browsing window. This has advantages as it doesn’t require IE to
render anything, so turning off visibility will create time savings.
To turn on and off visibility with the IEAgent, add the
following code:
'Set visibility of ie
Public Property Let visible(theValue As Boolean)
ie.visible = theValue
End Property
Public Property Let visible(theValue As Boolean)
ie.visible = theValue
End Property
To call this code, do the following:
ieAgent.visible = True
You can also set it False. This is a property function,
meaning that whatever you can set parameters in VBA using the = and not the .()
pattern. Personally I don’t like this method, but I thought that I would add it
in here to show a new way of setting variables in VBA. You may come across this
pattern in the future. I would avoid this and instead do the following:
'Set visibility of ie
Sub visible(theValue As Boolean)
ie.visible = theValue
End Property
Sub visible(theValue As Boolean)
ie.visible = theValue
End Property
To call this code, do the following:
Call ieAgent.visible(True)
You can use the first pattern to set any property of a class
object and also to run code. You can also get properties (like the handle for
the IE object in the IEAgent) by using the following code:
Public Property Get getHandle() As Long
getHandle = handle
End Property
getHandle = handle
End Property
Handle has been defined at the top of the IEAgent, and so
this is simply returning the variable.
Completed IE Tools
This concludes the portion of filling out the basic IE
functions you will need to automate IE. The next blog post will discuss adding
methods to navigate across the DOM.
No comments:
Post a Comment