Как вывести HTTP GET из Excel VBA для Mac
Мне нужно выдать HTTP Get со строкой запроса в веб-службу из Excel для Mac 2011. Я видел ответы по использованию QueryTables ( Как я могу отправить HTTP-запрос POST на сервер из Excel с помощью VBA?), Но они используйте метод POST, а не метод GET. Я также вижу, что это легко с машины Windows, но я застрял на Mac.
Есть предложения или это безнадежно?
3 ответа
Продолжая исследование, я наткнулся на комментарий Роберта Найта по этому вопросу о функции оболочки VBA в Office 2011 для Mac и построил функцию HTTPGet, используя его функцию execShell для вызова curl. Я проверил это на Mac с Mac OS X 10.8.3 (Mountain Lion) с Excel для Mac 2011. Вот код VBA:
Option Explicit
' execShell() function courtesy of Robert Knight via Stackru
' https://stackru.com/questions/6136798/vba-shell-function-in-office-2011-for-mac
Private Declare Function popen Lib "libc.dylib" (ByVal command As String, ByVal mode As String) As Long
Private Declare Function pclose Lib "libc.dylib" (ByVal file As Long) As Long
Private Declare Function fread Lib "libc.dylib" (ByVal outStr As String, ByVal size As Long, ByVal items As Long, ByVal stream As Long) As Long
Private Declare Function feof Lib "libc.dylib" (ByVal file As Long) As Long
Function execShell(command As String, Optional ByRef exitCode As Long) As String
Dim file As Long
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(50)
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
Function HTTPGet(sUrl As String, sQuery As String) As String
Dim sCmd As String
Dim sResult As String
Dim lExitCode As Long
sCmd = "curl --get -d """ & sQuery & """" & " " & sUrl
sResult = execShell(sCmd, lExitCode)
' ToDo check lExitCode
HTTPGet = sResult
End Function
Чтобы использовать это, скопируйте приведенный выше код, откройте редактор VBA в Excel для Mac 2011. Если у вас нет модуля, нажмите Вставить-> Модуль. Вставьте код в файл модуля. Оставьте редактор VBA (клевер-Q).
Вот конкретный пример использования веб-службы прогноза погоды ( http://openweathermap.org/wiki/API/JSON_API)
Ячейка A1 будет зарезервирована для названия города.
В ячейку A2 введите строку URL: http://api.openweathermap.org/data/2.1/forecast/city
В ячейку A3, которая будет строить строку запроса, введите: ="q=" & A1
В ячейку A4 введите: =HTTPGet(A2, A3)
Теперь введите название города в ячейку A1, например London
ячейка A4 покажет вам ответ JSON, содержащий прогноз погоды для Лондона. Измените значение в A1 с London
в Moscow
- A4 изменится на прогноз в формате JSON для Москвы.
Очевидно, что с помощью VBA вы можете проанализировать и переформатировать данные JSON и поместить их, где это необходимо, в свой рабочий лист.
Никаких претензий к производительности или масштабируемости, но для простого однократного доступа к веб-сервису из Excel для Mac 2011, это, кажется, решает проблему и удовлетворяет потребность, для которой я разместил свой оригинальный вопрос. YMMV!
Приведенный выше ответ Джона Стивенса является фантастическим (пожалуйста, подтвердите его!), Но он больше не работает для меня в более поздней версии Excel:mac 2016, с ошибкой, из-за которой необходимо обновить код для использования в 64-битных системах.
Воспользовавшись некоторыми советами по проблеме, обнаруженной в связанном репозитории, я смог настроить типы данных в сценарии Джона для правильной работы в Excel:mac 2016:
Option Explicit
' execShell() function courtesy of Robert Knight via Stackru
' http://stackru.com/questions/6136798/vba-shell-function-in-office-2011-for-mac
Private Declare PtrSafe Function popen Lib "libc.dylib" (ByVal command As String, ByVal mode As String) As LongPtr
Private Declare PtrSafe Function pclose Lib "libc.dylib" (ByVal file As LongPtr) As Long
Private Declare PtrSafe Function fread 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 "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(50)
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
Function HTTPGet(sUrl As String, sQuery As String) As String
Dim sCmd As String
Dim sResult As String
Dim lExitCode As Long
sCmd = "curl --get -d """ & sQuery & """" & " " & sUrl
sResult = execShell(sCmd, lExitCode)
' ToDo check lExitCode
HTTPGet = sResult
End Function
Другой вариант (обновите соответственно, если ваш curl не находится в / opt / local / bin / curl):
VBA:
Public Function getUrlContents(url) As String
Dim command As String
command = "do shell script ""/path_to/getUrl.sh " + url + """"
getUrlContents = VBA.MacScript(command)
End Function
/path_to/getUrl.sh:
#!/bin/sh
if [ -z "$1" ]
then
echo "missing url argument"
else
/opt/local/bin/curl "$1"
fi
Обратите внимание, что вам нужно убедиться, что getUrl.sh является исполняемым:
chmod u+x getUrl.sh