Уровень сложности
Средний
Время на прочтение
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, если кому-то будет любопытно
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
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.
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
This tutorial is for you if you’re an Excel user who would like to learn how to extend your spreadsheets with data from APIs. You might be one of the people who spend most of their workdays in Excel and do calculations and visualizations but still work manually to import or even just copy and paste data from external sources.
If data is available from an API, however, there are various ways in which can consume it directly from Excel, saving you time and preventing errors.
That is, unfortunately, just as long you are using a Windows PC. The integrations presented in this article do not work in Excel for Mac or the web-based version of the Office apps.
BASF provides the Periodic Table of Elements API, which enables you to query the periodic table and retrieve all kinds of information about chemical elements.
We assume you came here from the Introduction to APIs. If not, please check out that document to learn the basics of APIs before continuing.
The Periodic Table of Elements API follows the CRUD/RESTful paradigm but implements only a subset. Specifically, the periodic table is read-only and allows HTTP GET requests exclusively. It is also limited to one resource called «element».
The base URL for the API is https://dev.api.basf.com/chemical/. Every endpoint starts with this URL.
For the elements, there are two endpoints. The first is a collection endpoint that allows you to either retrieve the full periodic table or request a subset of elements through filter parameters. It is called a collection endpoint because it always returns a collection data structure containing multiple items. The second is an individual resource endpoint that allows you to retrieve a single element.
Both endpoints return JSON-formatted responses.
All BASF APIs require authentication. The Periodic Table of Elements API uses an app-only context with an API key. If you haven’t done so, please read the introduction, terminology, and app-only context sections of the Authentication and Authorization guide. You can skip the part on the app and user context and OAuth as it is not required for this API.
To use authentication, you need to create an account and an application. The process gives you a Client ID, which you can then use as your API key. If you do not have an API key, follow the steps outlined in the Get Started guide. Make sure you select the API product BASF Periodic Table while creating your app.
In Excel for Windows, there are three options for getting external data from an API, which we’ll investigate throughout this article.
The first option is the built-in WEBSERVICE() function. Retrieving data from a URL is a single step. However, extracting the information is rather cumbersome as Excel doesn’t understand JSON responses and you have to use string processing functions. Also, as the function only supports the URL as a parameter, this works only with APIs that allow you to provide authentication information as part of the URL. The BASF Periodic Table of Elements API fits the criteria, as it uses a query string for authentication. For other APIs that require custom headers, though, you’re out of luck.
The second option is using VBA, Visual Basic for Applications, to write a Macro in Basic code to consume an API and fill the sheet programmatically. It is the most powerful and flexible option and should work with all kinds of APIs, but it requires you to have some basic programming knowledge.
The third option is the Power Query builder that allows you to gather and combine data from different sources, including APIs. If you have already used the Power Query builder, for example, to access a database directly, this is the sensible way to do it. It’s also a good choice if you do not want to work with code and the WEBSERVICE() option is too limited.
We’ll use an individual resource endpoint with the WEBSERVICE() function as well as the VBA macro, and we’ll demonstrate the collection endpoint with the Power Query builder.
Before we introduce the WEBSERVICE() function, let’s look at functions in Excel in general. They allow you to fill a table cell with computed data. To enter a function into a cell, you start with the equals sign (=), followed by the function name, a left parenthesis [(], your arguments (if needed), and a right parenthesis [)] to end. If there is more than one argument, you separate them with semicolons (;). A common function that you may have used is SUM(), which adds the data from a number of other cells and returns the result. It takes a range of cells as its argument.
The WEBSERVICE() function also takes one argument, a URL. Then, Excel issues an HTTP GET request to fetch whatever is available at that URL, and puts it into the cell as its result. If we want to do an API requests, since the function only allows a single argument, we have to encode the full API request into the URL. As mentioned before, this rules out APIs that require other HTTP methods (such as POST) or custom headers, e.g., for authorization. With the Periodic Table API, however, we put the API key in the URL and only need the GET method.
Open a new Excel workbook, and enter the following line into a cell, replacing the string APIKEY with the previously generated key:
=WEBSERVICE("https://dev.api.basf.com/chemical/elements/He?x-api-key=APIKEY")
Once you hit Enter or click on another cell, you should see a JSON structure describing the Helium element appear in your cell.
As mentioned before, every API endpoint starts with the base URL. For the Periodic Table API, that is https://dev.api.basf.com/chemical/. Then, the path to a resource or collection endpoint follows. In our example, we retrieved a single element, hence, we used a resource endpoint. Typically, the path to a resource starts with the pluralized resource name, followed by a slash (/) and finally an identifier. If you look at the URL above, you can identify elements/He as this path. The question mark (?) separates the parameter section, and you can see the x-api-key parameter that authenticates the request.
We can separate the base URL and the API key from the URL and build the URL dynamically through string concatenation. That is useful if you have multiple requests in the same Excel sheet and, let’s say, you want to share this sheet with another person who then provides a different API key. The other person then only has to enter their API key in one designated cell instead of modifying your API requests.
As next step, we’ll create a sheet that allows users to modify the base URL and API key in one place. We’ll also apply string processing functions to parse a single field from the JSON response. You can follow along these steps. If something is unclear or doesn’t work for you, you can compare your sheet with the screenshots as well as the full Excel workbook that we’ll provide as download further below.
Here we go:
- Type «Base URL» in A1 and the base URL https://dev.api.basf.com/chemical/ in B1.
- Type «API Key» in A2 and paste your API key from the developer portal in B2.
- Type «Element» as a header in A4 and some elements below it. As an example, we’ll put «H» in A5 and «N» in A6.
- Type «API URL» as a header in B4. To build the URL, concatenate the following elements: a reference to the field containing the base URL, «elements/», a reference to the field containing the element name, «?x-api-key=», and a reference to the field containing the API key. You need to use absolute references to base URL and API key and a relative reference to the element name. Your function call should look like this: =CONCAT($B$1;»elements/»;A5;»?x-api-key=»;$B$2)
- Type «API Response» as a header in C4. Make the webservice call using the URL you built in the previous step by typing =WEBSERVICE(B5) in C5. You should see a JSON API response appear in the cell.
- Type «Atomic Mass» as a header in D4. As there is no JSON parser in Excel, we copy a substring from the API response between the atomic_mass field and the subsequent field, covalent_radius. The whole function looks like this: =MID(C5;SEARCH(«atomic_mass»;C5)+13;SEARCH(«covalent_radius»;C5)-SEARCH(«atomic_mass»;C5)-16) You should now see only the atomic mass as a number in the cell.
- Select the cells B5 to D5, grab the right bottom corner, and drag them down to the B6 to D6. You should see the API URL, API response and atomic mass for the second element appear.
- To get the atomic mass for more elements, add a new element symbol in column A and copy or drag down the three other columns.
Please note that Excel function names are localized along with the Excel user interface. If your Excel installation is in German, replace the names based on this list:
- CONCAT – TEXTKETTE
- MID – TEIL
- SEARCH – SUCHEN
You can get a working Excel workbook in the PeriodicTableWebservice.xlsx file (TODO: add download).
Visual Basic for Applications, or VBA for short, is a powerful programming language that you can use to automate Microsoft Office applications, including Excel. VBA is closely related to, but not fully compatible with, other versions of the Basic language (such as Visual Basic .NET).
If you not worked with VBA before but have programming skills in a different language, you have to learn a new syntax, but should be able to understand the structure of the macro we build in this section.
Our goal is to retrieve various attributes of specific chemical elements (but not the entire periodic table). The sheet layout uses one row per element. The user should enter the element names into the first column of the sheet (A). Then, upon running the macro, it should go through the list of rows and fill the other columns with details. For example, the atomic mass in the second column (B) and the covalent radius in the third column (C).
Open Excel with a new, empty sheet. Then, press the combination Alt and F11 on your keyboard to launch the Visual Basic editor.
On the left side of the editor, you can see the project structure. There’s an entry for your sheet. Double-click on this entry to open the code view where you can enter Basic code that is specific to that sheet.
We start by creating two global string variables, one for the base URL and the API key. It helps us separate them from the code itself so we can swap them if necessary.
Dim baseUrl, apiKey As String
It’s not possible to assign a value to these variables yet. We’ll do that later.
As mentioned under the objective above, we need to retrieve specific elements that the user enters into the sheet, not the full periodic table. For this purpose, we use the API endpoint for specific elements and have to make multiple requests. Hence it is useful to develop an abstraction and put the logic for the API request into a function.
In VBA, you can define functions with the Function keyword. They have parameters with types and a return type. Here is the definition of our getElement() function:
Function getElement(id As String) As Object
Next, we create a script control. That is actually a workaround because there is no native JSON parser available and we don’t want to install a third-party module. The script control can execute JScript, which is a version of JavaScript, and thus understand JSON.
Dim scriptControl As Object Set scriptControl = CreateObject("MSScriptControl.ScriptControl") scriptControl.Language = "JScript"
Then, we can make an HTTP request to the API endpoint. VBA makes HTTP requests through the XMLHTTP object. While building the request, we use string concatenation to build the API URL and include the base URL and API key from the variables we defined earlier.
With CreateObject("MSXML2.XMLHTTP") .Open "GET", baseUrl + "elements/" + id + "?x-api-key=" + apiKey, False .send
Once we have a response, we can parse it with the script control and assign the result to the function name, which is VBA’s way of specifying the returned value for a function:
Set getElement = scriptControl.Eval("(" + .responsetext + ")") .abort
After that, all is left is closing the With-block and the function. The VBA editor might have already generated this code for you automatically.
End With End Function
Macros are public VBA subroutines. Let’s call ours getPeriodicElementData():
Public Sub getPeriodicElementData()
Inside the subroutine, we first assign some values to our global variables. Add these lines and replace APIKEY with your API key from the developer portal:
baseUrl = [https://dev.api.basf.com/chemical/](https://dev.api.basf.com/chemical/) apiKey = "APIKEY"
Then, as we want to go through our sheet row by row to get element data, we set up a counter variable:
Dim row As Integer row = 1
Our algorithm goes through all rows until it stops at an empty row. We can achieve this with a Do-Until-loop:
Do Until IsEmpty(Cells(row, 1))
Inside the loop, we call our getElement() function we created in the previous section. By using a With-block, we can access the attributes of the elements directly and write them in the cells. Our sample code reads two attributes, atomic mass and covalent radius, which go in the row of the current element and the second or third column respectively.
With getElement(Cells(row, 1)) Cells(row, 2) = .atomic_mass Cells(row, 3) = .covalent_radius End With
If you want, you can extend this code with more properties from the element object and put them in additional columns. Tip: Use the WEBSERVICE() function to get the full JSON structure so you can see the available properties.
Afterwards, make sure to increase the row variable, otherwise you have an infinite loop:
row = row + 1
Finally, we close the loop and the subroutine. The VBA editor might have already generated this code for you automatically.
Loop End Sub
Before we can run the macro, we should add a couple of element symbols in the first column (A) so that the macro has something to do. As an example, use the elements H, S and O. Use one row for each, so that H is in the first, S in the second and O in the third row.
During development, you can run your macro directly from the VBA editor, using either the play button in the toolbar, the Run menu, or the F5 key on your keyboard.
The macro should run and automatically fill the other columns for your three rows.
To re-run your macro later when you’ve closed the VBA editor, follow these steps:
- Open the View ribbon.
- Click on Macros.
- Select the macro and click Run to execute.
The Power Query builder provides access to a variety of data sources. It even enables the combination of data from multiple sources. In this tutorial, though, we’ll just show you the basics to make an API call and display the results in your Excel sheet. We use the collection endpoint to retrieve the complete periodic table.
To get started, go to the Data ribbon, click the Get Data button, choose From Other Sources, and From Web.
In the popup window, enter the URL for the API. You can configure advanced settings such as HTTP headers for your request, but the BASF Periodic Table API doesn’t need any. You have to provide the full URL to the collection endpoint and add the query parameter for authentication directly into the URL. In the following sample, replace APIKEY with the Client ID of your application
https://dev.api.basf.com/chemical/elements?x-api-key=APIKEY
Once you confirm with OK, the Power Query Builder opens and shows the API response. At first, you just see the container element items. Right-click on it and select Drill Down.
Note the list of applied steps on the right side of the window. It shows you everything you did in the query builder and you can undo any step by clicking the X next to it.
Now you see a list of records and you can click on each to see the different attributes of each element. The next step is converting this list into a table and you do this by clicking the To Table button.
A popup with additional options may appear which you can simply confirm with OK. After that, you see the list as a table but it still has just one column that we need to expand into multiple columns so you can see each attribute of the element in its own column. To do so, click the expand icon (<>) in the column header.
In the popup, select the fields that you like or keep all fields intact. You can uncheck «Use original column name as prefix» as the prefix doesn’t provide any value when you’re just working with one data source.
Once you see the data you want in the query builder, your final step is transferring the table into the Excel sheet. You do this with the Close&Load button.
You’re done! Your excel sheet contains the periodic table of elements now.
Congratulations on making it through the tutorial! We hope it deepened your understanding of APIs and how to consume them with Excel. Feel free to contact developer@basf.com with feedback and questions.