2013-04-12 34 views
11

Tôi cần phát hành HTTP Nhận chuỗi truy vấn đến dịch vụ web từ Excel cho Mac 2011. Tôi đã thấy câu trả lời cho việc sử dụng QueryTables (How can I send an HTTP POST request to a server from Excel using VBA?) nhưng họ sử dụng phương thức POST, không phải phương thức GET. Tôi cũng thấy rằng nó dễ dàng từ một máy Windows, nhưng tôi đang mắc kẹt trên một máy Mac.Làm cách nào để phát hành HTTP GET từ Excel VBA cho Mac 2011

Bất kỳ đề xuất nào hoặc nó vô vọng?

Trả lời

18

Làm nghiên cứu sâu hơn, tôi đã xem xét nhận xét của Robert Knight về câu hỏi này VBA Shell function in Office 2011 for Mac và xây dựng một hàm HTTPGet sử dụng hàm execShell của mình để gọi curl. Tôi đã thử nghiệm điều này trên máy Mac chạy Mac OS X 10.8.3 (Mountain Lion) với Excel cho Mac 2011. Đây là mã 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  

Để sử dụng, sao chép đoạn mã trên, mở VBA trình soạn thảo trong Excel cho Mac 2011. Nếu bạn không có mô-đun, hãy bấm Chèn-> Mô-đun. Dán mã vào tệp mô-đun. Để lại trình soạn thảo VBA (clover-Q).

Dưới đây là một ví dụ cụ thể sử dụng một dịch vụ web dự báo thời tiết (http://openweathermap.org/wiki/API/JSON_API)

Ô A1 sẽ được dành riêng cho các tên của thành phố.

Trong ô A2, nhập vào chuỗi URL: http://api.openweathermap.org/data/2.1/forecast/city

Trong ô A3 đó sẽ xây dựng chuỗi truy vấn, hãy nhập: ="q=" & A1

Trong ô A4, hãy nhập: =HTTPGet(A2, A3)

Bây giờ, gõ một tên thành phố trong ô A1, ví dụ: London, ô A4 sẽ hiển thị cho bạn phản hồi JSON chứa dự báo thời tiết cho Luân Đôn. Thay đổi giá trị trong A1 từ London thành Moscow - A4 sẽ thay đổi thành dự báo được định dạng JSON cho Moscow.

Rõ ràng, sử dụng VBA, bạn có thể phân tích cú pháp và định dạng lại dữ liệu JSON và đặt nó vào vị trí cần thiết trong trang tính của bạn.

Không có xác nhận quyền sở hữu cho hiệu suất hoặc khả năng mở rộng, nhưng đối với quyền truy cập một lần vào dịch vụ web từ Excel cho Mac 2011, điều này dường như thực hiện thủ thuật và đáp ứng nhu cầu mà tôi đã đăng câu hỏi ban đầu của mình. YMMV!

0

Một tùy chọn khác (cập nhật phù hợp nếu curl của bạn không nằm trong/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 

Lưu ý rằng bạn sẽ phải đảm bảo rằng getUrl.sh có thể thực thi:

chmod u+x getUrl.sh 
1

Câu trả lời ở trên từ John Stephens là tuyệt vời (hãy upvote nó!), Nhưng nó không còn làm việc cho tôi trong Excel gần đây hơn: mac 2016, với một lỗi mà mã cần phải được cập nhật để sử dụng trên hệ thống 64-bit .

Lấy một số lời khuyên từ an issue I found in a related repository, tôi đã có thể điều chỉnh các kiểu dữ liệu trong kịch bản của John để làm việc một cách chính xác trong 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