Уровень сложности
Средний
Время на прочтение
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
1. Introduction
This blog post aims to get you started using the Planning Analytics REST API. Excel will be used as the user interface with VBA to drive the queries handle the results.
Excel is not the ideal interface to work with JSON but through the use of 3rd party modules, JSON can be parsed into objects that can be dealt with in Excel VBA.
In this post we look at building processes to retrieve Sessions and associated Threads as well as a request to cancel a Thread.
There are multiple methods of interacting with the REST API:
- A service using MSXML2.XMLHTTP60
- Via Cognos Office Automation Object using the Reporting object
This post will look at using the MSXML2.XMLHTTP60 option where the Planning Analytics for Excel add-in is not required. The main difference that I have noticed when working with Planning Analytics on the Cloud (PAOC) is that you can only access the REST API through the provided automation user (non-interactive account). Using the Reporting object, you can interact with the REST API through the authenticated user.
For my examples, I will be connecting to PAOC through the automation user. You could change the endpoint for your local server e.g. http://tm1server:<HTTPPortNumber>/api/v1/
2. Connection Settings
On our first sheet in the workbook we will create the server access details.
We will make use of the following parameters as a start:
Connection: A name to identify the connection
Server: Endpoint of my server
Database: TM1 database name
Username: The automation user
Password: Password
CAM Namespace: For PAOC this is linked to LDAP
Name your sheet as Config and add each of the parameters to sheet starting in cell B3.
For each parameter, add a named range scoped to the workbook as follows:
pServer, pDatabase, pUsername, pPassword, pCAMNamespace
You should have a sheet that looks something like the below:
On my sheet I have multiple connections and have linked my connection to a list of servers to select and switch as required. You could add this to your solution later to extend it further.
3. Testing the connection
We will need 4 components before we can test the connection;
- Base64Encoder to encode our credentials
- JSON Converter to parse JSON into VBA objects we can deal with
- A function to perform the query and return the parsed JSON object
- A process to test our connection to the server
3.1. Base 64 Encoder
There are various functions available on the web but I used the following:
Option Explicit
Function Base64Encode(text As String) As String
Dim arrData() As Byte
arrData = StrConv(text, vbFromUnicode)
Dim objXML As Variant
Dim objNode As Variant
Set objXML = CreateObject("MSXML2.DOMDocument")
Set objNode = objXML.createElement("b64")
objNode.DataType = "bin.base64"
objNode.nodeTypedValue = arrData
Base64Encode = objNode.text
Set objNode = Nothing
Set objXML = Nothing
End Function
Add a new module to your VBA project and call it modRESTAPI or similar. Paste the above function into the module. I like to add Option Explicit to ensure the variables are correctly defined and we don’t encounter surprises.
3.2. JSON Converter
Download Tim Hall’s module from https://github.com/VBA-tools/VBA-JSON.
Import the module into your VBA project to make it available to our calls.
This makes use of Dictionary data types and requires the Microsoft Scripting Library reference to be selected in Tools, References.
3.3. Function to Query the REST API
Copy the function below and add to your VBA project in the module you previously created.
Function ExecuteQuery(pAction As String, pQueryString As String, Optional strPayload As String) As Object
Dim TM1Service As New MSXML2.XMLHTTP60
Dim pServer As String
Dim pDatabase As String
Dim pUsername As String
Dim pPassword As String
Dim pCAMNamespace As String
Dim sBase64Credentials As String
Dim sQueryString As String
Dim sQueryResult As String
Dim bAsynch As Boolean
Sheets("Config").Calculate
pServer = ThisWorkbook.Names("pServer").RefersToRange
pDatabase = ThisWorkbook.Names("pDatabase").RefersToRange
pUsername = ThisWorkbook.Names("pUsername").RefersToRange
pPassword = ThisWorkbook.Names("pPassword").RefersToRange
pCAMNamespace = ThisWorkbook.Names("pCAMNamespace").RefersToRange
sBase64Credentials = Base64Encode(pUsername & ":" & pPassword & ":" & pCAMNamespace)
With TM1Service
'Query design for PAOC but could add in some code to look for ibmcloud.com and use the below or a local endpoint
sQueryString = pServer & "tm1/api/" & pDatabase & "/api/v1/" + pQueryString
If UCase(pAction) = "POST" Then
bAsynch = True
Else
bAsynch = False
End If
.Open pAction, sQueryString, bAsynch
.setRequestHeader "Content-Type", "application/json"
.setRequestHeader "Accept", "application/json;odata.metadata=none"
.setRequestHeader "TM1-SessionContext", "TM1 REST API tool"
.setRequestHeader "Authorization", "CAMNamespace " & sBase64Credentials
.Send strPayload
While .readyState <> 4
DoEvents
Wend
If .Status >= 400 And .Status <= 599 Then
sQueryResult = CStr(.Status) + " - " + .statusText
If .responseText <> "" Then
sQueryResult = sQueryResult + vbCrLf & .responseText
End If
MsgBox "Error " + sQueryResult, vbCritical, "Connection"
GoTo Cleanup
End If
sQueryResult = .responseText
'This outputs the JSON to the Immediate window.
'You can copy this to a viewer like http://jsonviewer.stack.hu/ to interrogate the JSON
Debug.Print sQueryResult
End With
If sQueryResult <> "" Then
Set ExecuteQuery = JsonConverter.ParseJson(sQueryResult)
Else
Set ExecuteQuery = Nothing
End If
Cleanup:
End Function
Be sure to go to Tools, References and tick Microsoft XML, v6.0 from available references as the TM1Service leverages this.
A walk-through of what the function does:
All the server parameters required are retrieved
Username, password and CAMNamespace are concatenated then Base64 encoded for authentication.
The query string is built based on the parameters passed from the underlying caller process.
Next we need to set the Request Headers for the call we are about to make. This sets the expected content type to JSON and some other settings required.
Note that I am setting odata.metadata=none as I do not need any additional information like the odata.etags. This could also be set to minimal to or removed depending on what you would like to see returned.
I have also set TM1-SessionContext so that I can easily see which are calls from my testing versus other sessions.
We then send the request and get a response. If the response is not ready, we do events then check again.
Our response is then checked to see if we have success or errors. See https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html for more on return codes.
Assuming we have a success code and some JSON returned from the query, we parse the JSON using the JSONConverter and return the result back to the calling process.
If an error was encountered, we show the error and associated text to assist in troubleshooting.
3.4. Test Function
Our test function is simply going to request the server information and return it to a message box if successfully connected.
Sub GetServer()
Dim oJSON As Variant
Dim oKey As Variant
Dim pQueryString As String
Dim sResult As String
pQueryString = "Server"
Set oJSON = ExecuteQuery("Get", pQueryString)
sResult = ""
If Not oJSON Is Nothing Then
For Each oKey In oJSON
sResult = sResult & oKey & " - " & oJSON(oKey) & vbCrLf
Next
MsgBox sResult, vbInformation, "Server Details"
End If
End Sub
You should be able to run the code to test it or step through it line by line to check what each step is doing.
The JSON returned is returned to an object which in this case is a dictionary object i.e. key and value pairs.
The code loops through each key and returns the associated value to a string then pops the result up in a message box.
Now that the connection has been successfully tested we can move on to retrieving Sessions and Threads.
4. Retrieving Sessions and Threads
We want to retrieve both Sessions and Threads in one query. Threads are linked to a Session which means that we can expand Sessions to include the Threads using a query like:
Sessions?$expand=Threads
A session in the resultant JSON should look something like the below:
{
"ID": 5707,
"Context": "",
"Active": true,
"Threads": [
{
"ID": 13016,
"Type": "User",
"Name": "LDAP/xxx_tm1_automation ccc_user CAMID("LDAP:u:uid=xxx_tm1_automation,ou=people")",
"Context": "",
"State": "Run",
"Function": "GET /api/v1/Sessions",
"ObjectType": "",
"ObjectName": "",
"RLocks": 2841,
"IXLocks": 0,
"WLocks": 0,
"ElapsedTime": "P0DT00H00M00S",
"WaitTime": "P0DT00H00M00S",
"Info": ""
}
]
},...
Threads could contain multiple records for the same Session e.g. where multi-threading is occurring. Note that Threads has square then each Thread has braces. The square brackets are seen as an array whereas the braces are interpreted as a dictionary.
Add a new sheet to the Excel book to return the Session and Threads results.
In my sheet I have a header row on row 7 and return the results to row 8 onwards. Above row 7 I have some space to add command buttons.
Cell A7 contains ID, B7, Context then Active, Thread ID etc. per above JSON.
For Cell A8 I added a named range, scoped to the sheet, called Sessions and added in the text «Start». This indicates the start of my result range but importantly also updates the last cell used for the clear function.
I also added a button to call my macro to make running the process easier.
Add the below code to your module. This will execute the query and return the results to the sheet.
Sub GetActiveSessions()
Dim oJSON As Variant
Dim oSession As Variant
Dim oThreads As Variant
Dim oThread As Variant
Dim oThreadDetail As Variant
Dim pQueryString As String
Dim sResult As String
Dim iRow As Integer
Dim iCol As Integer
Dim sResultRange As String
Application.EnableEvents = False
Application.ScreenUpdating = False
'Clear old rows
sResultRange = "Sessions"
Range(Range(sResultRange), Range(sResultRange).SpecialCells(xlLastCell)).EntireRow.Clear
pQueryString = "Sessions?$expand=Threads"
Range("qryREST").Value2 = pQueryString
Set oJSON = ExecuteQuery("Get", pQueryString)
sResult = ""
If Not oJSON Is Nothing Then
iRow = 0
For Each oSession In oJSON("value")
iCol = 0
For Each oThreads In oSession
If oThreads <> "Threads" Then
Range(sResultRange).Offset(iRow, iCol).Value2 = oSession(oThreads)
iCol = iCol + 1
Else
'Threads - defined as oJSON("value")(<item>)("Threads")(<threaditem>)("ID")
If oSession("Threads").Count > 0 Then
For Each oThread In oSession("Threads")
iCol = 3
For Each oThreadDetail In oThread
Range(sResultRange).Offset(iRow, iCol).Value2 = oThread(oThreadDetail)
iCol = iCol + 1
Next
If oThread("ID") <> oSession("Threads")(oSession("Threads").Count)("ID") Then
iRow = iRow + 1
End If
Next
End If
End If
Next
iRow = iRow + 1
Next
End If
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
With the above code, it may be useful to add some watches to better understand what each object contains.
Per the JSON snippet above, there are Session related properties and then a container of zero of more Threads.
My Sessions sheet looks like the below snippet after running the macro:
You can see the Session detail with the Thread detail alongside. Where there are multiple Threads, these would be iterated starting in column D of subsequent rows.
5. Cancelling a Thread
Essentially, we want to select a Thread ID and pass this to a REST API action which will request the cancellation.
Add the following code to your module:
Sub ThreadCancel()
Dim oJSON As Variant
Dim pQueryString As String
Dim sThread As String
'Thread ID is in column D
sThread = ActiveCell.EntireRow.Columns(4).Value2
If sThread = "" Then GoTo Cleanup:
pQueryString = "Threads('" & sThread & "')/tm1.CancelOperation"
Set oJSON = ExecuteQuery("Post", pQueryString)
Cleanup:
End Sub
The process will read the Thread ID from column D for the row of the ActiveCell. This value is then sent to the CancelOperation.
You can add another button to your sheet to cancel the Thread by assigning the ThreadCancel process to it.
To test this function, you will need to run a process from PAW or possibly create a simple process with a Sleep function to keep the process running for a few seconds.
The screenshot below shows the Session and the active Threads along with the process being run.
To cancel the Thread, select a cell in the relevant row then click the Cancel Thread button or run your process.
PAW should then show you a message box that the process has been cancelled (may not show to non-admin users):
6. Summary
You now have a way to check active Sessions and Threads running on a specified server.
You also have a way to cancel a Thread should there be an issue with a process.
You could extend this example by adding to your configuration sheet, catering to multiple connections. You could also change your Cancel Thread process to cater for multiple selected Threads.
These examples have laid the foundation for many more REST API query projects and will allow you to easily extend to querying cubes, dimensions, subsets etc.
Please leave a comment if you found this useful or have something else to say. Let me know too of any errors so that I can address them.
#PlanningAnalyticswithWatson
Hello everyone. In this post, we are going to look at how to make a rest API call from VBA. That is what we are going to learn in this post. And this is a sample API which going to return this dummy data user object. You can download the source code at the bottom of the post.
We are going to cover the below point in this article
- Getting a JSON response from a REST API with VBA excel
- How do JSON POST requests in Excel VBA
- Parse API response data in VBA
And this is the URL: https://reqres.in/api/users/2
{ "data": { "id": 2, "email": "janet.weaver@reqres.in", "first_name": "Janet", "last_name": "Weaver", "avatar": "https://reqres.in/img/faces/2-image.jpg" }, "support": { "url": "https://reqres.in/#support-heading", "text": "" } }
if you make an API call with this get request, you will get on the dummy data user ID, email,first_name,last_name, image, etc.
How to call rest api from excel vba and parse json response return by rest Api
And this is what we are going to use that in our script. Excel doesn’t have a built JSON parser. So we are going to use VBA-tools JSON parser which helps us to parse the JSON that we receive after making a get request.
And we have to pass this JSON object as a parameter to this VBA JSON or method so that we can easily parse the object and get a value that we are looking for.
So go to the Git link : https://github.com/VBA-tools/VBA-JSON
So just click on the download code and it will be downloaded in the zip format.
And now go to your Excel sheet. I have already created a blank Excel format. so go to the developer tool and visual basic.
So now you can see the visual basic IDE and go to insert, and insert a form and add two button control on it.
So before writing a script, we need to do some import.
The first thing is we need to import the JSON converter that we download from Github. Go to File and click on Import file. So I have already exported the zip
so this is the folder that I extracted go inside this folder and select the JsonConverter.bas And click on Open.
You can see a new module here, so it imported all the scripts which are present on the Bas file.
So now go back to the Form and click on Tools and select references. And now we are going to deal with a dictionary.
So enable the Microsoft scripting runtime references that you can find it in the list scroll down. So here you can see Microsoft Scripting runtime, select and click on OK.
So let write API calling code on button click of each button i.e GetUser and CreateUser and write code for calling the rest api.
Using Excel and VBA to get rest API data
Click on GetUser and wrute below code
so let me create a variable called objRequest and the data type is the object and we need to store the endpoint URL in a string. So let me create a variable called strUrl .
Private Sub CommandButton1_Click() Dim JsonObject As Object Dim objRequest As Object Dim strUrl As String Dim blnAsync As Boolean Dim strResponse As String Set objRequest = CreateObject("MSXML2.XMLHTTP") strUrl = "https://reqres.in/api/users/2" blnAsync = True With objRequest .Open "GET", strUrl, blnAsync .setRequestHeader "Content-Type", "application/json" .setRequestHeader "Authorization", "Bearer " & token .Send 'spin wheels whilst waiting for response While objRequest.readyState <> 4 DoEvents Wend strResponse = .responseText End With Set JsonObject = JsonConverter.ParseJson(strResponse) MsgBox (JsonObject("data")("email")) End Sub
It should be the string format and we are going to make the request using XMLHttpRequest and where to make a request, blnAsync as you need to pass a boolean value true or also whether you are making a sync operation or not.
And finally, after we get the response, we are going to pass it and store it in a variable. name this variable as JsonObject and data type is an object so that’s it. We have created all the variables that we need to make the HTTP call.
and then filanly we are Parsing String Response From API inVBA. So let’s show this response to a message box and see whether it actually makes an API call or makes sure that we are getting the response or not. we are extracting the “email” from the api response, showing it in a message box.
Now let’s click on “Getuser” button, So we got the response and it successfully makes a get request.
Excel VBA HTTP post request json
Private Sub CommandButton2_Click() Dim objHTTP As Object Dim Json As String Dim Jsonresult As Object Json = "{""name"":""Mark Henry"",""job"":""Project Manager""}" 'here I am pulling creating json body 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")) End Sub
we have set the request header using ssetRequestHeader and you have to specify the key-value, Content-type, and application/json. And so we have to specify that as an argument here, application/json. we are going to get the response in the form of JSON our next line.
Download Source Code
The post [Solved]-How to call rest api from Excel macros vba and Parse Json appeared first on Software Development | Programming Tutorials.
Read More Articles
- How can I retrieve JSON from an HTTP endpoint, from within Excel on MacOS, and parse it?
- How to read from a text (.txt) file and place data into an excel 2016 document using VBA Macros editor?
- How to fix and extract google CSE JSON API results with excel vba
- How can I read a HTTP-header while making an API call from Excel VBA using JSON?
- How to call a C# function from VBA and Excel
- How to copy «specific» rows from one sheet and paste in to another in an excel using VBA Macros
- How to Call VBA Function from Excel Cells?
- How do I call VBA code in an Excel spreadsheet from Java?
- How to call Excel VBA functions and subs using Python win32com?
- How to find and call javascript method from vba
- How do I call an Oracle stored procedure from an Excel VBA script?
- How to load vba macros to the excel file from a text file by a C# code?
- How to call an Excel VBA Macro from Java Code?
- Excel VBA — call same macro from both Ribbon and AutoOpen
- Passing a LPCTSTR parameter to an API call from VBA in a PTRSAFE and UNICODE safe manner
- How to call VBA function from excel
- How to instantiate a vba class and call a method from vb.net?
- How to make VBA count from 0 and not 1 in Excel Macro
- VBA — How to download .xls from website and put data into excel file
- How to call Word macros from Excel
- How to delete a column of a table and shift the rest to the left without affecting the previous tables in excel vba
- Excel VBA — How to get data from multiple-array JSON into columns
- How to copy column data from one sheet and then copy that to another sheet in vba excel
- Using VBA and VBA-JSON to access JSON data from WordPress API
- How can I extract a specific Letter(s) and numbers from a text string via VBA Or excel Formula
- how to get path input from textbox and use in command button in vba macros
- How to retrieve data from other Excel using VBA and SQL?
- Excel VBA macro using iTunes search API — fastest way to query & parse JSON results
- In VBA how do I write a script to copy a button from one worksheet to a worksheet in a different note book(without recording macros and using .select)
- How to set a variable equal to a json value from another variable excel vba
- Append data to beginning of CSV file
- before save validation on vba
- VBA Split String Loop
- Copying to a Macro if there is a «-» in a certain cell (VBA)
- Get list of all user with attributes from AD with VBA
- Validation List automatically convert string as date in VBA
- Programmatically add sound effects to the soundeffect library in a PowerPoint presentation
- Debug is finding an error 91 with an intersect(target, [range variable]).value
- Copy specific lines from text files into excel
- Access Continuous form based on recordest made with VBA (fill the form fields)
- Is there a way to store all Excel VBA Google searches in a separate sheet in the Excel file?
- VBA Loop search by text,offset then incremnt
- Extracting data from a dynamic userform VBA
- Add a commandbutton with a macro assigned
- VBA macro multiplying column with outside cell, if certain criteria is met
- How to make a VBA script (that runs on Command Button Click) reflect data that has changed after I saved the script?
- Find range between two words and iterate through it with loop
- Excel VBA to replace column values with another value?
- Finding the n-th cell in a column with a given property
- Controlling Encrypt and Digitally Sign buttons in Outlook 2007 or later
Содержание
- How to use Excel VBA to query REST JSON APIs
- Creating a blank worksheet
- Creating the macro to query the API
- Importing the VBA-JSON library
- Enabling Microsoft Scripting Runtime
- Creating the VBA macro to query the REST API
- Conclusion
- rpharrison/Excel-REST
- Sign In Required
- Launching GitHub Desktop
- Launching GitHub Desktop
- Launching Xcode
- Launching Visual Studio Code
- Latest commit
- Git stats
- Files
- README.md
- Как Excel и VBA помогают отправлять тысячи HTTP REST API запросов
- Часть 1. Реализация решения под Windows
- Часть 2. Реализация решения под MacOS и Excel 64-bit
How to use Excel VBA to query REST JSON APIs
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:
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.
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.
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.
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 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.
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.
Источник
rpharrison/Excel-REST
Use Git or checkout with SVN using the web URL.
Work fast with our official CLI. Learn more.
Sign In Required
Please sign in to use Codespaces.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching Xcode
If nothing happens, download Xcode and try again.
Launching Visual Studio Code
Your codespace will open once ready.
There was a problem preparing your codespace, please try again.
Latest commit
Git stats
Files
Failed to load latest commit information.
README.md
VBA-Web (formerly Excel-REST) makes working with complex webservices and APIs easy with VBA on Windows and Mac. It includes support for authentication, automatically converting and parsing JSON, working with cookies and headers, and much more.
- Download the latest release (v4.1.6)
- To install/upgrade in an existing file, use VBA-Web — Installer.xlsm
- To start from scratch in Excel, VBA-Web — Blank.xlsm has everything setup and ready to go
For more details see the Wiki
To upgrade from Excel-REST to VBA-Web, follow the Upgrading Guide
Note: XML support has been temporarily removed from VBA-Web while parser issues for Mac are resolved. XML support is still possible on Windows, follow these instructions to use a custom formatter.
- Authentication support is built-in, with suppory for HTTP Basic, OAuth 1.0, OAuth 2.0, Windows, Digest, Google, and more. See Authentication for more information
- For proxy environments, Client.EnabledAutoProxy = True will automatically load proxy settings
- Support for custom request and response formats. See RegisterConverter
The following examples demonstrate using the Google Maps API to get directions between two locations.
There are 3 primary components in VBA-Web:
- WebRequest for defining complex requests
- WebClient for executing requests
- WebResponse for dealing with responses.
In the above example, the request is fairly simple, so we can skip creating a WebRequest and instead use the Client.GetJSON helper to GET json from a specific url. In processing the response, we can look at the StatusCode to make sure the request succeeded and then use the parsed json in the Data parameter to extract complex information from the response.
If you wish to have more control over the request, the following example uses WebRequest to define a complex request.
The above example demonstrates some of the powerful feature available with WebRequest . Some of the features include:
- Url segments (Replace in resource with value)
- Method (GET, POST, PUT, PATCH, DELETE)
- Format (json, xml, url-encoded, plain-text) for content-type and accept headers and converting/parsing request and response
- QuerystringParams
- Body
- Cookies
- Headers
For more details, see the WebRequest portion of the Docs
The following example demonstrates using an authenticator with VBA-Web to query Twitter. The TwitterAuthenticator (found in the authenticators/ folder) uses Twitter’s OAuth 1.0a authentication and details of how it was created can be found in the Wiki.
For more details, check out the Wiki, Docs, and Examples
Источник
Как 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 и массово их отправлять на сервер. Надеюсь, кому-то пригодится 🙂
Если такие сторонние решения есть, а я не в курсе, и все можно было сделать проще, быстрее и изящнее – делитесь опытом в комментариях.
Файл-пример, который можно потыкать, пока жив сервер и «бессрочный» токен:
Источник