Login into website using MSXML2.XMLHTTP instead of InternetExplorer.Application with VBA - vba

first time posting,
I'm trying to get the ID "dadosDoUsuario" from a website's page I have to be logged in. I got it working using "InternetExplorer.Application" object, but can't get the ID value when using "MSXML2.XMLHTTP" object. It seems it won't go past the login page, since I'm able to get other IDs from this page (example: "tituloPagina"). Could someone give a hint on how I get the data from the page after logged in? Thanks!
InternetExplorer.Application code (this one works):
Sub testIE()
Dim texto As String
Set ie = CreateObject("InternetExplorer.Application")
my_url = "https://www.nfp.fazenda.sp.gov.br/login.aspx"
With ie
.Visible = False
.Navigate my_url
Do Until Not ie.Busy And ie.readyState = 4
DoEvents
Loop
End With
ie.Document.getelementbyid("userName").Value = "MYUSERNAME"
ie.Document.getelementbyid("Password").Value = "MYPASSWORD"
ie.Document.getelementbyid("Login").Click
Do Until Not ie.Busy And ie.readyState = 4
DoEvents
Loop
ie.Document.getelementbyid("btnConsultarNFSemestre").Click
Do Until Not ie.Busy And ie.readyState = 4
DoEvents
Loop
texto = ie.Document.getelementbyid("dadosDoUsuario").innerText
MsgBox texto
ie.Quit
End Sub
MSXML2.XMLHTTP code (this one doesn't work):
Sub testXMLHTTP()
Dim xml As Object
Dim html As Object
Dim dados As Object
Dim text As Object
Set xml = CreateObject("MSXML2.XMLHTTP")
Set html = CreateObject("htmlFile")
With xml
.Open "POST", "https://www.nfp.fazenda.sp.gov.br/Login.aspx", False
.setRequestHeader "Content-Type", "text/xml"
.send "userName=MYUSERNAME&password=MYPASSWORD"
.Open "GET", "https://www.nfp.fazenda.sp.gov.br/Inicio.aspx", False
.setRequestHeader "Content-Type", "text/xml"
.send
End With
html.body.innerhtml = xml.responseText
Set objResult = html.GetElementById("dadosDoUsuario")
GetElementById = objResult.innertext
MsgBox GetElementById
End Sub
EDIT: I followed the steps suggested by #Florent B., and added a scripcontrol to get the encoded values for __VIEWSTATE, __VIEWSTATEGENERATOR and __EVENTVALIDATION. Got it working!
Sub testXMLHTTP()
Dim xml As Object
Dim html As HTMLDocument
Dim dados As Object
Dim text As Object
Dim html2 As HTMLDocument
Dim xml2 As Object
Set xml = CreateObject("Msxml2.ServerXMLHTTP.6.0")
Set html = CreateObject("htmlFile")
With xml
.Open "GET", "https://www.nfp.fazenda.sp.gov.br/Login.aspx", False
.send
End With
strCookie = xml.getResponseHeader("Set-Cookie")
html.body.innerhtml = xml.responseText
Set objvstate = html.GetElementById("__VIEWSTATE")
Set objvstategen = html.GetElementById("__VIEWSTATEGENERATOR")
Set objeventval = html.GetElementById("__EVENTVALIDATION")
vstate = objvstate.Value
vstategen = objvstategen.Value
eventval = objeventval.Value
'URL Encode ViewState
Dim ScriptEngine As ScriptControl
Set ScriptEngine = New ScriptControl
ScriptEngine.Language = "JScript"
ScriptEngine.AddCode "function encode(vstate) {return encodeURIComponent(vstate);}"
Dim encoded As String
encoded = ScriptEngine.Run("encode", vstate)
vstate = encoded
'URL Encode Event Validation
ScriptEngine.AddCode "function encode(eventval) {return encodeURIComponent(eventval);}"
encoded = ScriptEngine.Run("encode", eventval)
eventval = encoded
'URL Encode ViewState Generator
ScriptEngine.AddCode "function encode(vstategen) {return encodeURIComponent(vstategen);}"
encoded = ScriptEngine.Run("encode", vstategen)
vstategen = encoded
Postdata = "__EVENTTARGET=" & "&__EVENTARGUMENT=" & "&__VIEWSTATE=" & vstate & "&__VIEWSTATEGENERATOR=" & vstategen & "&__EVENTVALIDATION=" & eventval & "&ctl00$ddlTipoUsuario=#rdBtnNaoContribuinte" & "&ctl00$UserNameAcessivel=Digite+o+Usuário" & "&ctl00$PasswordAcessivel=x" & "&ctl00$ConteudoPagina$Login1$rblTipo=rdBtnNaoContribuinte" & "&ctl00$ConteudoPagina$Login1$UserName=MYUSERNAME" & "&ctl00$ConteudoPagina$Login1$Password=MYPASSWORD" & "&ctl00$ConteudoPagina$Login1$Login=Acessar" & "&ctl00$ConteudoPagina$Login1$txtCpfCnpj=Digite+o+Usuário"
Set xml2 = CreateObject("Msxml2.ServerXMLHTTP.6.0")
Set html2 = CreateObject("htmlFile")
With xml2
.Open "POST", "https://www.nfp.fazenda.sp.gov.br/Login.aspx", False
.setRequestHeader "Cookie", strCookie
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.setRequestHeader "Content-Lenght", Len(Postdata)
.send (Postdata)
End With
html2.body.innerhtml = xml2.responseText
Set objResult = html2.GetElementById("dadosDoUsuario")
GetElementById = objResult.innertext
MsgBox GetElementById
End Sub

It's possible but not that easy.
First you need to use CreateObject("Msxml2.ServerXMLHTTP.6.0") and not CreateObject("MSXML2.XMLHTTP").
Then follow these steps:
Open and send a GET to https://www.nfp.fazenda.sp.gov.br/login.aspx
Parse and store the cookie from the response header "Set-Cookie"
Parse and store the __VIEWSTATE, __VIEWSTATEGENERATOR, __EVENTVALIDATION from the HTML response
Build the data for the next query with the values parsed previously and with your user-name/password :
__EVENTTARGET:""
__EVENTARGUMENT:""
__VIEWSTATE:"..."
__VIEWSTATEGENERATOR:"..."
__EVENTVALIDATION:"..."
ctl00$ddlTipoUsuario:"#rdBtnNaoContribuinte"
ctl00$UserNameAcessivel:"Digite+o+Usuário"
ctl00$PasswordAcessivel:"x"
ctl00$ConteudoPagina$Login1$rblTipo:"rdBtnNaoContribuinte"
ctl00$ConteudoPagina$Login1$UserName:"..."
ctl00$ConteudoPagina$Login1$Password:"..."
ctl00$ConteudoPagina$Login1$Login:"Acessar"
ctl00$ConteudoPagina$Login1$txtCpfCnpj:"Digite+o+Usuário"
Open a POST to https://www.nfp.fazenda.sp.gov.br/login.aspx
Set the header "Cookie" with the cookie parsed at step 2
Set the header Content-Type: "application/x-www-form-urlencoded"
Set the header Content-Length with the length of the data
Send the POST with the data from step 4

Related

Rest API in VBA Macros

When i wrote a http get request in vba to get the session id , instead of getting the session id , i am getting an HTML code in the immediate window?
Why is this so?
So basically , when you open the link on browser it will first ask the user to enter his username and password , then it will show him the session id.
But when i select the link in vba code , it shows me the html code
Sub Button1_Click()
Dim objRequest As Object
Dim strUrl As String
Dim blnAsync As Boolean
Dim strResponse As String
Set objRequest = CreateObject("MSXML2.XMLHTTP")
strUrl = "url to be entered"
blnAsync = True
With objRequest
.Open "GET", strUrl, blnAsync
.SetRequestHeader "Content-Type", "application/json"
.Send
'spin wheels whilst waiting for response
While objRequest.readyState <> 4
DoEvents
Wend
strResponse = .ResponseText
End With
Debug.Print strResponse
End Sub

Getting meta proper content from url

I am trying to get meta proper content from url but facing some problem
i want to grab "og:url" content detail, here is my code
Sub GrabCanonicalUrl3()
Const Url$ = "https://www.justdial.com/Ambala/Beauty-Parlours-in-Naraingarh"
Dim S$
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", Url, False
.Send
S = Replace(Replace(.responseText, "<!--", ""), "-->", "")
End With
With New HTMLDocument
.body.innerHTML = S
MsgBox .querySelector("meta[property='og:url']").getAttribute("content")
End With
End Sub
facing this earror
Object variable or block variable not set
MsgBox .querySelector("meta[property='og:url']").getAttribute("content")
I want to get url (og:url) link from inner HTML . but not
please help me out
Try this code
Sub Test()
Dim obj As Object, sResp As String
With CreateObject("MSXML2.xmlHttp")
.Open "GET", "https://www.justdial.com/Ambala/Beauty-Parlours-in-Naraingarh", False
.send
sResp = .responseText
End With
With CreateObject("HTMLFile")
.write sResp
For Each obj In .all(2).getElementsByTagName("meta")
If obj.getAttribute("Property") = "og:url" Then Debug.Print obj.Content: Exit For
Next obj
End With
End Sub

Sending Photo to Telegram (API / Bot)

I send messages form Excel to telegram. It works nice.
But how can I send a photo? I don't understand it (https://core.telegram.org/bots/api#sendphoto)
Thanks for help!
My send Message:
Dim objRequest As Object
Dim strChatId As String
Dim strMessage As String
Dim strPostData As String
Dim strResponse As String
strChatId = Worksheets("Einstellungen").Cells(3, "AB")
strMessage = Report
APIcode = Worksheets("Einstellungen").Cells(2, "AB")
strPostData = "chat_id=" & strChatId & "&text=" & strMessage
Set objRequest = CreateObject("MSXML2.XMLHTTP")
With objRequest
.Open "POST", "https://api.telegram.org/" & APIcode & "/sendMessage?", False
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.send (strPostData)
GetSessionId = .responseText
End With
If your code is working as-is for plain text messages then you should only need to make a couple changes to it.
You're probably currently using the API's sendMessage method, which takes the chat_id and text parameters.
You want to use the sendPhoto method, which tales the chat_id and photo parameters (but no text parameter).
So this is a bit of a shot in the dark since I've never used or heard of Telegram and I don't have a key, so I can't test it, but theoretically, you could send a photo from a URL like this:
Sub telegram_SendPhoto()
Const photoURL = "https://i.imgur.com/0eH6d1v.gif" 'URL of photo
Dim objRequest As Object, strChatId As String, APIcode As String
Dim strPostData As String, strResponse As String
strChatId = Worksheets("Einstellungen").Cells(3, "AB")
APIcode = Worksheets("Einstellungen").Cells(2, "AB")
strPostData = "chat_id=" & strChatId & "&photo=" & photoURL
Set objRequest = CreateObject("MSXML2.XMLHTTP")
With objRequest
.Open "POST", "https://api.telegram.org/" & APIcode & "/sendPhoto?", False
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.send (strPostData)
strResponse = .responseText
End With
MsgBox strResponse
End Sub
Pass a file_id as String to send a photo that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get a photo from the Internet (above), or upload a new photo using multipart/form-data. More info on Sending Files »

"LOADING" SOAP response to DOMDocument

After some help from stackoverflow experts I have been able to successfully retrieve my response using SOAP. The below piece is how I received and stored the data. This of course is not all the code. I just included this to show how I later reference the xml.
With xmlhtp
webserviceSOAPActionNameSpace = "http://example.com/webservices/"
.Open "POST", sUrl, False
.setRequestHeader "POST", "https://onesite.example.com/webservices/stuff.asmx HTTP/1.1"
.setRequestHeader "Content-Type", "text/xml; charset=utf-8"
.setRequestHeader "Content-Length", 100
.setRequestHeader "SOAPAction", webserviceSOAPActionNameSpace & "RetrieveData"
.send sEnv
sResult = xmlhtp.statusText
responseText = xmlhtp.responseText
ActiveSheet.Cells(1, 1).Value = .responseText
End With
Debug.Print responseText
Now I am having trouble parsing that out. This seems like it should be pretty simple but I get an error indicating that the responseText I receive above is not "loading" to xmlDOC. The following is at the beginning of the sub:
Dim xmlhtp As New MSXML2.XMLHTTP
Dim xmlDoc As New DOMDocument
Dim XDoc As Object
After the With End (shown above) my code looks like this:
Set XDoc = CreateObject("MSXML2.DOMDocument")
XDoc.async = False: XDoc.validateOnParse = False
XDoc.Load (xmlhtp.responseText)
Set lists = XDoc.DocumentElement
Set getFirstChild = lists.FirstChild
Debug.Print getFirstChild.XML
Debug.Print getFirstChild.Text
On the line
Set getFirstChild = lists.FirstChild
I recieve the following error
Object variable or With block variable not set
When I look at the Local Variable window in VBA I can clearly see that nothing was assigned to xmlDoc. So I assume my problem is in XDoc.Load Line.
Any direction would be appreciated.
use XDoc.LoadXML (xmlhtp.responseText) instead of XDoc.Load (xmlhtp.responseText)

MSXML2.ServerXMLHTTP - can't access website

For instance, kat.cr is one of the few websites I cannot access.
In the response, I get 2 symbols instead of the actual webpage:
Here's the VBA code I'm using:
url = "https://kat.cr"
Set xmlHTTP = CreateObject("MSXML2.serverXMLHTTP")
xmlHTTP.Open "GET", url, False
xmlHTTP.setRequestHeader "Accept-Language", "en-US,en;q=0.8"
xmlHTTP.setRequestHeader "Content-Type", "text/xml"
xmlHTTP.Send
Set html = CreateObject("htmlfile")
response = xmlHTTP.responseText
Is the website actually denying me access or am I doing something wrong?
Use CreateObject("MSXML.XMLHTTP") for client applications. ServerXMLHttp is meant for server applications. See this article for more information on the two.
Set xmlHTTP = CreateObject("MSXML2.XMLHTTP")
xmlHTTP.Open "GET", "https://kat.cr", False
xmlHTTP.Send
Debug.Print xmlHTTP.responseText
The website is not denying you access, it's your code I am afraid. Below is a quick example to get the HTML you want from the page you visit.
Note: This was just a quick type-o, but to help get you in the right direction.
Dim ie As InternetExplorer
Dim html As HTMLDocument
Set ie = New InternetExplorer
ie.Visible = False
ie.navigate "https://kat.cr"
Set html = ie.document
'this is the inner html -html.DocumentElement.innerHTML
Set ie = Nothing
Edit - This might be a better solution for you
Set xmlHTTP = New MSXML2.XMLHTTP
xmlHTTP.Open "GET", "https://kat.cr", False
xmlHTTP.send
Dim doc As Object
Set doc = CreateObject("htmlfile")
doc.body.innerHTML = xmlHTTP.responseText
debug.print doc.body.innerHTML