VBA Error 70: Permission Denied during IE automation - vba

I've been trying to create a quick subroutine in VBA through Excel 2010 to automate putting a list of URLs through bit.ly and copying the abbreviated links back to replace their original link. BUT I'm getting an Error 70: Permission Denied runtime error along the way. I've had a few courses and this MOSTLY works, but I'm not highly familiar with VBA and could use some help in debugging this if possible (it'd be a huge help). Here's the code:
Option Explicit
Dim IE As Object
Sub AutoAbbrev()
Set IE = CreateObject("InternetExplorer.Application")
Dim holdURL As String
Dim row_number As Integer
IE.Visible = True
For row_number = 101 To 112
holdURL = ""
If Range("b" & row_number).Value = "" Then GoTo Skip
IE.navigate "http://www.bitly.com" 'load bit.ly
Do While IE.readyState <> 4
DoEvents
Loop
IE.document.all("shorten_url").Value = Range("b" & row_number).Value
IE.document.all("shorten_btn").Click
Do While IE.document.all("shorten_url").Value = Range("b" & row_number).Value Or IE.document.all("shorten_url").Value = ""
DoEvents
Loop
holdURL = IE.document.all("shorten_url").Value
IE.document.all("shorten_url").Value = ""
Range("b" & row_number).Value = holdURL
Skip:
Next row_number
End Sub
Private Sub Command1_Click()
AutoAbbrev
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set IE = Nothing
If TypeName(IE) <> "Nothing" Then Unload IE
Set IE2 = Nothing
If TypeName(IE2) <> "Nothing" Then Unload IE2
End Sub
The error is mostly thrown on this line after the program has run through one or more iterations:
Do While IE.document.all("shorten_url").Value = Range("b" & row_number).Value Or IE.document.all("shorten_url").Value = ""
DoEvents
Loop
If any specific advice could be provided to help me over this hump, I'd greatly appreciate it. Thanks!

Automating Internet Explorer should always be a last resort, it's slow and relies on the structure of the page remaining unchanged. It's always better to opt for an API if one is available, in this case bitly provide an API for shotening links, you just need to get your Authentication Token and enter it in the below:
Public Function Shorten(url As String) As String
Const token As String = "YOUR AUTHENTICATION TOKEN"
Static oRequest As Object
If oRequest Is Nothing Then Set oRequest = CreateObject("winhttp.winhttprequest.5.1")
With oRequest
.Open "GET", "https://api-ssl.bitly.com/v3/shorten?access_token=" & token & "&longUrl=" & url & "&format=xml", False
.send
If Left(Split(.responsetext, "txt>")(1), 2) = "OK" Then Shorten = Split(Split(.responsetext, "url>")(1), "<")(0)
End With
End Function
You can then use the above as a function in your worksheet

I found this occurs because of the page not being fully loaded. IE is SLOW but sometimes you need to use it because you have dynamic content in Divs which need to be opened with an object.click event. Do Until Not appIE.Busy And appIE.ReadyState = 4: DoEvents: Loop can help but it can also hang up your browser so adding a wait period using a timer can help.

Related

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

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

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

Excel VBA Error - Runtime Error 70: Permission Denied

I need help with a code that was written for me. The code is below. I works find perhaps 70% of the time, but every approx 20 rows it throws up
Runtime Error 70: Permission Denied
What would cause this, and is there any fix for it? Also, How can I change the code to skip any errors like this (or similar) and just move onto the next row.
Debugger throws up the line: If btn.ID = "gs_hdr_tsb" Then
The full script is below.
Dim ie As Object
Private Sub CommandButton1_Click()
Set ie = CreateObject("InternetExplorer.Application")
ie.Visible = True
ie.Navigate TextBox1.Text
Do
DoEvents
Loop Until ie.readystate = 4
Application.Wait (Now + TimeValue("00:00:02"))
End Sub
Private Sub CommandButton2_Click()
Dim i As Long
Dim prfl As String
Dim ws As Worksheet
Set ws = ActiveSheet
Dim INPTTG, btn As Object
Dim Profile_link As String
Dim H3tg As Object
Dim iedata As Object
If iedata Is Nothing Then
Set iedata = CreateObject("InternetExplorer.Application")
End If
iedata.Visible = True
For i = TextBox2.Text To TextBox3.Text
prfl = ws.Range("E" & i).Value
For Each INPTTG In ie.document.getelementsbytagname("input")
If INPTTG.classname = "gs_in_txt" Then
INPTTG.Value = ""
INPTTG.Value = prfl
Exit For
End If
Next INPTTG
'button
Application.Wait (Now + TimeValue("00:00:02"))
For Each btn In ie.document.getelementsbytagname("button")
If btn.ID = "gs_hdr_tsb" Then
btn.Click
Do
DoEvents
Loop Until ie.readystate = 4
Application.Wait (Now + TimeValue("00:00:02"))
End If
Next btn
'prfl
For Each H3tg In ie.document.getelementsbytagname("h3")
If H3tg.classname = "gsc_oai_name" And VBA.Trim(H3tg.innertext) = prfl Then
Call GetData(H3tg.getelementsbytagname("a").Item(0).href, iedata, i)
Exit For
End If
Next H3tg
TextBox2.Text = i
Next i
MsgBox "Completed"
iedata.Quit
Set iedata = Nothing
Application.DisplayAlerts = False
ThisWorkbook.Save
End Sub
Any help would be very appreciated.
Try this one.
Dim ie As Object
Private Sub CommandButton1_Click()
On error go to ErrMsg
Set ie = CreateObject("InternetExplorer.Application")
ie.Visible = True
ie.Navigate TextBox1.Text
Do
DoEvents
Loop Until ie.readystate = 4
Application.Wait (Now + TimeValue("00:00:02"))
ErrMsg:
End Sub
Private Sub CommandButton2_Click()
Dim i As Long
Dim prfl As String
Dim ws As Worksheet
Set ws = ActiveSheet
Dim INPTTG, btn As Object
Dim Profile_link As String
Dim H3tg As Object
Dim iedata As Object
On error go to msgErr
If iedata Is Nothing Then
Set iedata = CreateObject("InternetExplorer.Application")
End If
iedata.Visible = True
For i = TextBox2.Text To TextBox3.Text
prfl = ws.Range("E" & i).Value
For Each INPTTG In ie.document.getelementsbytagname("input")
If INPTTG.classname = "gs_in_txt" Then
INPTTG.Value = ""
INPTTG.Value = prfl
Exit For
End If
Next INPTTG
'button
Application.Wait (Now + TimeValue("00:00:02"))
For Each btn In ie.document.getelementsbytagname("button")
If btn.ID = "gs_hdr_tsb" Then
btn.Click
Do
DoEvents
Loop Until ie.readystate = 4
Application.Wait (Now + TimeValue("00:00:02"))
End If
Next btn
'prfl
For Each H3tg In ie.document.getelementsbytagname("h3")
If H3tg.classname = "gsc_oai_name" And VBA.Trim(H3tg.innertext) = prfl Then
Call GetData(H3tg.getelementsbytagname("a").Item(0).href, iedata, i)
Exit For
End If
Next H3tg
TextBox2.Text = i
Next i
MsgBox "Completed"
iedata.Quit
Set iedata = Nothing
Application.DisplayAlerts = False
ThisWorkbook.Save
MsgErr:
End Sub
There are several answers here on StackOverflow about this VB Error. Each answer or situation is unique in reality - although each existing answer states a different potential root cause (file permissions, folder permissions, name reuse, ranges, etc).
I would recommend narrowing down the root-cause by double clicking on the side of the stating function/code in order to mark a breakpoinnt (looks like a red dot) (Alternatively, you can right click on the line of the code - Select the Toggle and then Breakpoint).
Next, run your code, and it will stop in your breakpoint. You can then Step-Into/Over/Out your code and essentially find the line of code that is responsible for throwing your error code. (Step Into is F8, Step over is Shift+F8 ((Go To the Debug top menu to see more options)))
Once you identified the responsible line of code - you can start looking further.
In my case scenario, I was using a protected variable name "Date" (look into variable names). Once I renamed it to something else, the problem was fixed.
One possible cause of this error (as was my case) is an antivirus/antimalware program blocking certain libraries. Try temporarily disabling all antivirus/antimalware programs and test your script again. In my case, Malwarebytes
In MalWare bytes, you can disable this setting by going to:
Security > Advanced Settings > Application Hardening [tab]
On the row called "Disable Loading of VBScript Libraries", un-check the checkbox under "MS Office".

Excel VBA Macro: Scraping data from site table that spans multiple pages

Thanks in advance for the help. I'm running Windows 8.1, I have the latest IE / Chrome browsers, and the latest Excel. I'm trying to write an Excel Macro that pulls data from StackOverflow (https://stackoverflow.com/tags). Specifically, I'm trying to pull the date (that the macro is run), the tag names, the # of tags, and the brief description of what the tag is. I have it working for the first page of the table, but not for the rest (there are 1132 pages at the moment). Right now, it overwrites the data everytime I run the macro, and I'm not sure how to make it look for the next empty cell before running.. Lastly, I'm trying to make it run automatically once per week.
I'd much appreciate any help here. Problems are:
Pulling data from the web table beyond the first page
Making it scrape data to the next empty row rather than overwriting
Making the Macro run automatically once per week
Code (so far) is below. Thanks!
Enum READYSTATE
READYSTATE_UNINITIALIZED = 0
READYSTATE_LOADING = 1
READYSTATE_LOADED = 2
READYSTATE_INTERACTIVE = 3
READYSTATE_COMPLETE = 4
End Enum
Sub ImportStackOverflowData()
'to refer to the running copy of Internet Explorer
Dim ie As InternetExplorer
'to refer to the HTML document returned
Dim html As HTMLDocument
'open Internet Explorer in memory, and go to website
Set ie = New InternetExplorer
ie.Visible = False
ie.navigate "http://stackoverflow.com/tags"
'Wait until IE is done loading page
Do While ie.READYSTATE <> READYSTATE_COMPLETE
Application.StatusBar = "Trying to go to StackOverflow ..."
DoEvents
Loop
'show text of HTML document returned
Set html = ie.document
'close down IE and reset status bar
Set ie = Nothing
Application.StatusBar = ""
'clear old data out and put titles in
'Cells.Clear
'put heading across the top of row 3
Range("A3").Value = "Date Pulled"
Range("B3").Value = "Keyword"
Range("C3").Value = "# Of Tags"
'Range("C3").Value = "Asked This Week"
Range("D3").Value = "Description"
Dim TagList As IHTMLElement
Dim Tags As IHTMLElementCollection
Dim Tag As IHTMLElement
Dim RowNumber As Long
Dim TagFields As IHTMLElementCollection
Dim TagField As IHTMLElement
Dim Keyword As String
Dim NumberOfTags As String
'Dim AskedThisWeek As String
Dim TagDescription As String
'Dim QuestionFieldLinks As IHTMLElementCollection
Dim TodaysDate As Date
Set TagList = html.getElementById("tags-browser")
Set Tags = html.getElementsByClassName("tag-cell")
RowNumber = 4
For Each Tag In Tags
'if this is the tag containing the details, process it
If Tag.className = "tag-cell" Then
'get a list of all of the parts of this question,
'and loop over them
Set TagFields = Tag.all
For Each TagField In TagFields
'if this is the keyword, store it
If TagField.className = "post-tag" Then
'store the text value
Keyword = TagField.innerText
Cells(RowNumber, 2).Value = TagField.innerText
End If
If TagField.className = "item-multiplier-count" Then
'store the integer for number of tags
NumberOfTags = TagField.innerText
'NumberOfTags = Replace(NumberOfTags, "x", "")
Cells(RowNumber, 3).Value = Trim(NumberOfTags)
End If
If TagField.className = "excerpt" Then
Description = TagField.innerText
Cells(RowNumber, 4).Value = TagField.innerText
End If
TodaysDate = Format(Now, "MM/dd/yy")
Cells(RowNumber, 1).Value = TodaysDate
Next TagField
'go on to next row of worksheet
RowNumber = RowNumber + 1
End If
Next
Set html = Nothing
'do some final formatting
Range("A3").CurrentRegion.WrapText = False
Range("A3").CurrentRegion.EntireColumn.AutoFit
Range("A1:C1").EntireColumn.HorizontalAlignment = xlCenter
Range("A1:D1").Merge
Range("A1").Value = "StackOverflow Tag Trends"
Range("A1").Font.Bold = True
Application.StatusBar = ""
MsgBox "Done!"
End Sub
There's no need to scrape Stack Overflow when they make the underlying data available to you through things like the Data Explorer. Using this query in the Data Explorer should get you the results you need:
select t.TagName, t.Count, p.Body
from Tags t inner join Posts p
on t.ExcerptPostId = p.Id
order by t.count desc;
The permalink to that query is here and the "Download CSV" option which appears after the query runs is probably the easiest way to get the data into Excel. If you wanted to automate that part of things, the direct link to the CSV download of results is here
You can improve this to parse out exact elements but it loops all the pages and grabs all the tag info (everything next to a tag)
Option Explicit
Public Sub ImportStackOverflowData()
Dim ie As New InternetExplorer, html As HTMLDocument
Application.ScreenUpdating = False
With ie
.Visible = True
.navigate "https://stackoverflow.com/tags"
While .Busy Or .READYSTATE < 4: DoEvents: Wend
Set html = .document
Dim numPages As Long, i As Long, info As Object, item As Object, counter As Long
numPages = html.querySelector(".page-numbers.dots ~ a").innerText
For i = 1 To 2 ' numPages ''<==1 to 2 for testing; use to numPages
DoEvents
Set info = html.getElementById("tags_list")
For Each item In info.getElementsByClassName("grid-layout--cell tag-cell")
counter = counter + 1
Cells(counter, 1) = item.innerText
Next item
html.querySelector(".page-numbers.next").Click
While .Busy Or .READYSTATE < 4: DoEvents: Wend
Set html = .document
Next i
Application.ScreenUpdating = True
.Quit '<== Remember to quit application
End With
End Sub
I'm not making use of the DOM, but I find it very easy to get around just searching between known tags. If ever the expressions you are looking for are too common just tweak the code a bit so that it looks for a string after a string).
An example:
Public Sub ZipLookUp()
Dim URL As String, xmlHTTP As Object, html As Object, htmlResponse As String
Dim SStr As String, EStr As String, EndS As Integer, StartS As Integer
Dim Zip4Digit As String
URL = "https://tools.usps.com/go/ZipLookupResultsAction!input.action?resultMode=1&companyName=&address1=1642+Harmon+Street&address2=&city=Berkeley&state=CA&urbanCode=&postalCode=&zip=94703"
Set xmlHTTP = CreateObject("MSXML2.XMLHTTP")
xmlHTTP.Open "GET", URL, False
On Error GoTo NoConnect
xmlHTTP.send
On Error GoTo 0
Set html = CreateObject("htmlfile")
htmlResponse = xmlHTTP.ResponseText
If htmlResponse = Null Then
MsgBox ("Aborted Run - HTML response was null")
Application.ScreenUpdating = True
GoTo End_Prog
End If
'Searching for a string within 2 strings
SStr = "<span class=""address1 range"">" ' first string
EStr = "</span><br />" ' second string
StartS = InStr(1, htmlResponse, SStr, vbTextCompare) + Len(SStr)
EndS = InStr(StartS, htmlResponse, EStr, vbTextCompare)
Zip4Digit = Left(Mid(htmlResponse, StartS, EndS - StartS), 4)
MsgBox Zip4Digit
GoTo End_Prog
NoConnect:
If Err = -2147467259 Or Err = -2146697211 Then MsgBox "Error - No Connection": GoTo End_Prog 'MsgBox Err & ": " & Error(Err)
End_Prog:
End Sub

Message box not always visible

I have the following VBA code that it is intended to download a file from the web, give me a message "Downloading Data from ..." and as soon as downloaded give me a message "Downloaded to ...". Here is my code:
Sub DownloadFileFromWeb()
Dim IE As Object
Dim links As Variant, lnk As Variant
Dim download_path As String
download_path = "\\xxxxx\Save Raw File here.xls"
Set IE = CreateObject("InternetExplorer.Application")
IE.Navigate "http://www.hkma.gov.hk/eng/market-data-and-statistics/monthly-statistical-bulletin/table.shtml#section2" 'load web page
While IE.Busy
DoEvents 'wait until IE is done loading page.
Wend
Set links = IE.document.getElementsByTagName("a")
For Each lnk In links
If Len(lnk.href) > 4 And Right(lnk.href, 4) = ".xls" And InStr(1, lnk.href, "http://www.hkma.gov.hk/media/eng/doc/market-data-and-statistics/monthly-statistical-bulletin/T080102.xls") <> 0 Then
MsgBox "Downloading Data from " & lnk.href
Download_File lnk.href, download_path
MsgBox "Downloaded to - " & download_path
Exit For
End If
Next
End Sub
Function Download_File(ByVal vWebFile As String, ByVal vLocalFile As String) As Boolean
Dim oXMLHTTP As Object, i As Long, vFF As Long, oResp() As Byte
Set oXMLHTTP = CreateObject("MSXML2.XMLHTTP")
oXMLHTTP.Open "GET", vWebFile, False 'Open socket to get the website
oXMLHTTP.Send 'send request
'Wait for request to finish
Do While oXMLHTTP.readyState <> 4
DoEvents
Loop
oResp = oXMLHTTP.responseBody 'Returns the results as a byte array
'Create local file and save results to it
vFF = FreeFile
If Dir(vLocalFile) <> "" Then Kill vLocalFile
Open vLocalFile For Binary As #vFF
Put #vFF, , oResp
Close #vFF
'Clear memory
Set oXMLHTTP = Nothing
End Function
The problem i have with this one is that most of the times i will not get any message box appearing and nothing gets downloaded in the meantime. Can you please help me in order to get the message box all of the time?
Thank you very much!
Tested your code on my end and I can see no errors. I've downloaded it like a hundred times already and it doesn't break. However, I made some minor modifications.
Change your main subroutine to the following:
Sub DownloadFileFromWeb()
Dim IE As Object
Dim links As Variant, lnk As Variant
Dim download_path As String
download_path = "C:\...\SavedFile.xls" 'Modify.
Set IE = CreateObject("InternetExplorer.Application")
IE.Navigate "http://www.hkma.gov.hk/eng/market-data-and-statistics/monthly-statistical-bulletin/table.shtml#section8" 'load web page
While IE.Busy
DoEvents 'wait until IE is done loading page.
Wend
Set links = IE.document.getElementsByTagName("a")
For Each lnk In links
If Len(lnk.href) > 4 And Right(lnk.href, 4) = ".xls" And InStr(1, lnk.href, "T080102.xls") <> 0 Then
If MsgBox("Downloading Data from " & lnk.href, vbOKOnly) = vbOK Then
Download_File lnk.href, download_path
MsgBox "Downloaded to - " & download_path
Exit For
End If
End If
Next
End Sub
Basically, I just changed one thing: the message box will wait for your input before it downloads the file. Notice how I did If MsgBox(...) = vbOKOnly. This way, it will wait for your input and not break.
Minor change as well to URL. Changed section2 to section8, since that's the table you want (not going to affect anything, IMHO).
Let us know if this helps.