My working macro stopped working (no changes were made) - excel

I have a macro that connects to a web-page, gets some info and displays it on a user form (for further actions):
Private Sub UserForm_Initialize()
Dim login As String, password As String
Dim waittime As String
Dim arrForms As Variant
Dim ie As InternetExplorer
LoadingForm.Show vbModeless
LoadingForm.lblLoading.Caption = "Loading..."
waittime = "0:00:02"
login = "lgn"
password = "passwrd"
txtEndDate.Value = Format(Now(), "dd.mm.yyyy")
Set ie = CreateObject("InternetExplorer.Application")
ie.Visible = False
'open login page
ie.navigate "my link (internal company database)"
Do Until Not ie.Busy And ie.readyState = 4
DoEvents
Loop
Application.Wait (Now + TimeValue(waittime))
'if already logged in, skip
On Error GoTo Skip_login
ie.document.getElementById("_58_login").Value = login
ie.document.getElementById("_58_password").Value = password
ie.document.getElementsByClassName("btn btn-primary")(0).Click
Do Until Not ie.Busy And ie.readyState = 4
DoEvents
Loop
Application.Wait (Now + TimeValue(waittime))
Skip_login:
ie.navigate "my link (internal company database)"
Do Until Not ie.Busy And ie.readyState = 4
DoEvents
Loop
Application.Wait (Now + TimeValue(waittime))
arrForms = GetListOfForms(ie) 'this is a function that reads the page,
'finds a table and converts its values to an array
'I tried to comment this line (maybe a bug in my function)
'but even without it the code does not work
For i = LBound(arrForms) To UBound(arrForms)
FormsList.AddItem (arrForms(i))
Next i
'Log out and quit IE
ie.navigate "my link (internal company database)"
Do Until Not ie.Busy And ie.readyState = 4
DoEvents
Loop
Application.Wait (Now + TimeValue(waittime))
ie.document.getElementById("sign-out").Click
Do Until Not ie.Busy And ie.readyState = 4
DoEvents
Loop
Application.Wait (Now + TimeValue(waittime))
ie.Quit
LoadingForm.Hide
End Sub
It worked fine for a few days. It also worked today. But it stopped working for an unknown reason (it just says"automation error" without reference to an error in my code). I was using it, closed the user form, then clicked to start macro again and it does not work. I tried to open older backups - they stopped working too. I did not change anything (links, login/password, any other line of code).
My user form does not have any uncommon user controls. It has the following controls only: text fields, lables, frames, listbox, and buttons)

Related

Make the page wait until it loads the second time

I have a site I need to log in and then change the URL. After it loads copy the entire site to excel.
If I'm doing it slowly (F8 button) or do application wait function, it work but its not optimal for different PC, and if I set it too high the data will take forever to load.
I wrote this code:
Set Ie = CreateObject("InternetExplorer.Application")
Ie.Visible = True
Ie.Navigate "Site login"
Do While Ie.Busy = True Or Ie.readyState < READYSTATE_COMPLETE
DoEvents
Loop
Set HTMLDoc = Ie.document
HTMLDoc.getElementById("user_login_name").Value = UserName 'the user name is defined before
HTMLDoc.getElementById("user_password").Value = UserPass 'the password is defined before
LoginButton = Ie.document.getElementsByName("button")
Click = Ie.document.getElementsByTagName
LoginButton.Click
Ie.Navigate "The wanted URL to load fully before the next code activates"
'copy and paste in excel
Ie.ExecWB 17, 0 '// SelectAll
Ie.ExecWB 12, 2 '// Copy selection
Range("A1").Select
ActiveSheet.Paste
Range("A1").Select
Ie.Quit
When I run it now I get the user name from login screen
Anything I'm missing?
Thanks in advance for your time
Nik
Put the code below, after second Ie.Navigate in your VBA code may help to fix your issue.
Do While Ie.Busy = True Or Ie.readyState < READYSTATE_COMPLETE
DoEvents
Loop
Your modified code:
Set Ie = CreateObject("InternetExplorer.Application")
Ie.Visible = True
Ie.Navigate "Site login"
Do While Ie.Busy = True Or Ie.readyState < READYSTATE_COMPLETE
DoEvents
Loop
Set HTMLDoc = Ie.document
HTMLDoc.getElementById("user_login_name").Value = UserName 'the user name is defined before
HTMLDoc.getElementById("user_password").Value = UserPass 'the password is defined before
LoginButton = Ie.document.getElementsByName("button")
Click = Ie.document.getElementsByTagName
LoginButton.Click
Ie.Navigate "The wanted URL to load fully before the next code activates"
Do While Ie.Busy = True Or Ie.readyState < READYSTATE_COMPLETE
DoEvents
Loop
'copy and paste in excel
Ie.ExecWB 17, 0 '// SelectAll
Ie.ExecWB 12, 2 '// Copy selection
Range("A1").Select
ActiveSheet.Paste
Range("A1").Select
Ie.Quit
Output:
Sorry to keep you waiting, I will close this due to still waiting from our users for feedback(they use this files only once a month). which means I can't confirm if my solution was correct or not. However what I did was tweak the code. and added an if to check the current pages link and added the Ie.readyState < READYSTATE_COMPLETE into the code. it looks like the following:
If Ie.LocationURL <> "site link" Then Do While Ie.Busy = True Or Ie.readyState <
READYSTATE_COMPLETE DoEvents Loop
End If
I do this twice. once for the login page, and the second time.
It seems to work for me(did the data scrape at least 10 times and no error)
Thank you for your time and sorry for the wait.

VBA Automation isn't working on new IE tab

It's my first question and I'm new on VBA.
I was trying to run a macro to automatize some procedures on IE. My macro worked very well when opened on diferent windows, but when I tried to run the same macro on tabs it didn't work. It seems (maybe) the macro isn't recognizing the actual tab. Could anyone help me, please?
Sub Test1()
Dim IE As Object
Dim doc As HTMLDocument
Set IE = CreateObject("InternetExplorer.Application")
For intRow = 1 To 3
If intRow = 1 Then
With IE
.Visible = True
.navigate "https://gru.inpi.gov.br/pePI/jsp/patentes/PatenteSearchBasico.jsp"
Do While IE.Busy Or IE.readyState <> 4
Application.Wait DateAdd("s", 1, Now)
Loop
Set doc = IE.document
IE.document.getElementById("principal").Children(4). _
getElementsByTagName("tbody")(0).getElementsByTagName("tr")(5). _
getElementsByTagName("td")(1).getElementsByTagName("font")(0). _
getElementsByTagName("input")(0).Value = "intRow"
Application.Wait DateAdd("s", 2, Now)
End With
Else
With IE
.Visible = True
.navigate "https://gru.inpi.gov.br/pePI/jsp/patentes/PatenteSearchBasico.jsp", 2048&
Do While IE.Busy Or IE.readyState <> 4
Application.Wait DateAdd("s", 1, Now)
Loop
.document.getElementById("principal").Children(4). _
getElementsByTagName("tbody")(0).getElementsByTagName("tr")(5). _
getElementsByTagName("td")(1).getElementsByTagName("font")(0). _
getElementsByTagName("input")(0).Value = "intRow"
Application.Wait DateAdd("s", 2, Now)
End With
End If
Next
End Sub
According to your code and the website, it seems that you want to open multiple tab (with the same URL), and then fill a value in the text box. We should pay attention to the following point:
How to access the web page elements.
How to switch tabs and focus to the new tab.
To access the web page elements, from your web page resource (use F12 developer tools to check it), I notice that the table contains 6 rows, but the last row doesn't contain the input element. So, using your code, I can't find the input element. I found that the input elements contain the class property. So, I suggest you could use the getElementsByClassName method to find the element.
To switch the IE browser tab, we could loop through the opened tabs and compare the URL, and then set focus on the related tab.
More detail steps, please check the following sample code:
Sub Test1()
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
Dim intRow As Integer
For intRow = 1 To 3
If intRow = 1 Then
With IE
.Visible = True
.navigate "https://gru.inpi.gov.br/pePI/jsp/patentes/PatenteSearchBasico.jsp"
Do While IE.Busy Or IE.readyState <> 4
Application.Wait DateAdd("s", 1, Now)
Loop
Set doc = IE.document
IE.document.getElementsByClassName("basic")(0).Value = "intRow" & intRow
Application.Wait DateAdd("s", 3, Now)
End With
Else
With IE
.Visible = True
.navigate "https://gru.inpi.gov.br/pePI/jsp/patentes/PatenteSearchBasico.jsp", 2048&
Do While IE.Busy Or IE.readyState <> 4
Application.Wait DateAdd("s", 1, Now)
Loop
Application.Wait DateAdd("s", 3, Now)
Set IE = GetIE("https://gru.inpi.gov.br/pePI/jsp/patentes/PatenteSearchBasico.jsp")
Application.Wait DateAdd("s", 3, Now)
IE.document.getElementsByClassName("basic")(0).Value = "intRow" & intRow
End With
End If
Next
End Sub
Function GetIE(sLocation As String) As Object
Dim retVal As Object
Dim my_url As String, my_title As String
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_url
'find the special tab based on the title.
If my_url Like sLocation Then
Set retVal = objShell.Windows(x)
'IE.Quit 'call the Quit method to close the tab.
'Exit For 'exit the for loop
Else
End If
Next
Set GetIE = retVal
End Function
After running the above script, it will open three tabs and fill a value in the Login input text. Please see the following screenshot:
Reference:
Common VBA Methods & Properties used in web automation

VBA Automation (macro) isn't working very well on IE tabs

I'm new here and on VBA, it's my 2nd post and I don't speak english very well. So, please, take easy on me =D
Last week I was having some troubles trying to automatize some procedures on IE. My macro worked very well when opened on new windows, but when I tried to run the same macro on tabs it wasn't working. It seemed (maybe) the macro wasn't recognizing the actual tab. I post that problem here and a wonderfull guy called Deepak-MSFT helped me a lot. He taught me how to run the macro on tabs and it worked almost 100%.
Problems:
1 - The macro sometimes work, sometimes doesn't. Yesterday, for example, I was getting errors 424, 91 and, sometimes, it just opened another tab without insert the value (perheaps because of the "On Error Resume Next"). I think it was because one of the websites was slow. I tried to increase the TimeValue until 7 seconds but, even so, it didn't work. I tested during the whole day and it was extremely unstable, sometimes worked, and somtimes it doesn't. But today it's working (all the websites are stable). Any idea how to solve this instability?
2 - There are 2 websites (2nd and 3rd) where I use querySelector to find the box to insert the value. Both of them work on 70% of the PC's of my company and only those 2 websites doesn't work on the other 30%. I installed the same version of IE (11.0.9600), Excel (2007, SP3) and Windows (W7) on all of them, but even so, only those 2 websites with queryselector don't work. There are no errors. The macro just don't insert the value. Perhaps I'm missing something that make queryselector works on those PC's, but all the references match. I dig the first 5 pages on google trying to find a solution but I failed. I think there's a witch flying around those PC's. Could you help me?
3 - I have total instability trying to run my macros on Excel 2016 or other versions of Excel higher than 2007 at Windows 10. Does anyone have a good solution to adapt the program to run on Excel 2016 (all my company will run this version next year) without have to do all over again?
Thank you very much guys. Here is my code:
Sub ademo()
Dim i As Long
Dim URL As String
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
'TAB 1
URL = "https://servicos.ibama.gov.br/ctf/publico/areasembargadas/ConsultaPublicaAreasEmbargadas.php"
IE.Navigate2 URL
Do While IE.readyState = 4: DoEvents: Loop 'Do While
Do Until IE.readyState = 4: DoEvents: Loop 'Do Until
IE.document.getElementById("num_cpf_cnpj").Value = "demo1" 'Sheets("Main").Range("C10")
IE.document.getElementById("Emitir_Certificado").Click
'TAB 2 - DAP
On Error Resume Next
IE.Visible = True
IE.Navigate2 "http://smap14.mda.gov.br/extratodap/", 2048&
Application.Wait (Now + TimeValue("0:00:04"))
Set IE = GetIE("http://smap14.mda.gov.br/extratodap/")
Do While IE.Busy
Application.Wait DateAdd("s", 1, Now)
Loop
Set doc = IE.document
On Error Resume Next
Set Target = IE.document.querySelector("#corpo > div > div > div:nth-child(1) > button")
Target.Click
Do While IE.Busy
Application.Wait DateAdd("s", 1, Now)
Loop
doc.getElementById("txtCPF_CNPJ").Value = "demo2"
'TAB 3 - CNDT
IE.Visible = True
On Error Resume Next
IE.Navigate2 "http://aplicacao.jt.jus.br/cndtCertidao/inicio.faces", 2048&
Application.Wait (Now + TimeValue("0:00:04"))
Set IE = GetIE("http://aplicacao.jt.jus.br/cndtCertidao/inicio.faces")
Do While IE.Busy
Application.Wait DateAdd("s", 1, Now)
Loop
Set doc = IE.document
On Error Resume Next
Set target2 = IE.document.querySelector("#corpo > div > div:nth-child(2) > input:nth-child(1)")
target2.Click
Do While IE.Busy
Application.Wait DateAdd("s", 1, Now)
Loop
doc.getElementById("gerarCertidaoForm:cpfCnpj").Value = "demo3"
'TAB 4 - CND
On Error Resume Next
IE.Visible = True
IE.Navigate2 "http://servicos.receita.fazenda.gov.br/Servicos/certidao/CNDConjuntaInter/InformaNICertidao.asp?tipo=2", 2048&
Application.Wait (Now + TimeValue("0:00:04"))
Set IE = GetIE("http://servicos.receita.fazenda.gov.br/Servicos/certidao/CNDConjuntaInter/InformaNICertidao.asp?tipo=2")
Do While IE.Busy
Application.Wait DateAdd("s", 1, Now)
Loop
Set doc = IE.document
On Error Resume Next
IE.document.getElementsByName("NI")(0).Value = "demo4"
'TAB 5 - IMPROBIDADE
IE.Visible = True
IE.Navigate2 "http://www.cnj.jus.br/improbidade_adm/consultar_requerido.php?validar=form", 2048&
Application.Wait (Now + TimeValue("0:00:04"))
Set IE = GetIE("http://www.cnj.jus.br/improbidade_adm/consultar_requerido.php?validar=form")
IE.document.getElementById("num_cpf_cnpj").Value = "demo5"
End Sub
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 'because may not have a "document" property
'Check the URL and if it's the one you want then
' assign the window object to the return value and exit the loop
sURL = o.document.Location
On Error GoTo 0
If sURL Like sLocation & "*" Then
Set retVal = o
Exit For
End If
Next o
Set GetIE = retVal
End Function

Right Clicking on a particular Web Page in VBA

I am trying to Right click on Google Maps page, So far I am able to create the object ie, navigate to the page and search for a particular address.
But in the next step I have to click on the bottom of Address marker (Blue Dot)
After the click, I want to select What's Here from the options.
After the selection, I use the line
ie.document.getElementsByClassName("link-like widget-reveal-card-lat-lng")(0).innerText to get the co-ordinates of the Place.
Code so Far:
Set ie = CreateObject("InternetExplorer.Application")
ie.Visible = True
ie.navigate "https://www.google.com/maps"
Do While ie.Busy
Application.Wait DateAdd("s", 1, Now)
Loop
Application.Wait DateAdd("s", 1, Now)
ie.document.getElementById("searchboxinput").Value = "Signature Tower GurGaon"
ie.document.getElementById("searchbox-searchbutton").Click
MsgBox "After Manually clicking What's Here, press ok"
Basically I want to automate that Manual part. What are the elements that needs to be clicked for the right click and how do I identify the point where to click.
Alternate:
Just found that, those lat-long are also part of the a href by
ie.document.getElementsByClassName("gb_9d gb_2 gb_ob")(0).href
So there is no need to right click.
But I am still interested to know how to Right Click it.
Note that you can put the search term directly into the first navigate.
IE.navigate "https://www.google.com/maps" & "/search/Signature Tower GurGaon"
Your wait loop should check .Busy and .ReadyState
Do While IE.Busy Or IE.ReadyState <> 4
And as you already found out the coordinates are in the source code
Option Explicit
Public Sub Test()
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.navigate "https://www.google.com/maps" & "/search/Signature Tower GurGaon"
Do While IE.Busy Or IE.ReadyState <> 4
Application.Wait DateAdd("s", 1, Now)
Loop
Application.Wait DateAdd("s", 1, Now)
Dim GetLocation As String
GetLocation = IE.document.getElementsByClassName("gb_9d gb_2 gb_ob")(0).href
GetLocation = Right$(GetLocation, Len(GetLocation) - InStr(1, GetLocation, "%40") - 2)
GetLocation = Left$(GetLocation, InStr(1, GetLocation, "&") - 1)
Dim Location() As String
Location = Split(GetLocation, "%2C")
Debug.Print "Lat", Location(0)
Debug.Print "Lon", Location(1)
Debug.Print "zoom", Location(2)
End Sub
Will result in
Lat 28.4636862
Lon 77.054257
zoom 16z

Excel VBA object required error with IE automation

So I have some code to go to a website and then login. Then I need it to go to the password change URL. Sometimes when I run the code, I get the following error:
Runtime Error 424: Object Required
Sometimes the debugger says it is the first getelementbyid statement, but most times it says the issue is the last three getelementbyid statements. The code is below:
Dim ie As Variant
Dim strURL As String
Sub login()
Set ie = New SHDocVw.InternetExplorer
ie.Visible = True
ie.navigate "https://minecraft.net/profile"
While ie.Busy
DoEvents
Wend
ie.document.getElementById("username").Value = "ddd"
ie.document.getElementById("password").Value = "ddddddddddd"
Dim htmlForm As HTMLFormElement
Set htmlForm = ie.document.getElementById("loginForm")
htmlForm.submit
' **********************************************************************
'IE.Document.getElementById("username").Value = "ddddd"
' IE.Document.getElementById("password").Value = "ddddd"
' IE.Document.getElementById("signin").Click
'**********************************************************************
'Pause while page loads
Application.Wait (Now + #12:00:03 AM#)
ie.navigate "https://minecraft.net/profile/password"
ie.document.getElementById("oldPassword").Value = "oldpass"
ie.document.getElementById("password").Value = "enwapss"
ie.document.getElementById("passwordConfirmation").Value = "enwapss"
Set htmlForm = ie.document.getElementById("loginForm")
htmlForm.submit
End Sub
Thanks in advance!
It may be that the website isn't in a ready state, as in the site hasn't fully loaded when it's attempting to input the values.
After
ie.navigate "https://minecraft.net/profile/password"
Try adding
Do Until Not ie.Busy And ie.readyState = 4
DoEvents
Loop
This will loop until the webpage has loaded similar, to the way you've done it in your above code with
Application.Wait (Now + #12:00:03 AM#)

Resources