Excel is a powerful and most popular tool for data analysis! HTTP requests in VBA gives additional capabilities to Excel. XmlHttpRequest object is used to make HTTP requests in VBA. HTTP requests can be used to interact with a web service, API or even websites. Let’s understand how it works.
Open an excel file and open VBA editor (Alt + f11) > new module and start writing code in a sub
Public sub XmlHttpTutorial End Sub
Define XMLHttpRequest
Define http client using following code
Dim xmlhttp as object Set xmlhttp = CreateObject("MSXML2.serverXMLHTTP")
If you need VBA’s Intellisense autocomplete then do it this way :
First, Add a reference to MSXML (Tools > references)
Select appropriate version based on your PC :
1. Microsoft XML, v 3.0.
2. Microsoft XML, v 4.0 (if you have installed MSXML 4.0 separately).
3. Microsoft XML, v 5.0 (if you have installed Office 2003 – 2007 which provides MSXML 5.0 for Microsoft Office Applications).
4. Microsoft XML, v 6.0 for latest versions of MS Office.
Then define http client
Dim xmlhttp As New MSXML2.XMLHTTP 'Dim xmlhttp As New MSXML2.XMLHTTP60 for Microsoft XML, v 6.0
VBA Intellisense will show you the right one when you start typing.
Make requests
Requests can be made using open and send methods. Open method syntax is as follows :
xmlhttp.Open Method, URL, async(true or false)
I’m using requestBin to test requests. Create a bin there and send requests to that URL to test requests.
A simple GET request would be :
Dim xmlhttp As New MSXML2.XMLHTTP60, myurl As String myurl = "http://requestb.in/15oxrjh1" //replace with your URL xmlhttp.Open "GET", myurl, False xmlhttp.Send MsgBox(xmlhttp.responseText)
Run this code, a message box is displayed with the response of the request.
Request headers
Request headers can be set using setRequestHeader method. Examples :
xmlhttp.setRequestHeader "Content-Type", "text/json" xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded" xmlhttp.setRequestHeader "User-Agent", "Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405" xmlhttp.setRequestHeader "Authorization", AuthCredentials
Simple POST request to send formdata
POST requests are used to send some data, data can be sent in Send
method. A simple POST request to send form data :
Public Sub httpclient() Dim xmlhttp As New MSXML2.XMLHTTP, myurl As String myurl = "http://requestb.in/15oxrjh1" xmlhttp.Open "POST", myurl, False xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded" xmlhttp.Send "name=codingislove&[email protected]" MsgBox (xmlhttp.responseText) End Sub
Basic Authentication in VBA
When we need to access web services with basic authentication, A username and password have to be sent with the Authorization header. Username and password should also be base64 encoded. Example :
user = "someusername" password = "somepassword" xmlhttp.setRequestHeader "Authorization", "Basic " + Base64Encode(user + ":" + password)
Here’s a paste of utility function that helps to encode string to Base64
Practical use cases
Practical use cases of http requests in VBA are unlimited. Some of them are pulling data from Yahoo finance API, weather API, pulling orders from Ecommerce store admin panel, uploading products, retrieving web form data to excel etc.
Read : Parse HTML in Excel VBA – Learn by parsing hacker news home page where I retrieve a web page using HTTP GET request and parse its HTML to get data from a web page.
Read How to build a simple weather app in Excel VBA where I make a HTTP Get request to weather API
Read JSON Api in Excel VBA where I call JSON Apis using HTTP GET and POST requests.
If you have and questions or feedback, comment below.
- Author
- Recent Posts
A CA- by education, self taught coder by passion, loves to explore new technologies and believes in learn by doing.
To complete the response of the other users:
For this I have created an «WinHttp.WinHttpRequest.5.1» object.
Send a post request with some data from Excel using VBA:
Dim LoginRequest As Object
Set LoginRequest = CreateObject("WinHttp.WinHttpRequest.5.1")
LoginRequest.Open "POST", "http://...", False
LoginRequest.setRequestHeader "Content-type", "application/x-www-form-urlencoded"
LoginRequest.send ("key1=value1&key2=value2")
Send a get request with token authentication from Excel using VBA:
Dim TCRequestItem As Object
Set TCRequestItem = CreateObject("WinHttp.WinHttpRequest.5.1")
TCRequestItem.Open "GET", "http://...", False
TCRequestItem.setRequestHeader "Content-Type", "application/xml"
TCRequestItem.setRequestHeader "Accept", "application/xml"
TCRequestItem.setRequestHeader "Authorization", "Bearer " & token
TCRequestItem.send
Уровень сложности
Средний
Время на прочтение
9 мин
Количество просмотров 14K
Работая в IoT-сфере и плотно взаимодействуя с одним из основных элементов данной концепции технологий – сетевым сервером, столкнулся вот с какой проблемой (задачей): необходимо отправлять много запросов для работы с умными устройствами на сетевой сервер. На сервере был реализован REST API с оболочкой Swagger UI, где из графической оболочки можно было отправлять только разовые запросы. Анализ сторонних клиентов, типа Postman или Insomnia показал, что простого визуального способа поместить в скрипт массив из необходимого перечня идентификаторов устройств (или любых других элементов сервера), для обращения к ним – не нашлось.
Так как большая часть работы с выгрузками и данными была в Excel, то решено было вспомнить навыки, полученные на учебе в университете, и написать скрипт на VBA, который бы мою задачку решал.
Необходимо было:
-
получать информацию по устройствам с различными параметрами фильтрации (GET);
-
применять изменения в конфигурации по устройствам: имя, профиль устройства, сетевые лицензии и пр. (PUT);
-
отправлять данные для конфигурации и взаимодействия с устройствами (POST).
И сегодня я расскажу вам про то, как с помощью Excel, пары формул и самописных функций на VBA можно реализовать алгоритм, отправляющий любое необходимое количество REST-API запросов с использованием авторизации Bearer Token.
Данная статья будет полезная тем, кто воспользуется данным решением под Windows, но еще больше она будет полезна тем людям, которые хотят использовать данное решение на MacOS (с Excel x64) . Как вы уже догадались, ниже будут рассмотрены два варианта реализации под разные системы, так как с MacOS есть нюанс.
Часть 1. Реализация решения под Windows
GET
Начнем с самого простого: GET – запросов. В данном примере необходимо получить ответ (информацию) от сервера по заданному списку устройств.
Для реализации GET – запросов нам дано:
1) Ссылка, в которой указываются параметры запроса.
https://dx-api.thingpark.io/core/latest/api/devices?deviceEUI=
2) Заголовки запроса + Токен авторизации (Bearer Token)
—header ‘Accept: application/json’ —header ‘Authorization: Bearer
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6WyJTVUJTQ1JJQkVSOjY3MDAiXSwiZXhwIjozNzc0MTY0MzE4LCJqdGkiOiI5OTNiOTk1Ny03NGY1LTQ5MDgtYjg4Ni0xYjk5NTVkZDQwZTEiLCJjbGllbnRfaWQiOiJkZXYxLWFwaS9lcnRoLnRlY2guZGVzayt2bGFkaXNsYXYuZ2F0Y2Vua29AZ21haWwuY29tIn0.dqybsMdVXXpQV8_ykufNZoQpSPZrVA67uieOJan-qs8W7rAImyy0552buniHXPWy6ilvdwJKPCdIKE__LghP6A
3) Параметр, указываемый в ссылке (в данном примере это идентификаторы устройств – DevEUI):
1ABCDEFF00AABBCC
0016ACC4DCF15A23
D88039FFFE954DF4
0000000000001103
0000000000001104
Имея такие данные на входе, делаем в Excel лист-шаблон, который заполняем в соответствии с тем, что имеем:
-
столбец А уходит вот значения параметров
-
столбец F уходит под ссылку-родителя
-
столбец H уходит под заголовки, где в ячейке H1 единоразово для текущего листа указывается токен:
=СЦЕП("--header 'Accept: application/json' --header 'Authorization: Bearer ";$H$1;"'")
-
столбец I уходит под URL (ссылки-дети, на основе ссылки-родителя)
=СЦЕПИТЬ($F$1;A2)
-
столбец J уходит под результат (ответ от сервера)
Далее, нам необходимо реализовать подпрограмму(макрос) отправки GET-запросов. Состоит она из четырех частей:
-
цикла, который считает количество строк для работы по листу, пробегая по столбцу А с 2 по первую пустую ячейку, чтобы у цикла был конец.
-
функции, для работы с REST API (используется стандартная, библиотека Msxml2.XMLHTTP.6.0, встроенная в Windows., поэтому сложностей с реализацией не возникает. Для MacOS есть альтернатива)
-
временной задержки, в случае если нужно отправлять запросы не сразу, после получения ответа, а задав время ожидания
-
таймером, который показывает время выполнения всего макроса после завершения
Код:
Sub GET_Request() Dim i As Integer Dim j As Integer Dim objHTTP As Object Dim Json As String Dim result As String Dim URL As String Dim Token As String a = Timer i = 1 Do While Not IsEmpty(Cells(i, 1)) i = i + 1 Loop i = i - 1 'MsgBox i For j = 2 To i Json = Range("D" & j) URL = Range("I" & j) Token = Range("H1") Set objHTTP = CreateObject("Msxml2.XMLHTTP.6.0") objHTTP.Open "GET", URL, False objHTTP.setRequestHeader "Content-type", "application/json" objHTTP.setRequestHeader "Accept", "application/json" objHTTP.setRequestHeader "Authorization", "Bearer " + Token objHTTP.Send (Json) result = objHTTP.responseText Range("J" & j).Value = result Set objHTTP = Nothing 'Application.Wait (Now + TimeValue("0:00:01")) Next j MsgBox Timer - a End Sub
Привязываем подпрограмму к кнопкам для удобства и выполним скрипт. Получается:
Таким образом, скрипт проходит по столбцу I, забирая из значения каждой ячейки URL, для тех строк, где в столбце А есть значения (которые и подставляются в URL). Для удобства также сделаны кнопки очистки полей и подсветка запросов условным форматированием, в случае успешного ответа на запрос.
PUT
Чуть-чуть усложним задачу и перейдем к PUT-запросам. В данном примере необходимо изменить профиль устройства, чтобы сервер по-другому с ним взаимодействовал.
К исходным данным для GET – запроса добавляется тело запроса с ключем-значением (п4). Итого дано:
1) Ссылка, в которой указываются параметры запроса.
https://dx-api.thingpark.io/core/latest/api/devices/
2) Заголовки запроса + Токен авторизации (Bearer Token)
—header ‘Content-Type: application/json’ —header ‘Accept: application/json’ —header ‘Authorization: Bearer
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6WyJTVUJTQ1JJQkVSOjY3MDAiXSwiZXhwIjozNzc0MTY0MzE4LCJqdGkiOiI5OTNiOTk1Ny03NGY1LTQ5MDgtYjg4Ni0xYjk5NTVkZDQwZTEiLCJjbGllbnRfaWQiOiJkZXYxLWFwaS9lcnRoLnRlY2guZGVzayt2bGFkaXNsYXYuZ2F0Y2Vua29AZ21haWwuY29tIn0.dqybsMdVXXpQV8_ykufNZoQpSPZrVA67uieOJan-qs8W7rAImyy0552buniHXPWy6ilvdwJKPCdIKE__LghP6A
3) Параметр, указываемый в ссылке (в данном примере это внутренние идентификаторы устройств – hRef):
17272
18199
17242
17245
17248
4) Тело запроса, с ключом и значением:
{«deviceProfileId»:»LORA/GenericA.1.0.3a_ETSI»}
Немного дополняем новый PUT-лист в Excel по сравнению с GET (остальное без изменений):
-
новый столбец B теперь отвечает за ключ deviceProfileId (ячейка B1), а все значения ниже за его возможные значения)
-
столбец D отвечает за формирование итогового тела сообщения в формате JSON.
=СЦЕПИТЬ("'{""";$B$1;""":""";B2;"""";"}'")
Немного поменяем макрос и вынесем его в отдельную подпрограмму:
Код:
Sub PUT_Request()
Dim i As Integer
Dim j As Integer
Dim objHTTP As Object
Dim Json As String
Dim result As String
Dim URL As String
Dim Token As String
a = Timer
i = 1
Do While Not IsEmpty(Cells(i, 1))
i = i + 1
Loop
i = i - 1
'MsgBox i
For j = 2 To i
Json = Range("D" & j)
URL = Range("I" & j)
Token = Range("H1")
Set objHTTP = CreateObject("Msxml2.XMLHTTP.6.0")
objHTTP.Open "PUT", URL, False
objHTTP.setRequestHeader "Content-type", "application/json"
objHTTP.setRequestHeader "Accept", "application/json"
objHTTP.setRequestHeader "Authorization", "Bearer " + Token
objHTTP.Send (Json)
result = objHTTP.responseText
Range("J" & j).Value = result
Set objHTTP = Nothing
'Application.Wait (Now + TimeValue("0:00:01"))
Next j
MsgBox Timer - a
End Sub
Привяжем макрос к кнопке и выполним.
Логика абсолютно аналогична GET запросу.
POST
Для POST запросов все аналогично PUT. Только немного меняется код в части типа запроса. В данном примере на устройство отправляется команда-конфигурация с указанием тела посылки (payload_hex) и порта (fport) для конкретного устройства.
Код:
Sub PUT_Request()
Dim i As Integer
Dim j As Integer
Dim objHTTP As Object
Dim Json As String
Dim result As String
Dim URL As String
Dim Token As String
a = Timer
i = 1
Do While Not IsEmpty(Cells(i, 1))
i = i + 1
Loop
i = i - 1
'MsgBox i
For j = 2 To i
Json = Range("D" & j)
URL = Range("I" & j)
Token = Range("H1")
Set objHTTP = CreateObject("Msxml2.XMLHTTP.6.0")
objHTTP.Open "PUT", URL, False
objHTTP.setRequestHeader "Content-type", "application/json"
objHTTP.setRequestHeader "Accept", "application/json"
objHTTP.setRequestHeader "Authorization", "Bearer " + Token
objHTTP.Send (Json)
result = objHTTP.responseText
Range("J" & j).Value = result
Set objHTTP = Nothing
'Application.Wait (Now + TimeValue("0:00:01"))
Next j
MsgBox Timer - a
End Sub
Получившаяся таблица выглядит следующим образом:
На этом часть для Windows заканчивается. Здесь все оказалось довольно просто: стандартная библиотека, простенький алгоритм перебора значений в цикле.
Часть 2. Реализация решения под MacOS и Excel 64-bit
В виду того, что работал я на двух машинах под управлением разных ОС, хотелось, чтобы решение было универсальным. В итоге, собрав по крупицам информацию по интернет-форумам с данной тематикой у меня вышло следующее решение. Принцип работы его остается схожим, а изменения были внесены в часть, где использовалась стандартная библиотека WindowsMsxml2.XMLHTTP.6.0, которой в MacOS не было по понятным причинам.
Чтобы обойти данное ограничение, был выбран единственный рабочий подход через cUrl, exec и функции. Данное решение точно работает под версией MacOS 10.14 и Excel 16.51. Функция ниже, в том или ином виде, встречается на различных форумах, однако на текущих версиях софта – не работает. В итоге, после небольших правок получили рабочий вариант:
Была отлажена функция вызова ExecShell:
Код:
Option Explicit
Private Declare PtrSafe Function popen Lib "/usr/lib/libc.dylib" (ByVal Command As String, ByVal Mode As String) As LongPtr
Private Declare PtrSafe Function pclose Lib "/usr/lib/libc.dylib" (ByVal file As LongPtr) As Long
Private Declare PtrSafe Function fread Lib "/usr/lib/libc.dylib" (ByVal outStr As String, ByVal size As LongPtr, ByVal items As LongPtr, ByVal stream As LongPtr) As Long
Private Declare PtrSafe Function feof Lib "/usr/lib/libc.dylib" (ByVal file As LongPtr) As LongPtr
Function execShell(Command As String, Optional ByRef exitCode As Long) As String
Dim file As LongPtr
file = popen(Command, "r")
If file = 0 Then
Exit Function
End If
While feof(file) = 0
Dim chunk As String
Dim read As Long
chunk = Space(500)
read = fread(chunk, 1, Len(chunk) - 1, file)
If read > 0 Then
chunk = Left$(chunk, read)
execShell = execShell & chunk
End If
Wend
exitCode = pclose(file)
End Function
И написаны отдельные функции для работы с различным методами GET / PUT / POST, которые на входе принимают URL и параметры):
Код:
Function HTTPGet(sUrl As String, sQuery As String) As String
Dim sCmd As String
Dim sResult As String
Dim lExitCode As Long
sCmd = "curl -X GET " & sQuery & "" & " " & sUrl
sResult = execShell(sCmd, lExitCode)
HTTPGet = sResult
End Function
Function HTTPPost(sUrl As String, sQuery1 As String, sQuery2 As String) As String
Dim sCmd As String
Dim sResult As String
Dim lExitCode As Long
sCmd = "curl -X POST " & sQuery1 & "" & " -d " & sQuery2 & "" & " " & sUrl
sResult = execShell(sCmd, lExitCode)
HTTPPost = sResult
End Function
Function HTTPPut(sUrl As String, sQuery1 As String, sQuery2 As String) As String
Dim sCmd As String
Dim sResult As String
Dim lExitCode As Long
sCmd = "curl -X PUT " & sQuery1 & "" & " -d " & sQuery2 & "" & " " & sUrl
sResult = execShell(sCmd, lExitCode)
HTTPPut = sResult
End Function
Так как мы заменяем библиотеку Msxml2.XMLHTTP.6.0 – поменялась реализация макросов в этой части: мы заменили Msxml2 на написанные выше функции и получили следующее:
Код:
'GET-запросы
Sub SendGETRequest()
Dim i As Integer
Dim j As Integer
Dim result As String
Dim URL As String
Dim Auth As String
a = Timer
'Подсчет заполненных ячеек первого столбца
i = 1
Do While Not IsEmpty(Cells(i, 1))
i = i + 1
Loop
i = i - 1
'Цикл, который отправляет запрос от 2 до последнего элемента
For j = 2 To i
URL = Range("I" & j)
Auth = Range("H" & j)
result = HTTPGet(URL, Auth)
Range("J" & j).Value = result
'Application.Wait (Now + TimeValue("0:00:01"))
Next j
MsgBox Timer - a
End Sub
'PUT-запросы
Sub SendPUTRequest()
Dim i As Integer
Dim j As Integer
Dim result As String
Dim URL As String
Dim Auth As String
Dim Message As String
a = Timer
'Подсчет заполненных ячеек первого столбца
i = 1
Do While Not IsEmpty(Cells(i, 1))
i = i + 1
Loop
i = i - 1
'Цикл, который отправляет запрос от 2 до последнего элемента
For j = 2 To i
Message = Range("D" & j)
URL = Range("I" & j)
Auth = Range("H" & j)
result = HTTPPut(URL, Auth, Message)
Range("J" & j).Value = result
'Application.Wait (Now + TimeValue("0:00:01"))
Next j
MsgBox Timer - a
End Sub
'POST-запросы
Sub SendPOSTRequest()
Dim i As Integer
Dim j As Integer
Dim result As String
Dim URL As String
Dim Auth As String
Dim Message As String
a = Timer
'Подсчет заполненных ячеек первого столбца
i = 1
Do While Not IsEmpty(Cells(i, 1))
i = i + 1
Loop
i = i - 1
'Цикл, который отправляет запрос от 2 до последнего элемента
For j = 2 To i
Message = Range("D" & j)
URL = Range("I" & j)
Auth = Range("H" & j)
result = HTTPPost(URL, Auth, Message)
Range("J" & j).Value = result
'Application.Wait (Now + TimeValue("0:00:01"))
Next j
MsgBox Timer – a
Итог
В итоге, у меня получилось аналогичное windows по работе и функционалу решение для MacOS c использованием Excel 64-bit.
На просторах интернета я не нашел какого-то сборного и единого описания, только фрагменты кода и подходов, которые в большинстве случаев не работали полностью или частично. Поэтому решил объединить все в рабочее решение и выложить на хабр для истории.
На текущий момент я все еще не встретил иного решения, которое бы позволяло в пару кликов копипастить тысячи идентификаторов и параметров из excel и массово их отправлять на сервер. Надеюсь, кому-то пригодится
Если такие сторонние решения есть, а я не в курсе, и все можно было сделать проще, быстрее и изящнее – делитесь опытом в комментариях.
Примечание:
Файл-пример, который можно потыкать, пока жив сервер и «бессрочный» токен:
https://disk.yandex.ru/d/y7EVtn8afM4QPg
Открытое описание API, если кому-то будет любопытно
28 Aug Return Stock Data Using Excel VBA
Posted at 12:35h
in Excel VBA
0 Comments
Howdee! Querying data over the web becomes more common every day. Almost every cloud based program has the ability to serve up its data through some sort of API. Sometimes, the data can be extracted to Excel through some sort of reporting interface within the program. However, I’ve found that this functionality is usually difficult to use and/or incredibly slow or doesn’t exist at all. This is where the ability to make an Excel http get request is so valuable.
In my example today I’ll be building a small excel application that will allow the user to search for a company’s ticker and then return the most recent stock data using an http request. To do this, we will use the site http://dev.markitondemand.com/MODApis/Api/v2/doc. It is a free service that provides the ability to search for tickers and company names and then fetch stock data on that entity.
HTTP Basics
Before diving into the technical aspects of an Excel http get request, let’s first explore what http requests are. HTTP stands for “Hypertext Transfer Protocol”. In laymen’s terms, it is a means of communicating between a host and a client.
Let’s assume you type www.facebook.com into a web browser. You, the client, have just initiated an HTTP GET request to Facebook, the host (for thoroughness, it’s worth mentioning that sites like Facebook that contain sensitive information use an HTTPS request to secure the data being transferred). What you’ve sent is called the “Request” and the HTML page that Facebook sends back is the “Response”.
The request is sent using a URL (Uniform Resource Locator). While you might be familiar with URL’s, you might not be familiar with their structure. They consist of these components:
Protocol is usually HTTP but, as I said earlier, HTTPS is used when the connection needs to be secured (personal data, credit card information, etc.). The host is just that, the domain address a host has chosen for you to reach their server. The port is usually not needed to be explicitly typed. The default port is 80 and the URL implicitly sends that if you exclude it. The resource path and the query are the import parts I want to point out.
The resource path is instructions sent to the host that tell the server where to navigate to so that your information can be found. Lastly, the query section is always kicked off with a question mark. This section provides any parameters you want to include as well the option to explicitly list the precise data you want returned.
This is as dep as I’ll go into HTTP since this is enough to get started querying information. However, if you’re planning to develop an application that will make HTTP calls, I recommend reading up on the subject so you can handle several types of responses. Let’s say a user passes a bad request to the program you build; the host will send back an HTTP response but it could be an error 404 response and not include any data. You’ll need to be able to handle that and other issues that could arise. This article on the Mozilla Developer Network is a great place to start.
Excel HTTP Get Request – Creating the Search
Now that we know a little about HTTP, let’s dive into the Excel http request using VBA. To get started open a new Excel file and press alt + F11 to open the VBA editor window. The first thing we need to do is add some library references so we can access the controls we will need to make HTTP calls. Click on “Tools” and then “References” and add a check box to Microsoft Scripting Runtime, Microsoft Internet Controls, and Microsoft WinHTTP Services, version 5.1 as pictured below.
In this application, we want to allow the user the ability to search for a company’s stock ticker. We will then need to pass that data into our code. When my program needs to interact with data on a spreadsheet, I prefer to name the range or cell that it will be interacting with so that, when I’m writing code, it’s evident exactly what data I’m collecting or where I need to write data to. I’ve named a cell “Search_For_Company” and put instructions on the sheet so the user realizes that he/she needs to enter a search term there.
Now, we need to write the code that will accept this input, and then make an http get request to return potential matches. But, before that, let’s consider the returned results. I user might type in “face” when searching for Facebook. That would return dozens of companies so we need somewhere to store those values temporarily. For this, I’ve created a basic user form with a list box to display the values. It looks like this:
Typically I’ll break my code down in to sections to discuss, but I think this makes sense to look at the code in its entirety and then explain what’s happening step by step.
Sub GetCompanyInformation()
Dim hReq As Object, JSON As Dictionary
Dim i As Long
Dim var As Variant
Dim ws As Worksheet
Set ws = Sheet1
'create our URL string and pass the user entered information to it
Dim strUrl As String
strUrl = "http://dev.markitondemand.com/MODApis/Api/v2/Lookup/json?input=" & ws.[Search_For_Company]
Set hReq = CreateObject("MSXML2.XMLHTTP")
With hReq
.Open "GET", strUrl, False
.Send
End With
'wrap the response in a JSON root tag "data" to count returned objects
Dim response As String
response = "{""data"":" & hReq.ResponseText & "}"
Set JSON = JsonConverter.ParseJson(response)
'set array size to accept all returned objects
ReDim var(JSON("data").Count, 1)
i = 1
'loop through returned data and get Symbol & Name
For Each Item In JSON("data")
var(i, 0) = Item("Symbol")
var(i, 1) = Item("Name")
i = i + 1
Next
ufCompaniesReturned.lbCompaniesReturned.List = var
Erase var
Set var = Nothing
Set hReq = Nothing
Set JSON = Nothing
If ufCompaniesReturned.Visible = False Then
ufCompaniesReturned.Show
End If
End Sub
Let’s skip over the variable declarations as we’ll discuss each as they’re used. The first line simply assigns the “ws” variable to the sheet where I’m working, Sheet1 in this case. Next, I dimension a new string variable (I could have dimensions this variable above with the others but this is just personal preference when I’m creating a variable that represents a URL) and assign the URL I’m using to it. Note here that for the query section of the URL, I’m using a combination of text entered and I’m pulling the value the user typed into the range we named earlier. This is why I like to use that approach in my Excel http get request programs. I can easily see that I’m passing a value from Sheet1 that represents a company to search for.
Next set the Object variable “hReq” equal to a new object in the Microsoft XML Core Services. If you want to read more about what this entails, MSDN has a great write up on it. Suffice it to say this service allows us to send HTTP requests and parse the responses. Now, with that variable we will open a connection and pass it three parameters. We are telling it that we are sending a “GET” request, we pass the URL to use, and lastly, we want to explicitly tell it the call is not asynchronous (also could be said the call is synchronous). This prevents anything further from happening until we get a response from the host. If we left this blank, the default is true. The program could then move on while we are waiting the call and break. There are two more optional parameters in this Open method for username and password, in that order. If that information is required for your request, you’ll need to provide them. They are not required in this example however.
In the next section of code, we create a response variable and store the response from the request as a string. Since this response is returned in JSON, I’m using the VBA-JSON library to parse the JSON. If you’re unfamiliar with this, click here for my blog post on how to use the library. Note that I wrap my response in some additional text. This is a root JSON object that I wrap the data in so I can perform a count on how many objects were returned, which I do in the next step when I’m resizing the array I declared at the beginning of the code.
Lastly we will loop through each object returned by our Excell http get request, and assign the company’s symbol and name to the array. Once the array has been populated, we will pass that array to a listbox, dispose of some resources, and finally check if the form is already visible and, if it isn’t, show it.
Excel HTTP Get Request – Returning the Stock Quote
Now that we’ve successfully written code that will perform our search query, let’s move on to the http get request to return our stock quote. In the form that pops up, our user will select a company for which they want to return a stock quote. Once they click “OK” we will want the result to be returned. To do this, we need to have this process kick off when the event for the button click occurs. To create a sub routine that subscribes to that event, simply double click the “OK” on your user from inside the VBA editor window.
We can certainly embed all the code we want to run inside this event and call it a day. However, I prefer to keep my code separate. I’ve created another module called “Functions” and created a function inside to run my Excel http get request stock quote call when passed the correct parameters. That function looks like this:
Function GetStockData(company As String, companyName As String)
Dim hReq As Object, JSON As Dictionary
Dim sht As Worksheet
Set sht = Sheet1
Dim strUrl As String
strUrl = "http://dev.markitondemand.com/Api/v2/Quote/json?symbol=" & company
Set hReq = CreateObject("MSXML2.XMLHTTP")
With hReq
.Open "GET", strUrl, False
.Send
End With
Dim response As String
response = hReq.ResponseText
Set JSON = JsonConverter.ParseJson(response)
sht.[Last_Price] = JSON("LastPrice")
sht.[Change] = JSON("Change")
sht.[Change_Percent] = JSON("ChangePercent") / 100
sht.[Quote_Time] = JSON("MSDate")
sht.[Market_Cap] = JSON("MarketCap") / 1000000
sht.[Volume] = JSON("Volume")
sht.[Change_YTD] = JSON("ChangeYTD")
sht.[Change_YTD_Percent] = JSON("ChangePercentYTD") / 100
sht.[High] = JSON("High")
sht.[Low] = JSON("Low")
sht.[Open] = JSON("Open")
sht.[Search_For_Company].Value = companyName
End Function
As you can see, this code structure is very like the previous code structure so I won’t go through every detail. The first thing you might notice is that this isn’t a subroutine. I’ve made this a function and given it two parameters to receive. I first pass in the “company” parameter which will represent the stock ticker symbol. This is the parameter I pass to the strUrl variable to complete my Excel http get request string. Next, I pass in the company Name parameter which will be the formal name returned from our previous query.
The next difference you might notice is that I don’t wrap the HTTP response like I did previously. Since I know this response will only return one object, I don’t need to count or loop through the response. I can simply parse that response into a dictionary and then access them through the respective keys. Also, I’ve created several more named ranges to write these values to. Again, this is not necessary but I find it helps tremendously with the readability of my code. Lastly, I just assign the formal name I used in the call back to the cell.
To call this function, I used this code in the button click event handler:
Dim i As Long
For i = 0 To ufCompaniesReturned.lbCompaniesReturned.ListCount - 1
If lbCompaniesReturned.Selected(i) = True Then
Call GetStockData(lbCompaniesReturned.List(i, 0), lbCompaniesReturned.List(i, 1))
Else
'do nothing
End If
Next i
ufCompaniesReturned.Hide
This code is pretty straight forward. I’m first looping through each item in my list box and checking to see if that item has a selected property of true. If it does, I’m passing the two values in the list box to my GetStockData function. From there, the code is handled by the function in my Functions module. All of this together ends up with this result:
I hope this article showed you the power of being able to make http requests from within an Excel application. You can customize the user experience, pull only the data you need, and it’s very fast. As always, the file I worked with today is available for download if you’re a subscriber to my site. It’s free, easy to sign-up, and I won’t be spamming you with dozens of emails each week. If you have questions on anything I went over, please drop them in the comments section below.
Cheers,
R
Hello developers, In this post, we are going to look at How can we send an HTTP POST request to a server from Excel VBA?.
In this article, we will learn to call post API Using Excel VBA code to send a POST and retrieve data from the server .
You can download the HTTP POST request source code at the bottom of the post.
Api end
We are going to cover the below point in this article
- Using Rest API Sending JSON object as a POST request
- Send a POST and retrieve data Using Excel VBA code
Let’s understand step-by-step to Send JSON data in POST request VBA in Excel VBA with help of the rest API.
As we know that Excel doesn’t have a built JSON parser for parsing JSON strings. I’m using VBA-tools JSON parser that helps us to parse the JSON response that we return after making a post request.
with the help of VBA-tools JSON, we can easily parse the object and get a value desire value.
go to the Git link: https://github.com/VBA-tools/VBA-JSON and download the source code.
Extract that folder and Go to File and click on Import file in VBA IDE and select the JsonConverter.bas click on Open.
add reference of Microsoft scripting runtime references
Now all setup done for parsing the api response
VBA POST request with parameters Example -1
And this is a simple registration rest API that accepts email and password as JSON parameters and after SUCCESSFUL call return Userid and token id dummy data of user object.
Api End point: https://reqres.in/api/register
Request
{ "email": "test@gmail.com", "password": "test@123" }
Response(200)
{ "id": 4, "token": "3434Q54454p565655tke4Pnpja7X4" }
Vba code for calling Api
Private Sub CommandButton3_Click() Dim objpostHTTP As Object Dim JsonBody As String Dim Jsonresult As Object JsonBody = "{""email"":""eve.holt@reqres.in"",""password"":""vba1234""}" 'here I am pulling creating json body Dim apiresult As String Set objpostHTTP = CreateObject("MSXML2.ServerXMLHTTP") URL = "https://reqres.in/api/register" objpostHTTP.Open "POST", URL, False objpostHTTP.setRequestHeader "Content-type", "application/json" objpostHTTP.Send (JsonBody) apiresult = objpostHTTP.responseText Set Jsonresult = JsonConverter.ParseJson(apiresult) MsgBox ("User registered with us Id:" & Jsonresult("id") & " TokenId: " & Jsonresult("token")) End Sub
VBA POST request with parameters Example -2
And this is a simple rest API for creating user that accepts “name” and “job” as JSON parameters and after SUCCESSFUL call return user object.
Api End point: https://reqres.in//api/users
Request
{ "name": "Alex bliss", "job": "HR" }
Response(201)
{ "name": "Alex bliss", "job": "HR", "id": "932", "createdAt": "2021-08-26T06:32:37.312Z" }
Vba code for calling Api
Private Sub CommandButton2_Click() Dim objHTTP As Object Dim Json As String Dim Jsonresult As Object Json = "{""name"":""Alex bliss"",""job"":""HR""}" Dim result As String Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP") URL = "https://reqres.in/api/user" objHTTP.Open "POST", URL, False objHTTP.setRequestHeader "Content-type", "application/json" objHTTP.Send (Json) result = objHTTP.responseText Set Jsonresult = JsonConverter.ParseJson(result) MsgBox ("User created with name :" & Jsonresult("name") & " UserId:" & Jsonresult("id")) End Sub
Download Source Code
What is the utilization of Visual Basic?
Visual Basic.NET, and Visual Basic Applications, Although these systems have acquired ubiquity, Visual Basic is still very gainful.
The third era programming language is planned by designers to help them fabricate Windows applications. It works with a climate in which developers can compose code in .exe or executable documents. They can utilize the language to fabricate an in-house front-end framework for getting to huge information bases. Since the language upholds progressing changes, you can keep coding and altering your work as and when required.
Microsoft Visual Basic download has a few impediments. Assuming you need to make programs that require a great deal of handling time, then, at that point the product isn’t appropriate for you.
Why Use Excel VBA?
There are two different ways to make Excel macros. The principal technique is to utilize the large scale recorder. Subsequent to enacting the recorder, Excel will record every one of the means performed by the client and save it as a “cycle” known as a full scale. At the point when the client ends the recorder, this large scale is saved and can be alloted to a catch which when clicked will run a similar interaction once more. This strategy is somewhat straightforward and requires no underlying information on VBA code. This technique will work for basic cycles.
The ruin of this strategy, notwithstanding, is that it isn’t entirely adjustable, and the large scale will duplicate the client’s feedback precisely. Of course, recorder macros additionally utilize outright references rather than relative references. IKt implies that macros made this way are undeniably challenging to use with factors and “keen” methodology.
Dominate VBA empowers you to utilize English like explanations to compose directions for building different applications. This permits you to expand Excel usefulness with the goal that it acts as you need.
What is VBA utilized for?
VBA is utilized for both individual use just as business use. For business use, you can construct vigorous projects and influence the force of Excel in your custom projects utilizing VBA.
Requirements for Learning VBA Excel Tutorial?
Nothing by any means! This Excel VBA preparing regards you as a total fledgling to VBA. In any case, it is alluring on the off chance that you know the fundamentals of Excel and how to perform works in Excel, it will help your learning pace and comprehension.
Spotless and straightforward interface?
After the establishment is finished, you will be in the realistic improvement climate of Visual Basic. It is basic and deliberate, to such an extent that novices, also as specialists, can access and utilize every one of its capacities with no issues. The interface accompanies an advancement bar, catches, names, just as some altering devices that can assist you with changing the programming module consequently.
While creating Windows 10 applications, you can begin utilizing the accessible controls, components, and structures to construct the UI of the application. The Microsoft Visual Basic download, as other programming dialects, upholds the utilization of normal builds. Furthermore, you can utilize those components and develops when composing code to characterize the conduct of your application.
Nonetheless, since the language has an occasion driven climate, you will see a few contrasts in the develops that you use to assemble your application. Likewise, the language gives you admittance to the information base with the assistance of ActiveX information items and controls. Utilizing the data set, you can make different applications including recreation programs, adding machines, straightforward games and substantially more.
What are the fundamental elements of Virtual Basic?
In contrast to other programming dialects, Microsoft Visual Basic gives fast application improvement to application downloads. It is coordinated with string preparing provisions and C++, MFC and F# usefulness. The framework upholds multi-focusing just as the Windows Presentation Framework, so designers can picture different Windows applications, work area instruments, Metro-style projects, and equipment drivers.
Snap to dispatch
Quite possibly the main components of utilizing Visual Basic to foster projects is that it allows you to make executable records consistently. These documents are not difficult to send out and can be utilized to check the advancement of the application and make changes any place fundamental. Moreover, the program trades XAML code for clients, so they can dispatch an application with the snap of a catch right away.
Appreciate various topics?
Albeit the program is restricted to Microsoft working frameworks just, it gives a scope of Windows topics for software engineers to try different things with. You can assemble programming that is in a state of harmony with the working framework on which you need to run the last application. Since the coordinated advancement climate additionally gives you admittance to the information base, you can drag components from that point and drop them into your code.
The post How send an HTTP POST request to a server from Excel using VBA? appeared first on Software Development | Programming Tutorials.
Read More Articles
- How can I send an HTTP POST request to a server from Excel using VBA?
- VBA/Corel Draw: How to send binary and text file in HTTP POST request to server from VBA/VB6 script running from Corel Draw 12/X4?
- How to send a form-data POST request with VBA in Excel using WinHTTPRequest
- Send data in HTTP Post from VBA Excel for Mac
- Sending data from excel to Server using HTTP Post
- Using VBA how do I load an API DataSet into Excel from an HTTP GET function?
- How to send a post request via excel to a RESTful Web Service without using XML?
- How to update Sql server table from excel data using vba code?
- How to export excel spreadsheet data as JSON HTTP Post request using VBScript
- How to get the background color from a Conditional Formatting in Excel using VBA
- How do I issue an HTTP GET from Excel VBA for Mac
- Which references to add in HTTP Request from Excel VBA
- How to fetch data from XML file to Excel sheet using VBA
- HTTPS POST request using VBA for Excel
- How to obtain EXIF info from picture in an excel worksheet using VBA
- Using Excel VBA code to send a POST and retrieve data
- VBA send email from Excel using OFT template — Suppress automatic signatures
- How to release inprocess COM Server object from Excel VBA
- How to set Replacement Text to Bullet Format when creating WordDoc from Excel using VBA
- HTTP Get Request Using VBA in OSX Excel
- Connecting to SQL Server over network using ADO from Excel VBA
- How can I GZip compress a file from Excel VBA using code in an .xla file only?
- How to copy using Multiple filter from user inputbox data in Excel VBA
- Send an email from Excel 2007 VBA using an Outlook Template & Set Variables
- Access + VBA + SQL — How to export multiple queries into one excel Workbook, but, multiple Worksheet using the criteria from a table
- How delete a series from an Excel chart using VBA
- Getting «The server’s host key is not cached in the registry» when using pscp.exe to transfer file from Windows to Unix server in VBA + Excel
- How to retrieve data from access database(.accdb) into excel using vba
- excel vba http request download data from yahoo finance
- Uploading data from Excel 365 to Azure Sql Server using VBA only
- How to pass in a Range parameter for VLookup function?
- Sort Excel Pivot Items based on Date
- VBA WinHttpRequest 5.1 response text not full
- MS Access: referring to a subform textbox control element in VBA query definition
- VBA SAP occasional error Control ID Not Found
- Simple Excel VBA Loop needed
- Opening .xlsx with VBA, File in Use error. Read-only not working
- In Excel Charting, have one series out of four limit the data points
- How to speed up repeated string searching
- Find application directory path in VBA workable for both MS Access and MS Excel
- Using VBA for insert and edit Mathtye equations in MS-Word
- Excel VBA Store/Dim sheet tab color
- Word VBA: How to replace only the next instance of a string via Replacement Object
- VBA Excel 2019: Turn Off Hyperlinks for Workbook for All Users When Opening
- multipage — can’t validate option buttons inside a frame — excel VBA
- VBA Type Mismatch when defining workbook name
- Capture return value from ado recordset
- Finding the week number from a date in Visual Basic
- Connect to MySQL database from VBA without having MySQL installed
- Vba macro to combine some rows’ data in a table
Содержание
- Как Excel и VBA помогают отправлять тысячи HTTP REST API запросов
- Часть 1. Реализация решения под Windows
- Часть 2. Реализация решения под MacOS и Excel 64-bit
- VBA HTTP GET Requests with API and ServerXMLHTTP60
- The VBA Tutorials Blog
- API Basics
- Types of APIs
- Types of API Calls
- Endpoints and Parameters
- Pros and Cons of Using VBA with APIs
- Setting Up
- Determining the Variables
- Initiating the Call
- Authentication
- Using the built-in User and Password Parameters
- Using Request Headers
- Security
- Conclusion
Как Excel и VBA помогают отправлять тысячи HTTP REST API запросов
Работая в IoT-сфере и плотно взаимодействуя с одним из основных элементов данной концепции технологий – сетевым сервером, столкнулся вот с какой проблемой (задачей): необходимо отправлять много запросов для работы с умными устройствами на сетевой сервер. На сервере был реализован REST API с оболочкой Swagger UI, где из графической оболочки можно было отправлять только разовые запросы. Анализ сторонних клиентов, типа Postman или Insomnia показал, что простого визуального способа поместить в скрипт массив из необходимого перечня идентификаторов устройств (или любых других элементов сервера), для обращения к ним – не нашлось.
Так как большая часть работы с выгрузками и данными была в Excel, то решено было вспомнить навыки, полученные на учебе в университете, и написать скрипт на VBA, который бы мою задачку решал.
получать информацию по устройствам с различными параметрами фильтрации (GET);
применять изменения в конфигурации по устройствам: имя, профиль устройства, сетевые лицензии и пр. (PUT);
отправлять данные для конфигурации и взаимодействия с устройствами (POST).
И сегодня я расскажу вам про то, как с помощью Excel, пары формул и самописных функций на VBA можно реализовать алгоритм, отправляющий любое необходимое количество REST-API запросов с использованием авторизации Bearer Token.
Данная статья будет полезная тем, кто воспользуется данным решением под Windows, но еще больше она будет полезна тем людям, которые хотят использовать данное решение на MacOS (с Excel x64). Как вы уже догадались, ниже будут рассмотрены два варианта реализации под разные системы, так как с MacOS есть нюанс.
Часть 1. Реализация решения под Windows
GET
Начнем с самого простого: GET – запросов. В данном примере необходимо получить ответ (информацию) от сервера по заданному списку устройств.
Для реализации GET – запросов нам дано:
1) Ссылка, в которой указываются параметры запроса.
2) Заголовки запроса + Токен авторизации (Bearer Token)
—header ‘Accept: application/json’ —header ‘Authorization: Bearer
3) Параметр, указываемый в ссылке (в данном примере это идентификаторы устройств – DevEUI):
Имея такие данные на входе, делаем в Excel лист-шаблон, который заполняем в соответствии с тем, что имеем:
столбец А уходит вот значения параметров
столбец F уходит под ссылку-родителя
столбец H уходит под заголовки, где в ячейке H1 единоразово для текущего листа указывается токен:
=СЦЕП(«—header ‘Accept: application/json’ —header ‘Authorization: Bearer «;$H$1;»‘»)
столбец I уходит под URL (ссылки-дети, на основе ссылки-родителя)
столбец J уходит под результат (ответ от сервера)
Шаблон листа для GET-запросов
Далее, нам необходимо реализовать подпрограмму(макрос) отправки GET-запросов. Состоит она из четырех частей:
цикла, который считает количество строк для работы по листу, пробегая по столбцу А с 2 по первую пустую ячейку, чтобы у цикла был конец.
функции, для работы с REST API (используется стандартная, библиотека Msxml2.XMLHTTP.6.0, встроенная в Windows., поэтому сложностей с реализацией не возникает. Для MacOS есть альтернатива)
временной задержки, в случае если нужно отправлять запросы не сразу, после получения ответа, а задав время ожидания
таймером, который показывает время выполнения всего макроса после завершения
Привязываем подпрограмму к кнопкам для удобства и выполним скрипт. Получается:
Таким образом, скрипт проходит по столбцу I, забирая из значения каждой ячейки URL, для тех строк, где в столбце А есть значения (которые и подставляются в URL). Для удобства также сделаны кнопки очистки полей и подсветка запросов условным форматированием, в случае успешного ответа на запрос.
PUT
Чуть-чуть усложним задачу и перейдем к PUT-запросам. В данном примере необходимо изменить профиль устройства, чтобы сервер по-другому с ним взаимодействовал.
К исходным данным для GET – запроса добавляется тело запроса с ключем-значением (п4). Итого дано:
1) Ссылка, в которой указываются параметры запроса.
2) Заголовки запроса + Токен авторизации (Bearer Token)
—header ‘Content-Type: application/json’ —header ‘Accept: application/json’ —header ‘Authorization: Bearer
3) Параметр, указываемый в ссылке (в данном примере это внутренние идентификаторы устройств – hRef):
4) Тело запроса, с ключом и значением:
Немного дополняем новый PUT-лист в Excel по сравнению с GET (остальное без изменений):
новый столбец B теперь отвечает за ключ deviceProfileId (ячейка B1), а все значения ниже за его возможные значения)
столбец D отвечает за формирование итогового тела сообщения в формате JSON.
Немного поменяем макрос и вынесем его в отдельную подпрограмму:
Привяжем макрос к кнопке и выполним.
Логика абсолютно аналогична GET запросу.
POST
Для POST запросов все аналогично PUT. Только немного меняется код в части типа запроса. В данном примере на устройство отправляется команда-конфигурация с указанием тела посылки (payload_hex) и порта (fport) для конкретного устройства.
Получившаяся таблица выглядит следующим образом:
На этом часть для Windows заканчивается. Здесь все оказалось довольно просто: стандартная библиотека, простенький алгоритм перебора значений в цикле.
Часть 2. Реализация решения под MacOS и Excel 64-bit
В виду того, что работал я на двух машинах под управлением разных ОС, хотелось, чтобы решение было универсальным. В итоге, собрав по крупицам информацию по интернет-форумам с данной тематикой у меня вышло следующее решение. Принцип работы его остается схожим, а изменения были внесены в часть, где использовалась стандартная библиотека WindowsMsxml2.XMLHTTP.6.0, которой в MacOS не было по понятным причинам.
Чтобы обойти данное ограничение, был выбран единственный рабочий подход через cUrl, exec и функции. Данное решение точно работает под версией MacOS 10.14 и Excel 16.51. Функция ниже, в том или ином виде, встречается на различных форумах, однако на текущих версиях софта – не работает. В итоге, после небольших правок получили рабочий вариант:
Была отлажена функция вызова ExecShell:
И написаны отдельные функции для работы с различным методами GET / PUT / POST, которые на входе принимают URL и параметры):
Так как мы заменяем библиотеку Msxml2.XMLHTTP.6.0 – поменялась реализация макросов в этой части: мы заменили Msxml2 на написанные выше функции и получили следующее:
В итоге, у меня получилось аналогичное windows по работе и функционалу решение для MacOS c использованием Excel 64-bit.
На просторах интернета я не нашел какого-то сборного и единого описания, только фрагменты кода и подходов, которые в большинстве случаев не работали полностью или частично. Поэтому решил объединить все в рабочее решение и выложить на хабр для истории.
На текущий момент я все еще не встретил иного решения, которое бы позволяло в пару кликов копипастить тысячи идентификаторов и параметров из excel и массово их отправлять на сервер. Надеюсь, кому-то пригодится 🙂
Если такие сторонние решения есть, а я не в курсе, и все можно было сделать проще, быстрее и изящнее – делитесь опытом в комментариях.
Файл-пример, который можно потыкать, пока жив сервер и «бессрочный» токен:
Источник
VBA HTTP GET Requests with API and ServerXMLHTTP60
The VBA Tutorials Blog
If you’ve ever wanted to build your own programs — a somewhat high probability if you’re reading this website — you may have wondered how systems talk to each other. It is one thing to build a VBA program to collect data from users in userforms or to automate the manipulation of spreadsheet data, but is it possible to automatically populate your spreadsheets, too?
Of course it is! APIs, or Application Programming Interfaces, are extremely popular and allow one system to talk to another over the internet. If you want to programmatically capture data or even make automated decisions and send the results to another system, you can probably use an API to accomplish that goal. If a relevant API exists, it’s a much more efficient means of collecting data than using VBA to scrape webpages.
Note this tutorial applies many different VBA skills, the explanations of which fall outside the scope of this article. This is one of the most advanced tutorials on this site, and you may need to experiment and fill in some gaps on your own. Don’t let that discourage you, though. APIs are an incredibly powerful tool and the time invested to master them is worth it.
API Basics
APIs are a standard method for your system to talk to another system somewhere on the internet. This is done through HTTP requests, just like a web browser. In fact, many open APIs can be queried directly through a web browser, which can be a useful way to test that you are querying the right URL.
Types of APIs
There are two main types of API: public/open and authenticated. The former can be used by anyone without an account, while the latter requires some kind of account. Accounts may be paid or free, but you need to register in some way. After registering, you can access your API key, which you use for authentication. Free services may still require an account simply as a minimal layer of security, helping them avoid being bombarded with requests during an attack.
Types of API Calls
There are also two common types of API calls or actions: GET and POST. The former is designed to retrieve information, such as the latest stock prices. The latter is designed to make server-side changes or initiate server-side actions, such as entering an order to buy 100 shares of a stock. This post will deal only with GETs, but I will be writing a POST article soon, as they are also very important. (If you sign up for the newsletter, you won’t miss it).
Naturally, POST requests almost always require authentication, since a POST request asks the server to take an action, and the server needs to know to which account that action applies. GET requests can be open or authenticated.
Endpoints and Parameters
Endpoints are the addresses to which one should direct the API call. For example, if this website had an API (it doesn’t), a potential account endpoint might look something like wellsr.com/v1/account and a potential data endpoint for capturing the latest blogs might be wellsr.com/v1/data . A program should direct its call to the appropriate endpoint, and it may add parameters for clarification.
Not all endpoints require parameters, though. An endpoint whose sole function is to return a list of available foreign currencies may not have any parameters at all, while an endpoint designed to return detailed company information will probably require at least a company parameter. Otherwise it might return thousands of companies with hundreds of pieces of information each, unnecessarily burdening the network with extraneous information.
Pros and Cons of Using VBA with APIs
To be blunt, I usually don’t use VBA for most of my API projects. API responses tend to be in JSON format, and there is no built-in JSON library (reference in VBA-speak) for VBA, which means you have to either use a third-party one or build your own parsing function. Microsoft also has a tendency to forget about VBA in documentation, meaning you might have to do some trial-and-error on your own before something works, which can be incredibly frustrating.
Moreover, most API libraries and wrappers are not written in VBA. Wrappers are code that makes using the API easy, written either by third-parties or by the API provider itself. Wrappers will be in Python, C#, or another popular language, but usually not VBA. That means you may have to do a lot of design work on your own just to get functioning requests before you even start to think about how your program will use the data it receives. It also means you will need to understand how the system works on a fundamental level, because you won’t have the crutch of wrappers and libraries to make interaction easier. A lot of people — myself included — choose Python or another popular language for their API needs for these very reasons. Don’t know Python? We have a whole series of Python tutorials to get you started.
Not all is doom and gloom for VBA and APIs, though. Perhaps the predominant reason to use VBA is that the language is native to Excel, and Excel has very powerful visualization and data analysis tools. Its spreadsheet design is familiar to almost every office worker, too, so coworkers or friends can easily use the programs you create. PowerPoint and other Microsoft Office applications use VBA as well, so if the final product will heavily use those applications, VBA might beat out languages like Python, which would require a lot of work to create nice visualizations or GUIs non-tech people can understand.
Setting Up
Alright, let’s get to some actual code. For this section, I am going to use IEX’s open API, which is available from the stem https://api.iextrading.com/1.0/ . IEX provides market data through this service.
Before you can begin anything, we need to reference the VBA library Microsoft XML, v6.0. Without this, you would need to build all the network and operating system backend code to make the requests. Fortunately Microsoft has already done that for us.
Once you add the reference, your skeleton should look something like this:
Side note: You can use MSXML2.XMLHTTP60 instead of the server version, but you may have issues with caching. The Server version will make GET requests over the wire (over the internet) every time, whereas the regular version may only check your local cache and never send data over the wire. That means you may not receive fresh data from the service on every request.
Determining the Variables
Every API has its own documentation, and you will need to read your chosen API’s docs before you can do anything. IEX is relatively straightforward and mostly uses concatenation to build the query URL.
Let’s say you want to receive the last price paid for a set of particular stocks on IEX’s platform. To get such information, look under the IEX Market Data endpoint and the Last header (here). It seems you should hit the /tops/last endpoint. You should specify the symbols you want, too, as parameters.
Let’s start building out the request. Our variables should look like this:
When you build your requests, you’ll need to decide the most efficient method for you, but I like to add forward slashes / directly to the variables so you don’t forget when you’re ready to concatenate them.
Notice the ? before params in the concatenated requestString variable? This is the universal symbol to show the API service that what follows are meant as parameters. If you ever look at the URLs in links, you might see question marks. The web service should interpret whatever follows as parameters.
Initiating the Call
We should now have a string that is equal to
If you type this into a web browser, you should receive a JSON-structured response. Tip: FireFox automatically displays JSON in an easy-to-read format, while many other browsers don’t.
Of course, this is a tutorial for VBA, so how do we send this information via VBA? Add these lines of code to open, send off, and receive the request:
Make powerful macros with our free VBA Developer Kit
It’s easy to copy and paste a macro like this, but it’s harder make one on your own. To help you make macros like this, we built a free VBA Developer Kit and wrote the Big Book of Excel VBA Macros full of hundreds of pre-built macros to help you master file I/O, arrays, strings and more — grab your free copy below.
The ServerXMLHTTP60 object has many parts. The .Open method sets up the essentials. I usually set the Async variable to false to avoid any timeout issues. Submit the connection using .send , and then you can read whatever comes back across the wire by accessing the .ResponseText property. The ResponseText can be a very long string, depending on what you’re querying. For our example here, it is short enough that I’ve reproduced my own result below (yours is almost certain to be different since we are working with live data here). You can check your own result by typing ?request.responseText in the Immediate Window. This is what I received while I was writing the tutorial:
It is always good form to parse up the JSON response with a dedicated function, as JSON is generally set up like a dictionary already. However, in some cases, it might be easier to simply apply some string manipulation functions, which we do later in the tutorial.
Once you open a GET connection, it’s good practice to close it. Although not strictly necessary, use the .abort method to return the request object to an uninitialized state. You might have a for- or while-loop in your program, and you might want to close and open the connections just to keep things stable. Remember to open it again, though, or you’ll catch an error on the second run.
Authentication
So far we’ve only used unauthenticated APIs. Many APIs require authentication, and any API calls that are POSTs will likely require you log in. Otherwise the service won’t know to which account it should apply the request.
If you’ve used early binding and have Intellisense on, you may have noticed the two parameters bstrUser and bstrPassword in your request.Open statement. These are binary string representations of your username and password for the service.
Depending on the API, you might be able to use these variables, or you might need to set request headers. If you’re building a program that interacts with an API, it is very important to read and understand the documentation, because there are different ways of achieving the same result. Reading the documentation is doubly important for VBA programmers, as we suffer from a lack of libraries, documentation, and wrappers.
For the API service you’re using, find a menu item along the lines of Generate API Keys or Authentication. These should help you find your keys, as they’re not always the same as the credentials you would use through the service’s website for normal consumer interaction.
Using the built-in User and Password Parameters
If your API supports it, all you need to do is set the bstrUser and bstrPassword variables in your Open statement. According to the Microsoft documentation, these two parameters are not sent unless the service denies access. If your machine receives an Access Denied response, the .Open method will then send the username and password.
Moreover, if the service requires such logon credentials and these fields are omitted, a native COM popup should appear, asking for logon credentials.
Not all services will accept the user/password combination. Many require request headers be set with the appropriate keys, usually an ID key and a secret key.
The headers are part of the MSXML2.ServerXMLHTTP60 object, so you set them with a method. The first part is the name of the header and the second part is the value of the header.
Let’s say the service has two keys, termed logon-id-key and secret-pass-key . You can create the headers like this:
Here, the headers are sent to the server along with the associated username and password. The server reads the header, understands it’s the ID or the password, and makes sure the value matches its records.
The IEX API is open, so you wouldn’t need to authenticate, and the auth data will just be ignored by the API server. I’m including it to show you how it might look if IEX did require authentication. The final code block, including data extraction, would look something like this:
There are several third-party JSON parsers for VBA designed to convert the ResponseText from your GET command to a VBA Dictionary object. JSON is actually set up as a dictionary, so using the VBA Dictionary object is an efficient way to store its contents. However, these third-party solutions often require importing custom classes, so we’re not going to present them here.
Some people also use MSScriptControl.ScriptControl to process their JSON responses, but in a pinch, you can always extract the data you need using basic string manipulation functions rather than key-item pairs. In the macro above, I used a combination of VBA Split and VBA Mid functions to extract the prices from each stock ticker item in the API response. Here’s the output:
Pay attention to the data type! These are going to be of the String data type, since they’re being extracted from strings and we applied string manipulation functions. To do calculations you’ll want to convert them with a function like CDec or CDbl first.
Security
It is important that your requests are routed through HTTPS. If you route through HTTP, your request headers and any data you send might be sent in unsecured plaintext. If you are only making unauthenticated GET calls, this probably won’t be an issue. However, if you make any calls that require you to log in, or you make POST calls, you don’t want your information flying around cyberspace unencrypted.
Fortunately, using HTTPS in the API URL will probably be sufficient, since connecting to the endpoint will require the connection to be encrypted, anyway.
Please do note that I am not a security professional, and I didn’t write the Microsoft libraries. If you need to be absolutely sure, you can try a little sleuthing via network traffic analysis tools, which can tell you all the data that is coming in and going out. Just be aware that most people’s computers have many background connections constantly shipping data off, so you’ll probably need to turn them off to avoid being inundated with connection information.
Conclusion
APIs are designed to make systems talk to each other. They are a very powerful tool, and they really will take your programs to the next level by incorporating live, remote data. This tutorial looked at VBA GET requests, which only receive information. This can be extremely useful for gathering data, like financial or weather data, and processing it. To start out, you can simply paste your request strings directly into a browser’s URL bar and read the responses directly on the page. It will help you get a feel for writing API request strings and for dealing with the responses.
You may be at a disadvantage using VBA due to a lack of libraries and wrapper support, but it can certainly be rewarding, especially when coupled with the expansive suite of analysis and visualization tools available in Excel.
Finally, APIs sit at the intersection of several skills and topics, including networking, library references, complex objects, authentication, security, and third-party functions. You must also read code from other developers, since this code is embedded in the API’s documentation. You should definitely read the documentation for your particular API before you even start writing your program. So, yes, implementing APIs securely and efficiently can be complex and at times frustrating ( especially in VBA!), but a well-functioning implementation is just as rewarding and fulfilling as it was difficult and frustrating to develop in the first place.
If you’re serious about writing macros, subscribe for more VBA tips. Simply fill out the form below and we’ll share our best time-saving VBA tips.
Ready to do more with VBA?
We put together a giant PDF with over 300 pre-built macros and we want you to have it for free. Enter your email address below and we’ll send you a copy along with our VBA Developer Kit, loaded with VBA tips, tricks and shortcuts.
Before we go, I want to let you know we designed a suite of VBA Cheat Sheets to make it easier for you to write better macros. We included over 200 tips and 140 macro examples so they have everything you need to know to become a better VBA programmer.
This article was written by Cory Sarver, a contributing writer for The VBA Tutorials Blog. Visit him on LinkedIn and his personal page.
Источник
In this post You will learn how to get http request with XmlHttpRequest, get original file name from URL and download it to chosen location.
Case
We got a list of URL links to files in column B. We want to download everything automatically and save files in chosen location with original names from server.
How to do that?
There are several methods to do that (one of them is in previous post). In this article I’ll show You how to deal with our case using XmlHttpRequest.
There are 2 ways:
1. Reference – early binding
First of all You need to choose the reference in Tools/Reference -find Microsoft XML, v6.0 or other version.
And put this in code:
Dim xmlhttp As New MSXML2.XMLHTTP60
Quick note: there would be MSXML2.XMLHTTP for previous versions.
2.Object – late binding
Using this method You don’t have to choose a reference, just declare and create MSXML2.serverXMLHTTP object.
Dim xmlhttp As Object
Set xmlhttp = CreateObject("MSXML2.serverXMLHTTP")
How to get original file name from URL?
After some attempts I “discovered”, that what we need is .getResponseHeader(“Content-Disposition”). It provides original file name.
name0 = xmlhttp.getResponseHeader("Content-Disposition")
Unfortunately it returns us something like this: filename=name of the file with extension. We need to erase filename= phrase.
pos = InStr(1, name0, "=")
name2 = Mid(name0, pos + 1, (Len(name0) - (pos)))
If it returns empty, we will extract file name from URL.
name2 = FileNameFromPath(myURL)
FileNameFromPath is a simple function, which extracts everything after last slash from URL (function included in final code).
How to download file?
To make it nice and easy we will use function URLDownloadToFile from urlmon library.
xstatus = URLDownloadToFile(0, myURL, dlpath & "" & name2, 0, 0)
To make it possible we need to declare this function from library, like shown below. That has to be at the beginning, at the top of our code.
Private Declare PtrSafe Function URLDownloadToFile Lib "urlmon" _
Alias "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, _
ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
This function returns 0, when download is successful and returns 1, when something goes wrong.
Code
There is one more thing which I should mention.
dlpath = .Range("D2").Value
It means location for downloaded files, which is needed for URLDownloadToFile function.
And now, the code.
Option Explicit
Private Declare PtrSafe Function URLDownloadToFile Lib "urlmon" _
Alias "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, _
ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
Sub download_picture()
Dim wk As Workbook
Dim ws1 As Worksheet
Dim xmlhttp As New MSXML2.XMLHTTP60
Dim myURL As String, typ As String, name0 As String, name2 As String
Dim name1 As String, xstate As String, dlpath As String
Dim pos As Integer
Dim xstatus As Long, i As Long, lastRow As Long
Application.ScreenUpdating = False
Set wk = ThisWorkbook
Set ws1 = wk.Sheets(1)
With ws1
dlpath = .Range("D2").Value
lastRow = .Cells(Rows.Count, 2).End(xlUp).Row
For i = 2 To lastRow
myURL = .Range("B" & i).Value
xmlhttp.Open "GET", myURL, False
xmlhttp.send
name0 = xmlhttp.getResponseHeader("Content-Disposition")
If name0 <> "" Then
pos = InStr(1, name0, "=")
name2 = Mid(name0, pos + 1, (Len(name0) - (pos)))
Else
name2 = FileNameFromPath(myURL)
End If
xstatus = URLDownloadToFile(0, myURL, dlpath & "" & name2, 0, 0)
Debug.Print xstatus
Next i
End With
Application.ScreenUpdating = True
End Sub
Function FileNameFromPath(strFullPath As String) As String
FileNameFromPath = Right(strFullPath, Len(strFullPath) - InStrRev(strFullPath, "/"))
End Function
Summary
Now You know how to get http request with XmlHttpRequest, download file and save it with original file name. Remember that HTTP requests can be used to interact with a web service, API or even whole websites. Also keep in mind, that XmlHttpRequest is one from many methods to get http request, which I already mentioned in the article.
I’m very advanced in VBA, Excel, also easily linking VBA with other Office applications (e.g. PowerPoint) and external applications (e.g. SAP). I take part also in RPA processes (WebQuery, DataCache, IBM Access Client Solutions) where I can also use my SQL basic skillset. I’m trying now to widen my knowledge into TypeScript/JavaScript direction.
View all posts by Tomasz Płociński
Excel is probably one of the most used tools in this world, so the demand for integrations with extremely complex spreadsheets is a recurring scenario. APIs allow easy access to information in systems, which is becoming more and more standard in the market, with that in mind, some demands of connecting to systems via API in Excel are necessary and very useful, so I decided to share a little how I created this integration. Let’s learn how to query Rest APIs using VBA and convert the result to JSON for use in the spreadsheet.
This article hopes you will know the basics of Excel and VBA, as well as what is an API and how it works . Our goal will be to consult a Public Pokemon API and list the result in the tab results
.
Creating a blank worksheet
First let’s create a blank sheet with macro enabled, inside it I’ll create a tab called results
.
Creating the macro to query the API
by shortcut alt + f11
let’s open the Excel macro editor, and create a module called list pokemons
.
Importing the VBA-JSON library
As the API we’re going to query returns a JSON as an answer we will need to import the library VBA JSON , it will take care of all the boring work of translating the JSON and returning as an array and object. Installation is very simple, just download the latest version here and in the macro editor go to File > Import File > JsonConverter.bas
.
Enabling Microsoft Scripting Runtime
We also need to enable Microsoft Scripting Runtime, to do this just browse Tools > References
and search and enable in the list the Microsoft Scripting Runtime
.
Creating the VBA macro to query the REST API
Below is the complete code for our request, it might sound scary, but don’t worry, I’ll explain what each part is doing:
Sub listPokemons() Dim json As String Dim jsonObject As Object, item As Object Dim i As Long Dim ws As Worksheet Dim objHTTP As Object 'We selected our results sheet Set ws = Worksheets("results") 'We create our request object and send Set objHTTP = CreateObject("WinHttp.WinHttpRequest.5.1") URL = "https://pokeapi.co/api/v2/pokemon" objHTTP.Open "GET", URL, False objHTTP.Send strResult = objHTTP.responseText json = strResult Set objectJson = JsonConverter.ParseJson(json) 'We create the header cells ws.Cells(1, 1) = "name" ws.Cells(1, 2) = "link" 'We loop the results property of the API response i = 2 'We will start the counter on line 2 For Each pokemon InJsonObject("results") ws.Cells(i, 1) = pokemon("name") ws.Cells(i, 2) = pokemon("url") i = i + 1 next End Sub
First we define all the variables that we will use in our scripts, including the VBA JSON library import that we previously imported into our project.
Dim json As String Dim jsonObject As Object, item As Object Dim i As Long Dim ws As Worksheet Dim xmlhttp As Object Set xmlhttp = CreateObject("MSXML2.serverXMLHTTP") Dim objHTTP As Object
Then we select the spreadsheet we want to display the results of the API query, in our case Worksheets("results")
and then we create an object that will allow us to make the request to the API. https://pokeapi.co/api/v2/pokemon
. We’ll take the answer and put it in the variable json
, for now it is nothing more than a text.
'We selected our results sheet Set ws = Worksheets("results") 'We create our request object and send Set objHTTP = CreateObject("WinHttp.WinHttpRequest.5.1") URL = "https://pokeapi.co/api/v2/pokemon" objHTTP.Open "GET", URL, False objHTTP.Send strResult = objHTTP.responseText json = strResult
Here where the magic happens, the function parsejson
from the VBA JSON library converts the text of our variable json
for an accessible object in our script. We are now able to access all properties programmatically in our code.
Set objectJson = JsonConverter.ParseJson(json)
Now that we have the result of our API accessible, we create in the first row of the spreadsheet the header containing the columns Name and link .
'We create the header cells ws.Cells(1, 1) = "name" ws.Cells(1, 2) = "link"
Now before analyzing the script we need to understand the result of the API. If you open the link https://pokeapi.co/api/v2/pokemon in your browser you will see the following result:
{ "count": 964, "next": "https://pokeapi.co/api/v2/pokemon?offset=20&limit=20", "previous": null, "results": [ { "name": "bulbasaur", "url": "https://pokeapi.co/api/v2/pokemon/1/" }, { "name": "ivysaur", "url": "https://pokeapi.co/api/v2/pokemon/2/" }, { "name": "venusaur", "url": "https://pokeapi.co/api/v2/pokemon/3/" }, { "name": "charmander", "url": "https://pokeapi.co/api/v2/pokemon/4/" }, { "name": "charmeleon", "url": "https://pokeapi.co/api/v2/pokemon/5/" }, { "name": "charizard", "url": "https://pokeapi.co/api/v2/pokemon/6/" }, { "name": "squirtle", "url": "https://pokeapi.co/api/v2/pokemon/7/" }, { "name": "wartortle", "url": "https://pokeapi.co/api/v2/pokemon/8/" }, { "name": "blastoise", "url": "https://pokeapi.co/api/v2/pokemon/9/" }, { "name": "caterpie", "url": "https://pokeapi.co/api/v2/pokemon/10/" }, { "name": "metapod", "url": "https://pokeapi.co/api/v2/pokemon/11/" }, { "name": "butterfree", "url": "https://pokeapi.co/api/v2/pokemon/12/" }, { "name": "weedle", "url": "https://pokeapi.co/api/v2/pokemon/13/" }, { "name": "kakuna", "url": "https://pokeapi.co/api/v2/pokemon/14/" }, { "name": "beedrill", "url": "https://pokeapi.co/api/v2/pokemon/15/" }, { "name": "pidgey", "url": "https://pokeapi.co/api/v2/pokemon/16/" }, { "name": "pidgeotto", "url": "https://pokeapi.co/api/v2/pokemon/17/" }, { "name": "pidgeot", "url": "https://pokeapi.co/api/v2/pokemon/18/" }, { "name": "rattata", "url": "https://pokeapi.co/api/v2/pokemon/19/" }, { "name": "raticate", "url": "https://pokeapi.co/api/v2/pokemon/20/" } ] }
We are interested in the property. results
, an array containing a list of pokemons with their names and links to more details. We will access this matrix at jsonobject("results")
and we will loop to display each pokemon result in a new row of our table.
'We loop the results property of the API response i = 2 'We will start the counter on line 2 For Each pokemon InJsonObject("results") ws.Cells(i, 1) = pokemon("name") ws.Cells(i, 2) = pokemon("url") i = i + 1 next
If everything goes as expected, by pressing f5
to run our macro, in your spreadsheet you should see the following result:
Conclusion
This was a very simple example of a query, with the object of HT TP it is possible to perform all types of requests, GET, POST, UPDATE, … The interesting thing is to understand how the request is made and how you can display the result, thanks to the VBA JSON library, which already drastically reduces the work required. Now you just need to adapt this flow and script to your needs.
3.7
6
votos
Nota do Artigo