Подтвердить что ты не робот

Как я могу получить HTTP GET из Excel VBA для Mac 2011

Мне нужно выдать HTTP Get с строкой запроса в веб-службу из Excel для Mac 2011. Я видел ответы на использование QueryTables (Как отправить HTTP-сообщение POST-запрос на сервер из Excel с использованием VBA?), но они используют метод POST, а не метод GET. Я также вижу, что это легко с Windows-машины, но я застрял на Mac.

Любые предложения, или это безнадежно?

4b9b3361

Ответ 1

Проведя дальнейшие исследования, я наткнулся на комментарий Роберта Найт на этот вопрос функцию VBA Shell в Office 2011 для Mac и создал функцию HTTPGet, используя его функцию execShell, чтобы вызвать завиток, Я протестировал это на Mac с Mac OS X 10.8.3 (Mountain Lion) с Excel для Mac 2011. Вот код VBA:

Option Explicit

' execShell() function courtesy of Robert Knight via StackOverflow
' /questions/359854/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 (clover-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!

Ответ 2

Ответ выше от Джона Стивенса фантастичен (пожалуйста, повысьте его!), но он больше не работал у меня в более позднем Excel: mac 2016 с ошибкой, что код необходимо обновить для использования на 64-битной системы.

Взяв несколько советов проблему, которую я нашел в соответствующем репозитории, мне удалось настроить типы данных в John script для работы правильно в Excel: mac 2016:

Option Explicit

' execShell() function courtesy of Robert Knight via StackOverflow
' http://stackoverflow.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

Ответ 3

Другой вариант (обновите, если ваш завиток не находится в /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