(Excel VBA): Accessing JSON file - operation timed out - html

I'm attempting to pull data from a JSON file on the web. I'm using a dummy JSON file for the time being to get things working. My code is below, but it times out every time and doesn't return anything. The same happens if I use different URLs also.
Sub Test()
Dim strResult As String
Dim objHTTP As Object
Dim URL As String
Set objHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
URL = "https://jsonplaceholder.typicode.com/posts/2"
objHTTP.Open "GET", URL, False
objHTTP.Send
strResult = objHTTP.ResponseText
MsgBox strResult
End Sub
In case it's relevant, I have the following libraries enabled in the file:
Visual Basic for Applications
Microsoft Excel 15.0 Object Library
OLE Automation
Microsoft Scripting Runtime
Microsoft WinHTTP Services, version 5.1
What am I missing?
EDIT: Fixed. I wasn't aware of the distinction between WinHttpRequest and XMLHTTPRequest. When using the latter, the code worked fine. Thanks all.

Is there a special reason why using WinHttpRequest instead of XMLHTTPRequest?
While using WinHttpRequest the operating system defaults for HTTP requests - proxy settings for example - are not used and must be set explicitly:
Sub Test()
Dim strResult As String
Dim objHTTP As Object
Dim URL As String
Set objHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
objHTTP.SetProxy 2, "proxyIP:proxyPort"
URL = "https://jsonplaceholder.typicode.com/posts/2"
objHTTP.Open "GET", URL, False
objHTTP.setCredentials "username", "password", 1
objHTTP.Send
strResult = objHTTP.ResponseText
MsgBox strResult
End Sub
The 2 in IWinHttpRequest::SetProxy method is HTTPREQUEST_PROXYSETTING_PROXY.
The 1 in IWinHttpRequest::SetCredentials method is HTTPREQUEST_SETCREDENTIALS_FOR_PROXY.
While using XMLHTTPRequest the operating system defaults for HTTP requests are used as set in Internet Options in control panel. So the following should run if you are able accessing the URL via browser:
Sub Test()
Dim strResult As String
Dim objHTTP As Object
Dim URL As String
Set objHTTP = CreateObject("MSXML2.XMLHTTP.6.0")
URL = "https://jsonplaceholder.typicode.com/posts/2"
objHTTP.Open "GET", URL, False
objHTTP.Send
strResult = objHTTP.ResponseText
MsgBox strResult
End Sub

Your code works OK here, but perhaps you should .WaitForResponse if things are timing out:
Sub Test()
Dim strResult As String
Dim objHTTP As Object
Dim URL As String
Set objHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
URL = "https://jsonplaceholder.typicode.com/posts/2"
objHTTP.Open "GET", URL, False
objHTTP.Send
objHTTP.waitforresponse
strResult = objHTTP.ResponseText
MsgBox strResult
End Sub

Related

VBA Code to Call API Returns XML instead of JSON

I am using an API. I have credentials. It returns XML instead of JSON.
Sub usbRequest()
Dim objRequest As MSXML2.XMLHTTP60
Dim strURL As String
Set objRequest = New MSXML2.XMLHTTP60
strURL = "https://someAPIURL.com/"
objRequest.Open "GET", strURL, True, "MyUserName", "MyPassword"
objRequest.setRequestHeader "Content-Type", "application/json"
objRequest.send
While objRequest.readyState <> 4
DoEvents
Wend
Debug.Print objRequest.responseText
End Sub
The API Documentation indicates that an Accept header specifying JSON should return JSON. I do have a reference set to Microsoft XML V 6.0.

How to extract data from an API JSON response?

I am trying to extract data from an API JSON response. Everywhere I read says to use JsonConverter.ParseJson and then you can use the data by doing something like Debug.Print jsonObject("name").
I get a 424 error.
Sub get_request_expansions()
Dim ws As Worksheet
Dim jsonObject As Object
Dim sURL As String
Set request = CreateObject("winhttp.winhttprequest.5.1")
sURL = "https://api.scryfall.com/sets/jmp/"
request.Open "GET", sURL, False
request.send
'----------
Debug.Print request.responseText
Set jsonObject = JsonConverter.ParseJson(request.responseText)
Debug.Print jsonObject("name")
'----------
request.abort
End Sub

VBA to parse data from web API

Public Sub IMPORTMESTER()
Dim xTOK As String
Dim URL As String
Dim httpREQ As Object
Dim JSON As Object
Dim xLINE As Variant
xTOK = "bdj62bzknriy3dd9g561on2xl2"
URL = "https://api.smartsheet.com/2.0/sheets/7352150637471620"
Set httpREQ = CreateObject("MSXML2.XMLHTTP.6.0")
With httpREQ
.Open "GET", URL, False
.setRequestHeader "Authorization", "Bearer " & xTOK
.setRequestHeader "Content-Type", "application/json"
.Send
End With
xLINE = httpREQ.ResponseText
MsgBox ("Complete!")
End Sub
So, Ive returned data I need, but I tried several methods to parse it and paste in excel, but without success. Here is the part of responsetext:
"cells":[{"columnId":2400415921792900,"value":"MWP08","displayValue":"MWP08"},{"columnId":6904015549163396,"value":"A-WP-80301D5D10C00","displayValue":"A-WP-80301D5D10C00"},{"columnId":1274516014950276,"value":"MWP0830W27V50KD","displayValue":"MWP0830W27V50KD"},{"columnId":5778115642320772,"value":"WP08 30W,120-277VAC,Ra70 5000K Clear lens,Dark bronze","displayValue":"WP08 30W,120-277VAC,Ra70 5000K Clear lens,Dark bronze"},{"columnId":3526315828635524,"value":"image002.png","displayValue":"image002.png","formula":"=SYS_CELLIMAGE(\"image002.png\",\"vDOY-InMRamvhitNGotKzb\",35,52,\"image.png\")","image":{"id":"vDOY-InMRamvhitNGotKzb","height":35,"width":52,"altText":"image002.png"}},{"columnId":8029915456006020},{"columnId":711566061528964,"value":1884.0,"displayValue":"1884","linkInFromCell":{"status":"INACCESSIBLE","sheetId":4533800614029188,"rowId":null,"columnId":null,"sheetName":"MLC-Inventory扣减(2019)"}},{"columnId":2963365875214212,"value":"https://mesterleds.com/wp-content/uploads/2017/12/WP01-45W70W.png","displayValue":"https://mesterleds.com/wp-content/uploads/2017/12/WP01-45W70W.png"},{"columnId":7466965502584708},{"columnId":1837465968371588},{"columnId":6341065595742084},{"columnId":4089265782056836},{"columnId":8592865409427332},{"columnId":430091084818308,"value":175.0,"displayValue":"175"},{"columnId":4933690712188804},{"columnId":2681890898503556},{"columnId":7185490525874052},{"columnId":1555990991660932},{"columnId":6059590619031428}]},{"id":7080298036914052,"rowNumber":3,"siblingId":2576698409543556,"expanded":true,"createdAt":"2019-01-31T00:06:35Z","modifiedAt":"2019-02-18T16:56:50Z",
Each row of table I need starts with:"cells';[{" while I only need "displayValue": for columns!
I tried several solutions and suggestions from various threads from StackOverflow but... no luck!
Below is desired output:
Final excel format (unneccessary columns hidden)
If only after displayValue you can use the following with jsonconverter.bas. You add the .bas to your project and then VBE > Tools > References> Add a reference to Microsoft Scripting Runtime.
Option Explicit
Public Sub IMPORTMESTER()
Dim xTOK As String
Dim URL As String
Dim httpREQ As Object
Dim json As Object
Dim xLINE As Variant
xTOK = "token"
URL = "https://api.smartsheet.com/2.0/sheets/7352150637471620"
Set httpREQ = CreateObject("MSXML2.XMLHTTP.6.0")
With httpREQ
.Open "GET", URL, False
.setRequestHeader "Authorization", "Bearer " & xTOK
.setRequestHeader "Content-Type", "application/json"
.send
End With
xLINE = httpREQ.responseText
Set json = JsonConverter.ParseJson(xLINE)("rows")
Dim item As Object, nextitem As Object, i As Long
For Each item In json
For Each nextitem In item("cells")
i = i + 1
ActiveSheet.Cells(i, 1) = nextitem("displayValue")
Next
Next
End Sub
The item you want is nested within the json where {} is a dictionary, and [] is a collection.

VBA Function not returning HTMLElementCollection object

I'm attempting to return a HTMLElementCollection from a function. However, function-wise everything works as it should, but when the code returns to the calling sub, the variable assigned to the Functions output, "myTable", shows "< No Variables >". I've tried passing the collection back as part of a scripting.dictionary but with the same result.
Any help is appreciated. Thanks all.
Sub updateReports()
'//Function gathers latest report information and adds to sheets("Reports")
'//URL
Dim strURL As String
strURL = "http://www.ndbc.noaa.gov/station_page.php?station=62103"
Dim myTable As HTMLElementCollection
Set myTable = getTable(strURL)
'$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
'From here on, "myTable" listed as '<No Variables>'.
'HTMLElementCollection not sucessfully returned.
'$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
End Sub
Public Function getTable(strURL As String) As Variant
'//Downloads HTML Table from strURL
'//Create HTTP Object
Dim oXMLHTTP As Object
Set oXMLHTTP = CreateObject("MSXML2.XMLHTTP.6.0")
oXMLHTTP.Open "GET", strURL, False
oXMLHTTP.send
Dim HTMLDoc As New HTMLDocument
If oXMLHTTP.Status = 200 Then
HTMLDoc.body.innerHTML = oXMLHTTP.responsetext
Set getTable = HTMLDoc.getElementsByTagName("tr")()
'$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
'Under "getTable" call stack, getTable shows correct object (HTMLElementCollection)
'$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
End If
End Function
After some testing, I think I figured it out what's going on... Try creating the HTMLDocument in the main sub (updateReports) and pass it to the getTable function through an byRef Argument. Also change the returning type of the function to HTMLElementCollection. Something like that:
Sub updateReports()
'//Function gathers latest report information and adds to sheets("Reports")
'//URL
Dim strURL As String
strURL = "http://www.ndbc.noaa.gov/station_page.php?station=62103"
Dim myTable As HTMLElementCollection
Dim HTMLDoc As New HTMLDocument
Set myTable = getTable(strURL, HTMLDoc)
'$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
'From here on, "myTable" listed as '<No Variables>'.
'HTMLElementCollection not sucessfully returned.
'$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
End Sub
Public Function getTable(strURL As String, ByRef HTMLDoc As HTMLDocument) As HTMLElementCollection
'//Downloads HTML Table from strURL
'//Create HTTP Object
Dim oXMLHTTP As Object
Set oXMLHTTP = CreateObject("MSXML2.XMLHTTP.6.0")
oXMLHTTP.Open "GET", strURL, False
oXMLHTTP.send
If oXMLHTTP.Status = 200 Then
HTMLDoc.body.innerHTML = oXMLHTTP.responsetext
Set getTable = HTMLDoc.getElementsByTagName("tr")()
'$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
'Under "getTable" call stack, getTable shows correct object (HTMLElementCollection)
'$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
End If
End Function
Let me know if this works out for you!

objHTTP.Open unable to compile

I am attempting to send a POST URL message from MS Access VBA. When I attempt to run the code, it tells me that is not able to compile the following statement. Does anyone have any idea where I am incorrect in my syntax? Thank you in advance for assistance.
objHTTP.Open "POST", "http://kt1.com/apiv2/Configuration.asmx", False
The full code is:
Private Sub newKT_WebService_Click()
Dim objHTTP As String
Dim replyTXT As String
Dim AuthCode As String
objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
objHTTP.Open "POST", "http://kt1.com/apiv2/Configuration.asmx", False
objHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
objHTTP.send ("CallingID=12345&token=%20&domain=%20&userName=testuser&password=testpassword")
MsgBox objHTTP.responseText
End Sub
objHTTP was declared as String. But later the code attempts to assign an object reference to it. So declare objHTTP as Object. And you must use the Set keyword to assign to the object variable.
Dim objHTTP As Object
Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
objHTTP.Open "POST", "http://kt1.com/apiv2/Configuration.asmx", False
I'm not really familiar with MSXML2.ServerXMLHTTP but hopefully those changes will allow the code to compile and do what you need.