2013-04-12 12 views
11

Muszę wysłać komunikat HTTP Pobierz za pomocą ciągu zapytania do usługi WWW z programu Excel 2011 dla komputerów Mac. Widziałem odpowiedzi na używanie QueryTables (How can I send an HTTP POST request to a server from Excel using VBA?), ale używają metody POST, a nie metody GET. Widzę też, że jest to łatwe z komputera z Windows, ale utknąłem na komputerze Mac.Jak wysłać komunikat HTTP GET z programu Excel VBA dla komputerów Mac 2011

Jakieś sugestie, czy jest to beznadziejne?

Odpowiedz

18

Przeprowadzając dalsze badania, natknąłem się na komentarz Roberta Knighta na temat tego pytania VBA Shell function in Office 2011 for Mac i zbudowałem funkcję HTTPGet, używając jego funkcji execShell do wywoływania zwijania. Przetestowałem to na komputerze Mac z systemem Mac OS X 10.8.3 (Mountain Lion) w programie Excel 2011 dla komputerów Mac Oto kod VBA:

Option Explicit 

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

Aby to wykorzystać, skopiuj powyższy kod, otworzyć VBA edytor w programie Excel 2011 dla komputerów Mac. Jeśli nie masz modułu, kliknij opcję Wstaw-> Moduł. Wklej kod do pliku modułu. Pozostaw edytor VBA (koniczyna-Q).

Oto konkretny przykład za pomocą usługi internetowej prognozy pogody (http://openweathermap.org/wiki/API/JSON_API)

Komórka A1 zostanie zarezerwowane dla nazwy miasta.

W komórce A2, wprowadź ciąg URL: http://api.openweathermap.org/data/2.1/forecast/city

W A3 komórek, które będą budować ciąg kwerendy wpisz: ="q=" & A1

W komórce A4 wpisz: =HTTPGet(A2, A3)

Teraz wpisz nazwa miasta w komórce A1, na przykład London, komórka A4 pokaże odpowiedź JSON zawierającą prognozę pogody dla Londynu. Zmień wartość w A1 z London na Moscow - A4 zmieni się na prognozę sformatowaną w JSON dla Moskwy.

Oczywiście przy użyciu VBA można przeanalizować i ponownie sformatować dane JSON i umieścić je w razie potrzeby w arkuszu roboczym.

Brak roszczeń dotyczących wydajności lub skalowalności, ale w przypadku prostego jednorazowego dostępu do usługi sieciowej z programu Excel 2011 dla komputerów Mac, wydaje się, że to wystarczy i spełniono potrzebę, dla której opublikowałem moje oryginalne pytanie. YMMV!

0

Inną opcją (odpowiednio zaktualizować jeśli curl nie znajduje się w katalogu/opt/local/bin/zwinięcie):

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 

należy pamiętać, że trzeba będzie zapewnić getUrl.sh jest wykonywalny:

chmod u+x getUrl.sh 
1

Powyższa odpowiedź od Johna Stephensa jest fantastyczna (prosimy o upvote it!), Ale nie działała już dla mnie w nowszym Excel: mac 2016, z błędem, że kod musi zostać zaktualizowany do użytku w systemach 64-bitowych .

Biorąc kilka wskazówek od an issue I found in a related repository, byłem w stanie dostosować typy danych w skrypcie Jana pracować poprawnie w programie 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 
Powiązane problemy