Как вывести 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
Другие вопросы по тегам