IE Automation - VBA Error - Runtime Error 70: Permission Denied - vba

Friends, I'm very new to VBA and here I'm trying to scrape data from an internal website. The process goes like this: There are few serial numbers entered in the column A3 to End. The macro is supposed to navigate to the URL --> pick the serial number from excel --> Enter in the Search Field and Click Search. Once the result is populated on the page, it scrapes specific values and populates in the excel sheet.
The page opens up well, data is picked from excel and when the macro is reading the table cells it gives Runtime 70 Error. Below is my code for reference. Any help to fix is much appreciated.
Sub Type1_Data()
Dim ie As InternetExplorer
Dim html As MSHTML.HTMLDocument
Dim RowNumber, ColumnNumber As Long
RowNumber = 3
ColumnNumber = 0
Dim i As Long
Dim HTMLDoc As MSHTML.HTMLDocument
Dim Filt As MSHTML.IHTMLElement
Dim mtbl As MSHTML.IHTMLElement
Dim strempid As MSHTML.HTMLElementCollection
Dim strempid1 As MSHTML.HTMLElementCollection
Dim strempid2 As MSHTML.HTMLElementCollection
Dim strempid3 As MSHTML.HTMLElementCollection
Dim strempid4 As MSHTML.HTMLElementCollection
Dim strempid5 As MSHTML.HTMLElementCollection
Dim strempid6 As MSHTML.HTMLElementCollection
Set ie = New InternetExplorer
ie.Visible = False
ie.navigate ("URL")
Do While ie.READYSTATE = 4: DoEvents: Loop
Do Until ie.READYSTATE = 4: DoEvents: Loop
Set HTMLDoc = ie.document
xy:
If HTMLDoc.Title <> "Marketplace | Find a professional" Then
ie.Visible = True
GoTo xy
End If
ie.Visible = True
ThisWorkbook.Activate
Dim Ed As Integer
Ed = 3
While ThisWorkbook.Sheets("ProM Search").Cells(Ed, 1).Value <> 0
Ed = Ed + 1
Wend
Ed = Ed - 1
For i = 3 To Ed
Application.ScreenUpdating = True
Set UID = HTMLDoc.getElementById("navSelect")
Set Filt = HTMLDoc.getElementById("searchText")
Set mtbl = HTMLDoc.getElementsByTagName("Table")(23)
Application.Wait DateAdd("s", 1, Now)
HTMLDoc.getElementById("NLQTextArea").Value = ThisWorkbook.Sheets("ProM Search").Cells(i, 1).Value
HTMLDoc.getElementById("submitAction").Click
Set strempid = mtbl.getElementsByClassName("dojoxGridCell")(1)
Set strempid1 = mtbl.getElementsByClassName("dojoxGridCell")(2)
Set strempid2 = mtbl.getElementsByClassName("dojoxGridCell")(3)
Set strempid3 = mtbl.getElementsByClassName("dojoxGridCell")(7)
Set strempid4 = mtbl.getElementsByClassName("dojoxGridCell")(9)
Set strempid5 = mtbl.getElementsByClassName("dojoxGridCell")(11)
Set strempid6 = mtbl.getElementsByClassName("dojoxGridCell")(12)
ActiveCell.Offset(0, 1).Activate
ActiveCell.Value = strempid.innerText
ActiveCell.Offset(0, 1).Activate
ActiveCell.Value = strempid1.innerText
ActiveCell.Offset(0, 1).Activate
ActiveCell.Value = strempid2.innerText
ActiveCell.Offset(0, 1).Activate
ActiveCell.Value = strempid3.innerText
ActiveCell.Offset(0, 1).Activate
ActiveCell.Value = strempid4.innerText
ActiveCell.Offset(0, 1).Activate
ActiveCell.Value = strempid5.innerText
ActiveCell.Offset(0, 1).Activate
ActiveCell.Value = strempid6.innerText
ActiveCell.Offset(1, -7).Activate
DoEvents
If ActiveCell.Value = "" Then
MsgBox "Fetching Completed Successfully", vbExclamation, "ProM - Open Seat Search T2"
GoTo qt
End If
Next
qt:
ie.Quit
Set ie = Nothing
Set HTMLDoc = Nothing
End Sub

HTMLDoc.getElementById("submitAction").Click may cause a page refresh making any referenced elements become stale. Try working always of ie.document rather than setting into a variable when performing actions likely/known to cause page refresh/update. This is a common cause of a permission denied error.
Your If End If should probably be a loop with time out. You only need the one ie.visible = True. You rarely gain from setting Visible to false in my opinion. If you intend to hide it from a user you should do so from the start unless it interferes with functionality.
No point for Application.ScreenUpdating = True as it is never switched off within this sub. If this sub is called then you only need it once outside the loop. Your repeated ActiveCell.Offset(0, 1).Activate can just use a loop with Select Case and set the value direct without activate. Repeating the line Do While ie.READYSTATE = 4: DoEvents: Loop serves no purpose.
You could use Find method of range to determine the row in column 1 where 0 occurs rather than walking down the column. And tests to determine it is found and >=3.

This error means an attempt was made to write to a write-protected disk or to access a locked file. You could check if special permission is needed to access the worksheet. For detailed causes and solutions, you can refer to this doc.
Besides, you can also refer to my working sample about reading the cell value in VBA:
Sub LOADIE()
Set ieA = CreateObject("InternetExplorer.Application")
ieA.Visible = True
ieA.navigate "https://www.bing.com"
Do Until ieA.readyState = 4
DoEvents
Loop
Set doc = ieA.Document
Dim tempStr As String
tempStr = "sb_form_q"
doc.getElementById(tempStr).Value = ThisWorkbook.Sheets("SheetName").Range("E2").Value
End Sub

Related

Why isn't the VBA google search not looking up all the cells in the column?

Hi I'm trying to get VBA to run a script to bring back all the links from the first page after running a google search, but it doesn't consistently search all the cells in the column.
Also can anyone help me get the hyperlinks and innertext separate? Here's a copy of the code below:
'Start the bot called SearchBot
Sub SearchBot()
'declare/set aside memory for our variables
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ActiveWorkbook
Set ws = ActiveSheet
For h = 1 To ws.Range("A1").CurrentRegion.Rows.Count
Dim objIE As Object
Dim aEIe As HTMLLinkElement
Dim y As Integer
Dim result As String
'Start Internet Explorer
Set objIE = New InternetExplorer
'Make Internet Explorer Visible
objIE.Visible = True
'navigate to the google webpage
objIE.navigate "google.com"
'Wait for a few seconds while the browser is busy
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
'in the search box enter the field from the cell and press search
objIE.document.getElementsByName("q")(0).Value = ws.Cells(h, 1).Value
SendKeys "{Enter}"
'Wait again for the browser to finish
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
ws.Cells(h, 2).Select
x = 0
For Each aEIe In objIE.document.getElementsByClassName("r")
ActiveCell = objIE.document.getElementsByClassName("r")(x).innerText
ActiveCell.Offset(0, 1).Select
x = x + 1
Next
objIE.Quit
Next
End Sub

For loop in macro works when I step through but get run-time error '91' when I try to run it

I have set up a macro to go through a list of unique identifiers, take these to a website, and return a value into the adjacent cell. I have had some success with it working, but it has been very intermittent, it has also gone though part of the list and then broke. I can step into the VBA and it will work for the entire list, but when I run it the macro will fail, usually with
Run-time error '91': object variable or with block variable not set
Here is my code with details changed for privacy:
Option Explicit
Sub Autofill()
Dim i As Integer
Dim FinalRow As Integer
FinalRow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To FinalRow
Dim IE As New InternetExplorerMedium
IE.Visible = False
IE.navigate "https://website" & Cells(i, 1).Value & "last part of url"
Do
DoEvents
Loop Until IE.readyState = READYSTATE_COMPLETE
Dim Doc As HTMLDocument
Set Doc = IE.document
Dim zDD As String
zDD = Trim(Doc.getElementById("NameValue").innerText)
Cells(i, 2).Value = zDD
Cells(i, 3).Value = Cells(i, 1).Value & "#company.com"
IE.Quit
'Application.Wait Now + #12:00:01 AM# "tried this with varying times to see if it would help, did not have any success"
Set IE = Nothing
Next i
End Sub
Any ideas on why it will run stepping through and not running the macro? Could it be related to my use of internet explorer?
Doc.getElementById("NameValue") needs more time - Have another Do Loop until Doc.getElementById("NameValue") returns an object
Try this (untested):
Option Explicit
Public Sub AutoFillFromIE()
Dim ws As Worksheet, i As Long, IE As InternetExplorerMedium, docElement As Object
Set ws = ActiveSheet
Set IE = New InternetExplorerMedium
IE.Visible = False
For i = 2 To ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
IE.Navigate "https://website" & ws.Cells(i, 1).Value2 & "last part of url"
Do
DoEvents
Loop Until IE.readyState = READYSTATE_COMPLETE
IE.Refresh
Do
Set docElement = IE.Document.getElementById("NameValue")
DoEvents
Loop Until Not docElement Is Nothing
ws.Cells(i, 2).Value2 = Trim$(docElement.innerText)
ws.Cells(i, 3).Value2 = ws.Cells(i, 1).Value2 & "#company.com"
Set docElement = Nothing
Next i
IE.Quit
End Sub
When you use Cells method, specify what sheet you're refering to. Example:
Worksheets("Sheet1").Cells(.....
If you do not use this and call the macro from another sheet, Excel will try to use Cells method with the active sheet and you will get your error.

Pause script till website fully loaded - Excel VBA

I'm currently trying to create a sheet which will extract tracking information for parcels sent out. I've worked out the following code for the time being but encounter the following issues:
The code continues before the page fully loads, I suspect this may be because after the initial loading is complete, it runs a script and refreshes.
If mouse is not rolling over Internet Explorer, high probability of a human verification with images. I understand this may not be possible to avoid but is there any way I can pause the script while someone completes the verification?
Sub RoyalTrack()
Dim i As Long
Dim ie As Object
Dim t As String
Set ie = CreateObject("InternetExplorer.Application")
With ie
.Visible = True
.Navigate "https://www.royalmail.com/track-your-item#/tracking-results/SF511991733GB"
.Resizable = True
End With
While ie.ReadyState <> 4 Or ie.Busy: DoEvents: Wend
Dim full As Variant
Dim latest As Variant
full = ie.Document.getElementsByClassName("c-tracking-history")(0).innerText
latest = ie.Document.getElementsByClassName("tracking-history-item ng-scope")(0).innerText
MsgBox full
MsgBox latest
End Sub
Managed to figure it out. Added a 2 second wait after page loads to allow loading and an error handler to identify if the required property is available.
Sub RoyalTrack()
Dim i As Long
Dim ie As Object
Dim t As String
Dim trackingN As String
Dim count As Integer
count = 2
Do While Worksheets("Sheet1").Range("D" & count).Value <> ""
Set ie = CreateObject("InternetExplorer.Application")
trackingN = Worksheets("Sheet1").Range("D" & count).Value
With ie
.Visible = True
' Variable tracking SF-GB
.Navigate "https://www.royalmail.com/track-your-item#/tracking-results/" & trackingN
.resizable = True
End With
While ie.readyState <> 4 Or ie.Busy: DoEvents: Wend
Application.Wait (Now + TimeValue("0:00:02"))
Dim full As Variant
Dim latest As Variant
On Error Resume Next
latest = ie.document.getElementsByClassName("tracking-history-item ng-scope")(0).innerText
If Err Then
MsgBox "Prove your humanity if you can"
Err.Clear
End If
latest = ie.document.getElementsByClassName("tracking-history-item ng-scope")(0).innerText
Windows("Book1.xls").Activate
Sheets("Sheet1").Select
Range("E" & count).Value = latest
ie.Quit
Set ie = Nothing
count = count + 1
Loop
End Sub

VBA to find text from webpages

I have created Macro which gives me all URLs present on any webpages.
We just need to provide the URL and it gives us the all links present in that webpage and paste it in one column
Private Sub CommandButton4_Click()
'We refer to an active copy of Internet Explorer
Dim ie As InternetExplorer
'code to refer to the HTML document returned
Dim html As HTMLDocument
Dim ElementCol As Object
Dim Link As Object
Dim erow As Long
Application.ScreenUpdating = False
'open Internet Explorer and go to website
Set ie = New InternetExplorer
ie.Visible = True
ie.navigate Cells(1, 1)
'Wait until IE is done loading page
Do While ie.READYSTATE <> READYSTATE_COMPLETE
Application.StatusBar = "Trying to go to website…"
DoEvents
Loop
Set html = ie.document
'Display text of HTML document returned in a cell
'Range("A1") = html.DocumentElement.innerHTML
Set ElementCol = html.getElementsByTagName("a")
For Each Link In ElementCol
erow = Worksheets("Sheet4").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
Cells(erow, 1).Value = Link
Cells(erow, 1).Columns.AutoFit
Next
'close down IE, reset status bar & turn on screenupdating
'Set ie = Nothing
Application.StatusBar = ""
Application.ScreenUpdating = True
ie.Quit
ActiveSheet.Range("$A$1:$A$2752").removeDuplicates Columns:=1, Header:=xlNo
End Sub
Now can anyone will help me to create macro to find particular text from all these URLs present in column and if that text is present then in next column it should print text "text found".
Example if we search text "New" then it should print text "Text found" in next column of the URL.
Thank you.
The key would be the function Instr, if it finds the string "New", it returns the position where it begins, otherwise it returns 0.
i=1
do until trim(Cells(i,1).Value) = vbNullString
if instr(Cells(i,1).Value,"New") then
Cells(i,2).value="Text found"
end if
i=i+1
loop
Similar to above.
Dim a As Variant
a = 2
While Cells(a, 1) <> "" And Cells(a + 1, 1) <> ""
If InStr(Cells(a, 1), "new") = 0 Then
Else
Cells(a, 2) = "Text Found"
End If
a = a + 1
Wend

Scraping a single value from an HTML table and inserting into an Excel cell with VBA

Please see the code below. I am compiling a list of unusual currency pairings in excel and I wish to scrape this data with VBA. I only want to insert the value itself into the cell. Does anyone know where I am going wrong here? I am getting a 'Run-time error '91': object variable or With block variable not set'. I'm relatively new to VBA and i've put a lot a deal of thought into this.
Sub ie_open()
Dim wb As Workbook
Dim ws As Worksheet
Dim TxtRng As Range
Dim ie As Object
Set ie = CreateObject("INTERNETEXPLORER.APPLICATION")
ie.NAVIGATE "http://www.barchart.com/quotes/forex/British_Pound/Costa_Rican_Colon/%5EGBPCRC"
ie.Visible = True
While ie.ReadyState <> 4
DoEvents
Wend
Set wb = ActiveWorkbook
Set ws = wb.Sheets("Test Sheet")
Set TxtRng = ws.Range("A1")
TxtRng.Value = ie.document.getelementsbyname("divQuotePage").Item.innertext
End Sub
This is the data which I am trying to scrape:
Thanks.
I'm not that accomplished at web scraping, but that kind of error often means that what you are looking for isn't there. In particular, I don't see divQuotePage in the screen shot you provided.
But if you want the quote (793.19) you could do something like:
Dim V As Variant
Set V = ie.document.getelementbyid("dtaLast")
TxtRng = V.innertext
This will work.
Sub Test()
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
With IE
.Visible = True
.Navigate "http://www.barchart.com/quotes/forex/British_Pound/Costa_Rican_Colon/%5EGBPCRC" ' should work for any URL
Do Until .ReadyState = 4: DoEvents: Loop
x = .document.body.innertext
y = InStr(1, x, "Last Price")
Z = Mid(x, y, 19)
Range("A1").Value = Trim(Z)
.Quit
End With
End Sub
You can target that element with a CSS selector of div.pricechangerow > span.last-change;
which can be simplified to .last-change.
The "." means class and you can retrieve this specific item with
Debug.Print ie.document.querySelector.querySelector(".last-change").innerText
That is for the website's current incarnation at 2018-06-30