Excel VBA get data from web with msxml2.xmlhttp - how do I accept cookies automatically? - vba

need your expertise and help, as i've looked around and couldn't find a solution:
I am uploading information to Excel from a website using the msxml2.xmlhttp method (did it earlier via webquery but it gets stuck after a few iterations plus it is slower). My problem is that now on every iteration, I have a Windows Security warning popping up asking me to accept a cookie from the website. Note that the website doesn't require a login/password. I understood from an earlier post that the msxml2.xmlhttp method strips cookies for security reasons, but I get the same message even if I change the method to winhttp. I also changed the settings in IE to accept all cookies automatically from the website but it didn't help.
My question is, what code do I need to add in order to have the cookies be accepted automatically, as I am looping this code on bulk and can't have it hang waiting for me to accept the cookie manually. Your help will be very much appreciated!!! Below is the code snippet (which I actually found here on Stackoverflow).
Set htm = CreateObject("htmlFile")
With CreateObject("msxml2.xmlhttp")
.Open "GET", "http://finance.yahoo.com/q/ae?s=" & Ticker & "+Analyst+Estimates", False
.send
htm.body.innerHTML = .responseText
End With
Set elemCollection = htm.getElementsByTagName("td")
For Each itm In elemCollection
If itm.className = "yfnc_tabledata1" Then
ActiveCell = itm.innerText
If ActiveCell.Column = 7 Then
ActiveCell.Offset(1, -6).Select
Else
ActiveCell.Offset(0, 1).Select
End If
End If
Next

I had the same problem this week.
After google and trying some ideas, I added two MsgBox statements to my code.
objXMLDoc.Open "GET", strURL, False
objXMLDoc.send
MsgBox "After XMLDoc.send", vbOKOnly, "Test"
objHTMLDoc.body.innerHTML = objXMLDoc.responseText
MsgBox "After .innerHTML assignment", vbOKOnly, "Test"
I found pop-up security warning windows always appear after .innerHTML assignment, i.e., the problem is nothing to do with XMLHttp. It is HTMLDocument, which causes the pop-ups.
I guess objHTMLDoc.body.innerHTML = objXMLDoc.responseText does not just do a simple value assignment. It must also trigged some action according to the contents of the webpage.
I checked the webpage and found some code like this:
YUI().use('node','event','event-mouseenter','substitute','oop','node-focusmanager','node','event','substitute','**cookie**','event-resize','node', 'event', 'querystring-stringify','node','event','node','event','event-custom','event-valuechange','classnamemanager','node', function(Y) {})
Then I changed my code as follows and the pop-up warning windows disappear.
objXMLDoc.Open "GET", strURL, False
objXMLDoc.send
objHTMLDoc.body.innerHTML = Replace(objXMLDoc.responseText, "cookie", "")
Hope this can be helpful if you still have the problem.

Related

How to POST JSON data to an API using VBscript

I am currently working on a signup form and I want users to be pushed to my hubspot account upon sign up. The form is built in a .asp file format using HTML, CSS, and VBscript. I want the user to fill out all of the required fields and then send their responses to Hubspot using their Create Contact API endpoint.
The form itself is built out and working, now all I need to do is link up the API POST request. I am not familiar with VBscript or how one could go about sending JSON data to an API using VB. I started out by just trying to send dummy data that would be easily searchable figuring I can work on making the values dynamic later, but even this won't work. This is the code that I have written directly in the markup. Any help is appreciated!
<%
Dim objXmlHttpMain, URL, strJSONToSend
strJSONToSend = "{'properties': [{'property': 'email','value': 'testingapis#hubspot.com'},{'property': 'firstname','value': 'Adrian'},{'property': 'lastname','value': 'Mott'},{'property': 'website','value': 'http://hubspot.com'},{'property': 'company','value': 'HubSpot'},{'property': 'phone','value': '555-122-2323'},{'property': 'address',},{'property': 'city','value': 'Cambridge'},'property': 'state','value': 'MA'},{'property': 'zip','value': '02139'}]}"
URL="https://api.hubapi.com/contacts/v1/contact/?hapikey=df670ac6-cc2d-452d-a571-11d0374e515e"
Set objXmlHttpMain = CreateObject("Msxml2.ServerXMLHTTP")
On Error Resume Next
objXmlHttpMain.open "POST",URL, False
If Err Then
WScript.Echo Err.Description & " [0x" & Hex(Err.Number) & "]"
WScript.Quit 1
End If
On Error Goto 0
objXmlHttpMain.open "POST",URL, False
objXmlHttpMain.setRequestHeader "Accept", "application/json>"
objXmlHttpMain.setRequestHeader "Content-Type", "application/json"
objXmlHttpMain.send strJSONToSend
set objJSONDoc = nothing
set objResult = nothing
%>

Posting with an open event

Action: Trying to 'post' excel data to a webpage that the user sees/uses with a vba code event.
Issue: I can open a window with a get, or I can xmlhttp with a post and a get a response variable, but neither is what I need. I need to POST login information (a service account) from baked in vba code on a button to POST and open a browser.
The webpage is behind Spring Security and the service account credentials should not be known to the user, it's hidden in a protected workbook/vba. I need to post those over to the url.
--> How do I open AND post at the same time?
What I need is the excel equivalent of an HTML form post with a
target=_blank
attribute in vba. Is this possible?
I've tried both
ShellExecute
functions
and
xmlhttp
methods
but both only give me half of the package.
Any advice?
Adding to what #Florent B. has posted, check whether the cookie is set when calling the login page (which I assume) or really when posting the login data.
Dim xhttp As MSXML2.XMLHTTP ' make sure you reference to MSXML!
Dim strCookie As String
Set xHttp = New MSXML2.XMLHTTP
XMLHttp.Open "GET" TheURLOfYourLogInPage
If xHttp.Status = 200 Then
strCookie = xHttp.getResponseHeader("Set-Cookie")
End If
Check your web browser for what is sent to the server when login in, probably something like "username=" & YourUserName & "&password=" & YourPassword & "&cookie=" & strCookie Declare another string variable (I will call it strTicker) and fill it accordingly, then
xHttp.Open "POST", "URLOfYourLoginPage"
xHttp.setRequestHeader "Cookie", strCookie
xHttp.send strTicker

Scraping a HTML POST request using VBA

I'm trying to scrape quotes of Moroccan stocks from this website using VBA :
http://www.casablanca-bourse.com/bourseweb/en/Negociation-History.aspx?Cat=24&IdLink=225
Where you select a security, check "By period", specify the date interval and finally click the "Submit" button.
I went first with the easy method : using an Internet Explorer object :
Sub method1()
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = False
IE.Navigate "http://www.casablanca-bourse.com/bourseweb/Negociation-Historique.aspx?Cat=24&IdLink=302"
Do While IE.Busy
DoEvents
Loop
'Picking the security
Set obj1 = IE.document.getElementById("HistoriqueNegociation1_HistValeur1_DDValeur")
obj1.Value = "4100 " 'Security code taken from the source html
'Specifying "By period"
Set obj2 = IE.document.getElementById("HistoriqueNegociation1_HistValeur1_RBSearchDate")
obj2.Checked = True
'Start date
Set obj3 = IE.document.getElementById("HistoriqueNegociation1_HistValeur1_DateTimeControl1_TBCalendar")
obj3.Value = "07/03/2016"
'End date
Set obj4 = IE.document.getElementById("HistoriqueNegociation1_HistValeur1_DateTimeControl2_TBCalendar")
obj4.Value = "07/03/2016"
'Clicking the button
Set objs = IE.document.getElementById("HistoriqueNegociation1_HistValeur1_Image1")
objs.Click
'Setting the data <div> as an object
Set obj5 = IE.document.getElementById("HistoriqueNegociation1_UpdatePanel1")
s = obj5.innerHTML
'Looping until the quotes pop up
Do While InStr(s, "HistoriqueNegociation1_HistValeur1_RptListHist_ctl01_Label3") = 0
Application.Wait DateAdd("s", 0.1, Now)
s = obj5.innerHTML
Loop
'Printing the value
Set obj6 = IE.document.getElementById("HistoriqueNegociation1_HistValeur1_RptListHist_ctl01_Label3")
Cells(1, 1).Value = CDbl(obj6.innerText)
IE.Quit
Set IE = Nothing
End Sub
This webpage being dynamic, I had to make the application wait, until the data pops up (until the data pops in the HTML code), and that's why I used that second Do while loop.
Now, what I want to do, is to use the harder way : sending the form request through VBA, which is pretty easy when it comes to GET requests, but this site uses a POST request that I found pretty hard to mimic in VBA.
I used this simple code :
Sub method2()
Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
URL = "http://www.casablanca-bourse.com/bourseweb/Negociation-Historique.aspx?Cat=24&IdLink=302"
objHTTP.Open "POST", URL, False
objHTTP.setRequestHeader "Content-type", "application/x-www-form-urlencoded"
objHTTP.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
objHTTP.send ("encoded request params go here")
Cells(1, 1).Value = objHTTP.ResponseText
End Sub
I used the Chrome DevTools (F12) to record the POST request. But I had a hard time figuring what the params should be (The form data is too long, i couldn't make a screenshot or copy it here, so please feel free to record it yourself). I went with the only params that I needed (security code, the radiobox and the two dates), but the request response didn't match the DevTools one, and it didn't contain any usable. Here are the params that I used :
HistoriqueNegociation1$HistValeur1$DDValeur=9000%20%20&HistoriqueNegociation1$HistValeur1$historique=RBSearchDate&HistoriqueNegociation1$HistValeur1$DateTimeControl1$TBCalendar=07%2F03%2F2016&HistoriqueNegociation1$HistValeur1$DateTimeControl2$TBCalendar=07%2F03%2F2016
Obviously, I'm not getting something (or everything) right here.
Actually, I can't just pick "some of the params", I have to send all of them. I didn't do that at first because the params line that I got from the DevTools was too long (47012 characters), Excel-VBA doesn't acccept a line that long. So I copied the params to a text file and then sent the request using that file, and It worked.

cURL via VBA (Maxmind)

I'm trying to run the following cURL request (as provided by Maxmind) within VBA:
curl -u "{user_id}:{license_key}" \
"https://geoip.maxmind.com/geoip/v2.1/city/me?pretty"
Taking from other examples I've tried the following:
Sub maxmind_query()
Dim TargetURL As String
Dim HTTPReq As Object
TargetURL = "https://geoip.maxmind.com/geoip/v2.1/city/me"
Set HTTPReq = CreateObject("WinHttp.WinHttpRequest.5.1")
HTTPReq.Option(4) = 13056 '
HTTPReq.Open "PUT", TargetURL, False
HTTPReq.SetCredentials "XXXXX", "YYYYYYYY", 0
HTTPReq.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
HTTPReq.send ("test[status]=" & Forms!curl!Text0.Value & "&test2[status]=" & Text2.Value)
MsgBox (HTTPReq.responseText)
End Sub
'''XXXX is my user id, YYYY my license key, removed for obvious reasons!
This errors at HTTPReq.send (runtime error 424 object required) which has me stumped.
I have no knowledge of cURL so despite a few days of research and blind attempts, I'm struggling to get anywhere with the above code.
I'm only experienced with VBA, and what I know is self taught, so be gentle....
If anyone is able to share their knowledge I'd be much obliged.
Further info provided by Maxmind:
http://dev.maxmind.com/geoip/geoip2/web-services/#Per-Service_URIs
http://dev.maxmind.com/geoip/geoip2/web-services/#Command_Line_curl_Example
Many thanks!
PS. If I put the URL in a browser, input username and password into message box, the browser returns the required information, so I know the service and my credentials work. I guess my code isn't even getting that far though.
Got it working, here's my approach:
Sub Maxmind()
Dim MyRequest As Object
Set MyRequest = CreateObject("WinHttp.WinHttpRequest.5.1")
MyRequest.Open "GET", _
"https://geoip.maxmind.com/geoip/v2.1/city/me"
MyRequest.SetCredentials "user", "password", 0
' Send Request.
MyRequest.Send
'And we get this response
MsgBox MyRequest.ResponseText
End Sub
This was mainly copied from here here
so thanks to previous contributors.
Hope it helps someone!

auto click yes on certificate Security warnings and Windows Security Warnings

I wrote a VBA code which would take its input(url) from a column of an excel sheet, and return its http status code. The problem I face is that some urls are having Certificate issues and for some websites I am getting Windows Security Alerts. I want a simple solution to automatically click on Yes for all these alerts (if they come at all) as these sites are comletely trusted. I am attaching the the code which checks for the status code.
`'Takes input url as String and return the status(200 is up ,rest all are down)
Function urlCheck(url As String) As Integer
On Error GoTo error_help
Dim http: Set http = CreateObject("MSXML2.XMLHTTP")
http.Open "GET", url, False
http.Send
If (Not http.Status = 200) Then
urlCheck = http.Status
Else
urlCheck = http.Status
End If
error_help:
'MsgBox "error"
End Function
`
I have already tried Application.DisplayAlerts = False , it doesn't work