I am trying to speed up some intranet webscraping as well as make it more reliable. I am just learning how to implement XMLHTTP and I need some advice on converting my code from IE based scrapping to XMLHTTP.
I have 2 subs in my module that accomplishes loading up and navigating the intranet site (GetWebTable) and parsing through the data (GetOneTable) to return a table in excel. The subs are as follows:
Sub GetWebTable(sAccountNum As String)
On Error Resume Next
Dim objIE As Object
Dim strBuffer As String
Dim thisCol As Integer
Dim iAcctCount As Integer
Dim iCounter As Integer
Dim iNextCounter As Integer
Dim iAcctCell As Integer
Dim thisColCustInfo As Integer
Dim iErrorCounter As Integer
If InStr(1, sAccountNum, "-") <> 0 Then
sAccountNum = Replace(sAccountNum, "-", "")
End If
If InStr(1, sAccountNum, " ") <> 0 Then
sAccountNum = Replace(sAccountNum, " ", "")
End If
iErrorCounter = 1
TRY_AGAIN:
'Spawn Internet Explorer
Set objIE = GetObject("new:{D5E8041D-920F-45e9-B8FB-XXXXXXX}")
DoEvents
With objIE
.Visible = False
.Navigate "http://intranetsite.aspx"
While .busy = True Or .readystate <> 4: DoEvents: Wend
While .Document.readyState <> "complete": DoEvents: Wend
.Document.getElementById("ctl00_MainContentRegion_tAcct").Value = sAcct
While .busy = True Or .readyState <> 4: DoEvents: Wend
While .Document.readyState <> "complete": DoEvents: Wend
.Document.getElementById("ctl00_MainContentRegion_btnRunReport").Click
While .busy = True Or .readyState <> 4: DoEvents: Wend
While .Document.readyState <> "complete": DoEvents: Wend
End With
thisCol = 53
thisColCustInfo = 53
GetOneTable objIE.Document, 9, thisCol
'Cleanup:
objIE.Quit
Set objIE = Nothing
GetWebTable_Error:
Select Case Err.Number
Case 0
Case Else
Debug.Print Err.Number, Err.Description
iErrorCounter = iErrorCounter + 1
objIE.Quit
Set objIE = Nothing
If iErrorCounter > 4 Then On Error Resume Next
GoTo TRY_AGAIN
'Stop
End Select
End Sub
Sub GetOneTable(varWebPageDoc, varTableNum, varColInsert)
Dim varDocElement As Object ' the elements of the document
Dim varDocTable As Object ' the table required
Dim varDocRow As Object ' the rows of the table
Dim varDocCell As Object ' the cells of the rows.
Dim Rng As Range
Dim iCellCount As Long
Dim iElemCount As Long
Dim iTableCount As Long
Dim iRowCount As Long
Dim iRowCounter As Integer
Dim bTableEndFlag As Boolean
bTableEndFlag = False
For Each varDocElement In varWebPageDoc.all
If varDocElement.nodeName = "TABLE" Then
iElemCount = iElemCount + 1
End If
If iElemCount = varTableNum Then
Set varDocTable = varDocElement
iTableCount = iTableCount + 1
iRowCount = iRowCount + 1
Set Rng = Worksheets("Sheet1").Cells(2, varColInsert)
For Each varDocRow In varDocTable.Rows
For Each varDocCell In varDocRow.Cells
If Left(varDocCell.innerText, 9) = "Total for" Then
bTableEndFlag = True
Exit For
End If
Rng.Value = varDocCell.innerText
Set Rng = Rng.Offset(, 1)
iCellCount = iCellCount + 1
Next varDocCell
iRowCount = iRowCount + 1
Set Rng = Rng.Offset(1, -iCellCount)
iCellCount = 0
Next varDocRow
Exit For
End If
Next varDocElement
Set varDocElement = Nothing
Set varDocTable = Nothing
Set varDocRow = Nothing
Set varDocCell = Nothing
Set Rng = Nothing
End Sub
Any thoughts?
HTML is not XML. XML is strictly enforced is terms of opening and closing tags whilst HTML is famous for <br> tags without closuing </br>. You'd be very lucky if the HTML is XML compliant.
Anyway, if you want to use XMLHTTP because of the HTTP request and still keep your IE based web scraping code then see this article http://exceldevelopmentplatform.blogspot.com/2018/01/vba-xmlhttp-request-xhr-does-not-parse.html It shows how to use XMLHTTP before passing response to MSHTML.
You can use MSHTML independently of IE, see this article Use MSHTML to parse local HTML file without using Internet Explorer (Microsoft HTML Object Library). If you read that you will see much of the code that you write against the IE object model is in fact aaginst the MSHTML object model and as such you can decouple and jettison IE. Enjoy!
EDIT1: Don't forget you can ask your company's IT staff
You say it is an intranet site which implies internal to your company, you could ask the programmers who are responsible for that system for a direct API guide.
EDIT2: Folding in feedback about how to mimic a browser...
To mimic the browser you need to figure out the traffic that button clicks generate...
To watch network traffic I recommend you switch to Chrome as your browser. Then, on this web page, right-click mouse button and take "Inspect" menu option, this opens the Chrome Developer Tools. Then, in Developer Tools select the Network tab, then click on a link on this page and you will see the traffic that is generated.
So, if you want to go pure XMLHTTP and leave browsers behind then you won't have buttons available to click but you can observe the network traffic that happens when a button is clicked in a browser and you can then mimic this in code.
So for example, in your comment you ask how do I enter an account number and click the button. I'm guessing that clicking a button will result in a XMLHTTP call of something like http://example.com/dowork/mypage.asp?accountnumber=1233456&otherParams=true so you see account number would be buried in the query parameters. Once you have that url you can put that in your XMLHTTP request.
One potential problem is that system designers may have chosen to hide account numbers in the body of a HTTP POST because it is sensitive/confidential data. However, Chrome Developer Tools is very good and should still yield that information but may have to poke around.
Related
I inherited this VBA script from my predecessor. It works fine for me in Excel 2013 up until recently when I was told I may need to work from home. Come to find out, the Office 2016 environment of my newly accessed VPN desktop does not like this script. I keep getting "The remote server machine is unknown or unavailable" when it reaches .ReadyState <> READYSTATE_COMPLETE.
The navigation did not fail as I can see the window where it successfully navigated to the URL and I can interact with it correctly. The strange thing is if I change the URL to "www.google.com" I get a valid ready state result.
I also need to figure out how to late bind the Shell Windows so it will work with both the v15 and v16 libraries simultaneously.
The intent of this script is to automate a process that
1. Opens an internal database at DBurl via web interface
2. Manipulates and runs a java script located on the web page
3. Close the browser window without closing any other browser windows
This could be modified for someone else's use by looking for a page element, such as a search box or specific button on a page, and interacting with it.
Edit:
Additional testing has revealed that a pause at and skipping the Do While loop and resuming at IETab1 = SWs.Count results in this script working in Office 2016. The only issue, then, is without the loop, the page isn't yet ready for the next step when the script tries to run the interaction. A wait for 5 seconds in place of the loop band-aid's this issue. Finding why the .ReadyState won't read will fix this issue.
Declare PtrSafe Function apiShowWindow Lib "user32" Alias "ShowWindow" _
(ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Sub OpenWebDB()
Dim ieApp As Object
Dim SWs As ShellWindows
Dim IETab1 As Integer
Dim JScript As String
Dim CurrentWindow As Object
Dim DBurl As String
Dim tNow As Date, tOut As Date
DBurl = "My.Database.url"
Set SWs = New ShellWindows
tNow = Now
tOut = tNow + TimeValue("00:00:15")
If ieApp Is Nothing Then
Set ieApp = CreateObject("InternetExplorer.Application")
With ieApp
.Navigate DBurl
Do While tNow < tOut And .ReadyState <> READYSTATE_COMPLETE
DoEvents
tNow = Now
Loop
IETab1 = SWs.Count
End With
End If
If Not tNow < tOut Then GoTo DBFail
On Error GoTo DBFail
Set CurrentWindow = SWs.Item(IETab1 - 1).Document.parentWindow
JScript = "javascript: DoSomething"
Call CurrentWindow.execScript(JScript)
On Error GoTo 0
SWs.Item(IETab1 - 1).Quit
Set ieApp = Nothing
Set SWs = Nothing
Exit Sub
DBFail:
MsgBox (DBurl & vbCrLf & "took too long to connect or failed to load correctly." & vbCrLf & _
"Please notify the Database manager if this issue continues."), vbCritical, "DB Error"
SWs.Item(IETab1 - 1).Quit
Set ieApp = Nothing
Set SWs = Nothing
End Sub
Try to remove the tNow < tOut from the Do While condition. Or, using the While statement to wait page complete:
While IE.ReadyState <> 4
DoEvents
Wend
The intent of this script is to automate a process that
1. Opens an internal database at DBurl via web interface
2. Manipulates and runs a java script located on the web page
3. Close the browser window without closing any other browser windows
Besides, according to the intent of the script, I suggest you could refer the following code (it could loop through the tabs, and close specific tab according the title):
Sub TestClose()
Dim IE As Object, Data As Object
Dim ticket As String
Dim my_url As String, my_title As String
Set IE = CreateObject("InternetExplorer.Application")
With IE
.Visible = True
.Navigate "https://www.microsoft.com/en-sg/" '1st tab
.Navigate "https://www.bing.com", CLng(2048) '2nd
.Navigate "https://www.google.com", CLng(2048) '3rd
While IE.ReadyState <> 4
DoEvents
Wend
'wait some time to let page load
Application.Wait (Now + TimeValue("0:00:05"))
'get the opened windows
Set objShell = CreateObject("Shell.Application")
IE_count = objShell.Windows.Count
'loop through the window and find the tab
For x = 0 To (IE_count - 1)
On Error Resume Next
'get the location and title
my_url = objShell.Windows(x).Document.Location
my_title = objShell.Windows(x).Document.Title
'debug to check the value
Debug.Print x
Debug.Print my_title
'find the special tab based on the title.
If my_title Like "Bing" & "*" Then
Set IE = objShell.Windows(x)
IE.Quit 'call the Quit method to close the tab.
Exit For 'exit the for loop
Else
End If
Next
End With
Set IE = Nothing
End Sub
Thanks in advance for your answers.
I have a little Excel document that is made so that the naïve user can enter web pages in an Excel sheet, hit a button, and play the videos from that page in their browser, in full screen, and automatically loop the videos without any further user interaction. It basically creates a slide show of videos.
I originally made it for YouTube and it works fine there. I'm now trying to expand it to use another site. It works as planned but needs an extra step.
Whereas YouTube was made with a Full Screen mode that I can access programatically, this website has embedded videos. (An example: https://www.sharecare.com/video/health-topics-a-z/copd/what-can-i-do-to-prevent-my-copd-from-getting-worse).
You can see in the code that I open IE in full screen mode (which it does) but that's the full web page (header, side banner etc.). I want the video from that page to be the only element, full screen.
If I physically go into the page I can select for the video to play full screen. I've tried searching for various ways to do this, but most of the posts are for something else or how to get a video to play inside Excel rather than what I'm doing.
Sub StartLooping()
Dim IEapp As Object
Dim VidAddr1, VidAddr2 As String
Dim AddrStrStart, AddrStrEnd As Long
Dim AddrFudge1, AddrFudge2 As Integer
Dim TimeStart, DurMin, DurSec, DurTot As Single
Dim LRAll, LRVid, LRMin, LRSec, LRVidB, LRMinB, LRSecB As Integer
Dim I As Integer
Application.EnableCancelKey = xlErrorHandler
On Error GoTo ErrorHandle
'Review Sheet
LRVid = Cells(Rows.Count, "D").End(xlUp).Row
LRMin = Cells(Rows.Count, "E").End(xlUp).Row
LRSec = Cells(Rows.Count, "F").End(xlUp).Row
LRVidB = Cells(Rows.Count, "I").End(xlUp).Row
LRMinB = Cells(Rows.Count, "J").End(xlUp).Row
LRSecB = Cells(Rows.Count, "K").End(xlUp).Row
LRAll = Cells(Rows.Count, "S").End(xlUp).Row
If LRVid <> LRMin Then
MsgBox "You have to include video address and how long (the minutes and the seconds - use 0 if needed)"
Exit Sub
End If
If LRVid <> LRSec Then
MsgBox "You have to include video address and how long (the minutes and the seconds - use 0 if needed)"
Exit Sub
End If
If LRVidB <> LRMinB Then
MsgBox "You have to include video address and how long (the minutes and the seconds - use 0 if needed)"
Exit Sub
End If
If LRVidB <> LRSecB Then
MsgBox "You have to include video address and how long (the minutes and the seconds - use 0 if needed)"
Exit Sub
End If
'Start of For-Next Loop
For I = 20 To LRAll
'Set Addr
'VidAddr1
If Len(Range("S" & I).Text) = 0 Then
Exit Sub
Else
VidAddr1 = Range("S" & I).Text
End If
VidAddr2 = VidAddr1
'Set Timer
TimeStart = Timer 'Start time
DurMin = Range("T" & I).Value
DurSec = Range("U" & I).Value
DurTot = (DurMin * 60) + DurSec
'Open the web page
Set IEapp = CreateObject("Internetexplorer.Application") 'Set IEapp = InternetExplorer
With IEapp
.Silent = True 'No Pop-ups
.Visible = True
.FullScreen = True
.Navigate VidAddr2 'Load web page
'Keep it open for the duration
Do While Timer < (TimeStart + DurTot)
'Check for Esc - refers to a public function
If KeyDown(vbKeyEscape) Then
IEapp.Quit
Set IEapp = Nothing
Exit Sub
End If
Loop
'Close the page
IEapp.Quit
Set IEapp = Nothing
End With
If I = LRAll Then I = 19
Next I
ErrorHandle:
MsgBox Err.Number & " " & Err.Description
Exit Sub
End Sub
I copied the code. It works fine. It's just that extra bit of "Oh, I did that, here's how to go about it" that I need.
The browser used is IE so I can keep it simple, but if this were possible in another common browser that would be good to know.
Here's the second set that I tried today (9/12)
Dim IEapp As Object
Dim IEAppColl As HTMLButtonElement
'Open doc
Set IEapp = CreateObject("Internetexplorer.Application") 'Set IEapp = InternetExplorer
With IEapp
.Silent = True 'No Pop-ups
.Visible = True
'.FullScreen = True
.navigate "https://www.sharecare.com/video/health-topics-a-z/copd/got-copd-ask-your-doctor-about-vitamin-d"
Do While .readyState < 4 Or .Busy
Loop
Set IEAppColl = IEapp.Document.getElementsByTagName("BUTTON")
If IEAppColl.Name = "Fullscreen" Then
IEAppColl.Click
End If
End With
For the example COPD page given this works with Selenium basic. You install from here and then go VBE > Tools > References > and add a reference to Selenium Type Library. You can also use an IEDriver to work with InternetExplorer rather than Chrome (which uses ChromeDriver).
Option Explicit
Public Sub PlayFullScreen()
Dim d As WebDriver, t As Date, ele As Object
Const MAX_WAIT_SEC As Long = 10
Set d = New ChromeDriver
Const URL = "https://www.sharecare.com/video/health-topics-a-z/copd/what-can-i-do-to-prevent-my-copd-from-getting-worse"
With d
.Start "Chrome"
.get URL
Do
DoEvents
On Error Resume Next
Set ele = .FindElementByCss("[title='Accept Cookies']")
If Timer - t > MAX_WAIT_SEC Then Exit Do
On Error GoTo 0
Loop While ele Is Nothing
Application.Wait Now + TimeSerial(0, 0, 1)
If Not ele Is Nothing Then ele.Click
.FindElementByCss("#myExperience").Click
Application.Wait Now + TimeSerial(0, 0, 1)
.FindElementByCss("[Title=Fullscreen]", timeout:=7000).Click
Stop '<==Delete me later
.Quit
End With
End Sub
My suggestion is to, instead of using a browser to play video, use a video player.
Under "More Controls" you should have a "Windows Media Player", and likely others, depending on what you have installed.
For example, I've used the VLC control on Access forms. When you install VLC it automatically adds the control to Office (so I assume Office has to be installed first.)
Here's a tutorial I found online:
Link: How to Play Video on Access Form
Random Tip Time:
It can be tricky to Google about a website because, for example, using the search term *YouTube* in a Google search results in a list of YouTube content (videos).
Exclude results from a specific site with Google's site: and - operators like:
"microsoft access" form play youtube video -site:youtube.com
...which is how I found the tutorial above, and several others.
Using the search term access can also be tricky to search for since it's such a common word, which is why I'll often enclose it in quotes like "MS Access" or "Microsoft Access" (like above), which makes Google search for those words in that order.
(More Google tips)
I've written some code in vba to get the movie names from a torrent website using .createDocumentFromUrl() method. As I've never worked with this method and haven't found any remarkable information either on it to successfully go with, I get stuck. I have tried to create a script, though.
Here is my try:
Sub Fromurl_Method()
Const URL As String = "https://yts.am/browse-movies"
Dim hStart As HTMLDocument, hdoc As HTMLDocument
Set hStart = New HTMLDocument
Set hdoc = hStart.createDocumentFromUrl(URL, vbNullString)
Do While hdoc.readyState = "loading" Or hdoc.readyState = "interactive": DoEvents: Loop
Debug.Print hdoc.DocumentElement.innerHTML
End Sub
When I execute the above script, it fetches some html elements which are not from that website. I took a closer look into the elements I have parsed and noticed this line on the top This content cannot be displayed in a frame. It is behaving the same way with most of the sites. How can I make it successful? Thanks in advance.
Once again, my intention is to parse all the movie names from that site using .createDocumentFromUrl().
Sub Get_Info()
Dim Elems, e As Variant
Const READYSTATE_COMPLETE& = 4&
Dim ie As Object
Set ie = Nothing
DoEvents
Set ie = CreateObject("InternetExplorer.Application")
DoEvents
With ie
.Visible = false
.Navigate "https://yts.am/browse-movies"
While Not .readyState = READYSTATE_COMPLETE
DoEvents
Wend
End With
Dim i As Double
With ie.Document
Set Elems = .getElementsByTagName("a")
DoEvents
i = 2
For Each e In Elems
If e.getAttribute("class") = "browse-movie-title" Then
Range("A" & i).Value = e.innerText
i = i + 1
End If
Next e
End With
Set Elems = Nothing
Set e = Nothing
ie.Quit
Set ie = Nothing
End Sub
The code above will give you a list of all movies. Just modify the code to adapt it to your needs of getting the first one if you only need the first one.
I am trying to scrape all the table from start page to end contents from this Webpage
Using the code below I can scrape the table contents of page 1 but I don't know how can I modify the code to get the data from start page to end.
Option Explicit
Sub NBAStats()
Dim IE As Object, obj As Object
Dim r As Integer, c As Integer, t As Integer
Dim elemCollection As Object
Set IE = CreateObject("InternetExplorer.Application")
With IE
.Visible = True
.navigate ("http://stats.nba.com/league/player/#!/")
While IE.ReadyState <> 4
DoEvents
Wend
Do While IE.busy: DoEvents: Loop
ThisWorkbook.Sheet1.Clear
Set elemCollection = IE.Document.getElementsByTagName("TABLE")
For t = 0 To (elemCollection.Length - 1)
For r = 0 To (elemCollection(t).Rows.Length - 1)
For c = 0 To (elemCollection(t).Rows(r).Cells.Length - 1)
ThisWorkbook.Worksheets(1).Cells(r + 1, c + 1) = elemCollection(t).Rows(r).Cells(c).innerText
Next c
Next r
Next t
End With
Set IE = Nothing
End Sub
Try to find the Sitemap.xml of the website you are scraping. The sitemap.xml fill have all the links present in the webpage.
Import that xml file to your Excel Sheet, Read each link & fetch each table in it.
At first, in my opinion VBA automation of the Internet Explorer is highly instable and not really practicable in productive use-cases. This means also scraping data from web sites which are provided only for viewing within a browser is not really practicable in productive use-cases. If you are entitled to use those data then you should ask for another data source (XML or JSONfor example). If you are not entitled then you should not do that. Possible the provider of the web site does not agree with this.
To be clear, I'm talking about web sites like this, which provides it's data with JavaScript only. If the data would be within the HTML then you could get those data via XMLHTTP. This is another thing.
I will nevertheless provide a "solution". So you can't simply think "He is simply unable to do this, so he is saying you should not do that."
So you must analyze the site and pick out the elements you can click for navigation.
Option Explicit
Sub NBAStats()
Dim IE As Object
Dim r As Long, c As Long, t As Long, rSheet As Long, rStart As Long
Dim bReady As Boolean
Dim elementsTable As Object
Dim elementsPageNavRigth As Object
Dim elemPageNavRigth As Object
Dim elementsTableDiv As Object
ThisWorkbook.Worksheets(1).Cells.Clear
Set IE = CreateObject("InternetExplorer.Application")
With IE
.Visible = True
.navigate ("http://stats.nba.com/league/player/#!/")
Do While IE.busy
DoEvents
Loop
rSheet = 0
Do
Do While elementsTableDiv Is Nothing
Set elementsTableDiv = IE.Document.getElementsByClassName("table-responsive")
DoEvents
Loop
Do While elementsTableDiv(0) Is Nothing
DoEvents
Loop
Set elementsPageNavRigth = IE.Document.getElementsByClassName("page-nav right")
Set elemPageNavRigth = elementsPageNavRigth(0)
If elemPageNavRigth.className = "page-nav right disabled" Then bReady = True
'If rSheet = 0 Then rStart = 0 Else rStart = 1
Set elementsTable = elementsTableDiv(0).getElementsByTagName("TABLE")
For r = rStart To (elementsTable(0).Rows.Length - 1)
For c = 0 To (elementsTable(0).Rows(r).Cells.Length - 1)
ThisWorkbook.Worksheets(1).Cells(r + rSheet + 1, c + 1) = elementsTable(t).Rows(r).Cells(c).innerText
Next c
Next r
rSheet = rSheet + r
If Not elemPageNavRigth Is Nothing Then elemPageNavRigth.Click
Set elementsTableDiv = Nothing
Loop Until bReady Or elemPageNavRigth Is Nothing
End With
Set IE = Nothing
End Sub
Strangely enough I didn't find any information on the topic and I'm currently stuck at the point where I managed to open a new tab in an instance of IE by programmatically clicking a button, but I haven't the faintest clue of how to address the new tab in order to get information from there (the button basically brings up a new tab with the result of a search).
This is basically a straightforward question, but I'm including my code anyway:
Sub AddInfoFromIntranet()
Dim Ie As SHDocVw.InternetExplorer
Dim URL As String
Dim iFrames As MSHTML.IHTMLElementCollection
Dim iFrame As MSHTML.HTMLFrameElement
Dim Doc As MSHTML.HTMLDocument
Dim InputBox As MSHTML.IHTMLElementCollection, htmlButton, allTags, Tag
' Opens Intranet - yeah, sadly it's not a public web page
URL = "{My intranet website}"
Set Ie = New SHDocVw.InternetExplorer
With Ie
.navigate URL
.Visible = True
While .Busy Or .readyState <> READYSTATE_COMPLETE: DoEvents: Wend
Set Doc = .document
End With
' Gets top_window frame and navigates to it, then inserts the name to search
Set iFrames = Doc.getElementsByName("top_window")
If Not iFrames Is Nothing Then
Set iFrame = iFrames(0)
Ie.navigate URL & iFrame.src
While Ie.Busy Or Ie.readyState <> READYSTATE_COMPLETE: DoEvents: Wend
Set InputBox = Doc.getElementsByName("Nachnamevalue")
If Not InputBox Is Nothing Then InputBox(0).Value = "test"
' Clicks on "search"
Set allTags = Doc.getElementsByTagName("input")
For Each Tag In allTags
If Tag.Value = "suchen" Then
Tag.Click
Exit For
End If
Next
' Here a new tab is opened, must find info in this tab
While Ie.Busy Or Ie.readyState <> READYSTATE_COMPLETE: DoEvents: Wend
' HERE I HAVE NO CLUE WHAT TO WRITE. THE CODE ABOVE WORKS FLAWLESSLY
End If
Set Doc = Nothing
Set iFrames = Nothing
Set iFrame = Nothing
Set InputBox = Nothing
Set allTags = Nothing
Set Ie = Nothing
Ie.Quit
End Sub
Now, is there a way to address a tab by: 1) its name (and where do I find it) 2) its position in browser 3) the status (if it is "active") ?
Bonus questions: since I am new to VBA and Internet Explorer interaction, what exactly are the variables: htmlButton, allTags, Tag ? Also, could anyone explain if I need to set all the variables at the end to nothing, or I just need to set the Internet Explorer to nothing?
Thanks in advance!
See below for a function you can use to get an open IE document window - I don't think IE exposes any simple (VBA-accessible) API for working directly with tabs or determining whether a specific tab is active.
allTags is a collection of DOM elements with type "" , and Tag is a single memeber of that collection.
You do not have to set objects to Nothing before exiting a Sub (though some people still do that) - the VBA runtime will take care of that for you.
Sub TestGetIE()
Dim IE As Object
Set IE = GetIE("http://stackoverflow.com")
If Not IE Is Nothing Then
IE.document.execCommand "Print", False, 0
End If
End Sub
'Get a reference to an open IE window based on its URL
Function GetIE(sLocation As String) As Object
Dim objShell As Object, objShellWindows As Object, o As Object
Dim sURL As String
Dim retVal As Object
Set retVal = Nothing
Set objShell = CreateObject("Shell.Application")
Set objShellWindows = objShell.Windows
For Each o In objShellWindows
sURL = ""
On Error Resume Next
'check the URL and if it's the one you want then
' assign it to the return value
sURL = o.document.Location
On Error GoTo 0
'Debug.Print sURL
If sURL Like sLocation & "*" Then
Set retVal = o
Exit For
End If
Next o
Set GetIE = retVal
End Function