I'm trying to target an existing IE window (one tab only) with my script.
In other words: there's an Internet Explorer window opened with a specific tab and I'm trying to get my script to target that tab using its tab name.
I had a look at these topics, but none worked for me (or I did it wrong):
Get existing IE via VBA
Navigate to new URL in existing Internet Explorer window
VBA Macro For Already Open IE Window
Therefore I created this (which worked for a while until I got a 438 Error for no reason) :
Sub FindingExistingIE()
Dim Application As Object
Dim ApplicationWindows As Object
Dim WindowTitle As Variant
Dim TargetWindow As Object
Set Application = CreateObject("Shell.Application")
Set ApplicationWindows = Application.Windows
For Each Application In ApplicationWindows
WindowTitle = Application.Document.Title
If WindowTitle Like "IE Window Title" Then
Set TargetWindow = Application
Exit For
End If
Next Application
NextSub TargetWindow
End
End Sub
As I said, the script worked fine for a week but now I get the 438 error:
Object doesn't support this property or method (Error 438)
The error highlights the following line:
WindowTitle = Application.Document.Title
Having read the Microsoft Doc related to the error, I tried changing the WindowTitle variable to an object. Didn't work.
Does anyone have an idea?
Thanks!
This works for me - finds IE by looking for an open window with the passed URL:
Sub tester()
Dim w As Object
Set w = FindingExistingIEByUrl("https://www.google.com")
If Not w Is Nothing Then
MsgBox w.document.Title
Else
MsgBox "No IE window found"
End If
End Sub
Function FindingExistingIEByUrl(theUrl)
Dim w As Object
For Each w In CreateObject("Shell.Application").Windows
'Debug.Print w.locationurl
If w.locationurl Like theUrl & "*" Then
Set FindingExistingIEByUrl= w
Exit Function
End If
Next w
End Function
Function FindingExistingIEByTitle(theTitle)
Dim w As Object, t As String
For Each w In CreateObject("Shell.Application").Windows
t = ""
On Error Resume Next 'ignore error if no Document
t = w.Document.Title
On Error Goto 0
If t Like theTitle Then
Set FindingExistingIEByTitle = w
Exit Function
End If
Next w
End Function
Related
I am trying to open a .pbix file that sits on a network drive, refresh the PowerBI connection to the file, then close the file and save the changes. I am trying to run the process from Excel, because Excel does some things, propr to this refresh task. I am testing the code below, which I think is pretty close, but I an getting this error message:
RUN TIME ERROR: 424 Object Required
Public vPID As Variant
Sub Launch_Calculator()
Dim fileString as String
If IsProcessRunning("C:\Program Files\PBIDesktop.exe") = True Then
On Error GoTo Reload ' Open new instance of PBIX
AppActivate (vPID) ' Reactivate, using Public declared variant
SendKeys "%{Enter}" ' Bring it back into focus if user minimises it
Else
Reload:
fileString = """\\network_path_here\testing.pbix"""
strFileName = CreateObject("WScript.Shell").Specialfolders("\\network_path_here\") & "testing.pbix"
' fileString.Open...got RUN TIME ERROR: 424 Object Required
' strFileName.Open...got RUN TIME ERROR: 424 Object Required
End If
On error GoTo 0
End Sub
' Function to check for running application by its process name
Function IsProcessRunning(sApp As String)
On Error GoTo Skip
Dim objList As Object
Set objList = GetObject("winmgmts:") _
.ExecQuery("select * from win32_process where name='" & sApp & "'")
If objList.Count > 0 Then
IsProcessRunning = True
Exit Function
Else
IsProcessRunning = False
Exit Function
End If
Skip:
IsProcessRunning = False
End Function
So, I can open the PowerBI.exe file, and run the application just fine, but I can't open and refresh the '.pbix' file. How can I open the .pbix file, refresh it, and save it?
I run this function with two IE browsers open. IE_count finds six objects, but it does not find any titles (my_title) within the for loop for objShell. They all return an empty string.
Any idea as to why this could be? Relevant code below:
' code below adapted from ron's answer here: https://stackoverflow.com/questions/21407340/how-to-read-text-from-an-already-open-webpage-using-vba
Function SecondBrowserSearchForAndClick(ElementID As String, searchFor As String)
Dim objShell
Set objShell = CreateObject("Shell.Application")
Dim IE_count As Integer
IE_count = objShell.Windows.Count
Dim x As Integer
For x = 0 To (IE_count - 1)
On Error Resume Next ' sometimes more web pages are counted than are open
Dim my_url As String
my_url = objShell.Windows(x).document.Location
Dim my_title As String
my_title = objShell.Windows(x).document.Title
If my_title Like "*Select Process*" Then 'compare to find if the desired web page is already open
Dim tagColl_TR As Object
Set tagColl_TR = objShell.Windows(x).document.getElementById(ElementID).contentDocument.getElementsByTagName("tr")
Dim f
While f < tagColl_TR.Length
If tagColl_TR(f).Children.Length = 5 Then
If tagColl_TR(f).Children(3).Children(0).innerText Like "*" & searchFor & "*" Then
tagColl_TR(f).Children(1).Children(0).Children(1).Focus
tagColl_TR(f).Children(1).Children(0).Children(1).Click
Exit Function
End If
End If
f = f + 1
Wend
End If
Next
End Function
Any help would be appreciated.
It's easier to put the "find document by title" functionality in its own function:
Sub Tester()
Dim doc As Object
Set doc = IEDocumentByTitle("Google")
If Not doc Is Nothing Then
Debug.Print "Found window at: " & doc.Location
'work on doc here
End If
End Sub
'Return an open IE document based on its Title property
Function IEDocumentByTitle(title As String)
Dim w As Object, ttl As String
For Each w In CreateObject("Shell.Application").Windows
If w.Application.Name = "Internet Explorer" Then 'filter out Windows Explorer
ttl = ""
On Error Resume Next
ttl = w.document.title
On Error GoTo 0
If ttl Like title Then
Set IEDocumentByTitle = w.document
Exit Function
End If
End If
Next w
End Function
This works fine for me.
BTW the shell Windows collection also includes Windows Explorer instances in addition to IE windows/tabs.
Also you should really cancel On Error Resume Next as soon as possible or it will silently swallow all errors in your code, possibly leading to unexpected results.
I'm using this code to grab the instance of Internet Explorer from word VBA and scraping some values from a webpage. I'm looping through 4 items (just in case, sometimes I've accidentally grabbed something called "Windows Explorer", which I have no idea what that is) to grab Internet Explorer. But before I begin scraping values, I want to make sure my tab name is "Overview - City". How can I test against the tab names?
Dim shellWins As ShellWindows, IE As InternetExplorer
Dim i As Long
Set shellWins = New ShellWindows
'Find Internet Explorer - if it can't find it, close the program
If shellWins.Count > 0 Then
For i = 0 To 3
On Error Resume Next
If shellWins.Item(i).Name = "Internet Explorer" Then
Set IE = shellWins.Item(i)
Exit For
End If
On Error GoTo 0
If i = 3 Then
MsgBox "Could not find Internet Explorer.", vbExclamation, "Error"
Exit Sub
End If
Next i
Else
MsgBox "Could not find Internet Explorer.", vbExclamation, "Error"
Exit Sub
End If
I tried following the guide here and used this bit to try and Debug.Print all the active tab names in IE once I had found it:
Dim IE_Tab As SHDocVw.InternetExplorer
Dim SH_Win As SHDocVw.ShellWindows
For each IE_Tab in SH_Win
Debug.Print IE_Tab.Name 'This returns nothing?
Next IE_Tab
But the immediate window returns blank with no error. What am I doing wrong?
Here is some code that should find a reference to the open Internet Explorer tab. It does this by looping through the Shell.Application.Windows collection. The function supports looking for just the WindowName, the URL and WindowName, and supports specifying the compare method or if you want to do a like match. I kept this code late bound, to avoid needing references.
The code is commented, somewhat, let me know if there are questions.
Code
Option Explicit
Private Function GetIEWindow(WindowName As String, _
ExactMatch As Boolean, _
Optional CompareMethod As VbCompareMethod = vbTextCompare, _
Optional URL As String) As Object
Dim Window As Object
Dim Windows As Object: Set Windows = CreateObject("Shell.Application").Windows
For Each Window In Windows
'Make sure the app is Internet Explorer. Shell Windows can include other apps
If InStr(1, Window.FullName, "IEXPLORE.EXE", vbTextCompare) > 0 Then
'Perform exact matches, where the title or url and title match exactly
If ExactMatch Then
If Len(URL) = 0 Then
If Window.LocationName = WindowName Then
Set GetIEWindow = Window
Exit Function
End If
Else
If Window.LocationName = WindowName And Window.LocationUrl = URL Then
Set GetIEWindow = Window
Exit Function
End If
End If
Else
'Otherwise do a In String match
If Len(URL) = 0 Then
If InStr(1, Window.LocationName, WindowName, CompareMethod) > 0 Then
Set GetIEWindow = Window
Exit Function
End If
Else
If InStr(1, Window.LocationName, WindowName, CompareMethod) > 0 And InStr(1, Window.LocationUrl, URL, CompareMethod) > 0 Then
Set GetIEWindow = Window
Exit Function
End If
End If
End If
End If
Next
End Function
Sub ExampleUsage()
Dim IE As Object: Set IE = GetIEWindow("exe", True)
If Not IE Is Nothing Then
Debug.Print "I found the IE window"
Else
Debug.Print "I didn't find the IE window"
End If
End Sub
The tab is just another window. You can use the GetWebPage function below to loop through the windows and get the URL you are looking for.
References are
Microsoft Internet Controls
Microsoft Shell Controls and Automation
Sub Example()
Dim ieWin As InternetExplorer
Set ieWin = CreateObject("InternetExplorer.Application")
With ieWin
.Navigate "https://www.google.com/"
.Visible = True
.Silent = True
End With
Set ieWin = GetWebPage("https://www.google.com/")
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Desc: The Function gets the Internet Explorer window that has the current
' URL from the sURL Parameter. The Function Timesout after 30 seconds
'Input parameters:
'String sURL - The URL to look for
'Output parameters:
'InternetExplorer ie - the Internet Explorer window holding the webpage
'Result: returns the the Internet Explorer window holding the webpage
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Function GetWebPage(sUrl As String) As InternetExplorer
Dim winShell As Shell
Dim dt As Date
dt = DateAdd("s", 300, DateTime.Now)
Dim ie As InternetExplorer
Do While dt > DateTime.Now
Set winShell = New Shell
'loop through the windows and check the internet explorer windows
For Each ie In winShell.Windows
If ie.LocationURL = sUrl Then
Set GetWebPage = ie
Do While ie.Busy
DoEvents
Loop
Exit Do
Set winShell = Nothing
End If
Next ie
Set winShell = Nothing
DoEvents
Loop
End Function
I found a code online:
Public Sub showProcesses()
Dim W As Object
Dim ProcessQuery As String
Dim processes As Object
Dim process As Object
Set W = GetObject("winmgmts:")
ProcessQuery = "SELECT * FROM win32_process"
Set processes = W.execquery(ProcessQuery)
For Each process In processes
MsgBox process.Name
MsgBox process.Description
Next
Set W = Nothing
Set processes = Nothing
Set process = Nothing
End Sub
It prints out the name and description of all active processes.
Example:
TeraPad.exe acad.exe WINWORD.EXE EXCEL.EXE ...
With the code below I got the window names of the applications that are available in the Taskbar:
Private Sub AppActivates(WindowName As String)
Dim WD, task, n As Long
Set WD = CreateObject("Word.Application")
For Each task In WD.Tasks
MsgBox task.Name
Next
WD.Quit
Set WD = Nothing
End Sub
Example:
Basic_vba.pdf - Adobe Acrobat Reader DC AutoCAD Mechanical 2016 - [sample_model.dwg] 20170424.txt - TeraPad ...
The application acad.exe [AutoCAD] is in the taskbar(status is Minimum), I want to open(call) it's windows up in VBA.
Is that possible?
Any tips on these will be great help.
You can use the AppActivate method along with the window title (which just happens to be the name of the task).
VBA.AppActivate("Basic_vba.pdf - Adobe Acrobat Reader DC")
If the window is minimized, then you'll need to send a message to the window to restore or maximize it.
How do I integrate my code that activates a reference (if it's not already activated) into the beginning of a code I've already got? The problem seems to be the newly added reference isn't recognized as active if I try activating and calling them within the same sub... any suggestions? When I run them separately they run just fine. I'm getting a 4120 Run-time Error (bad parameter) which also happens when reference isn't activated
Sub test ()
Dim strGUID As String, theRef As Variant, i As Long
'Update the GUID you need below.
strGUID = "{00020905-0000-0000-C000-000000000046}"
'Remove any missing references
For i = ThisWorkbook.VBProject.References.Count To 1 Step -1
Set theRef = ThisWorkbook.VBProject.References.Item(i)
If theRef.isbroken = True Then
ThisWorkbook.VBProject.References.Remove theRef
End If
'Check if the reference isn't already activatet - can cause issues when stepping through but works just fine
If ThisWorkbook.VBProject.References.Item(i).GUID = strGUID Then
GoTo ContinueSub
End If
Next i
'Add the reference
ThisWorkbook.VBProject.References.AddFromGuid _
GUID:=strGUID, Major:=1, Minor:=0
Run "ContractPrep"
ContinueSub:
Dim wdApp As Object, wdDoc As Object
'Bunch of code here and then the error occurs here:
Set wdApp = CreateObject("Word.Application")
Set wdDoc = wdApp.Documents.Open(Temp)
'show the word document - put outside of loop for speed later
wdApp.Visible = True
wdDoc.Application.Selection.Wholestory
openxml = wdDoc.Application.Selection.WordOpenXML
wdDoc.Application.Selection.Delete
'Rest of code
End Sub