如何从Excel VBA for Mac发出HTTP GET

Joh*_*ens 12 excel vba http-get excel-vba excel-vba-mac

我需要从Excel for Mac 2011向Web服务发出带有查询字符串的HTTP Get.我已经看到了使用QueryTables的答案(如何使用VBA从Excel向服务器发送HTTP POST请求?)但是使用POST方法,而不是GET方法.我也看到从Windows机器上很容易,但我被卡在了Mac上.

有什么建议,还是没有希望?

Joh*_*ens 23

进一步研究,我遇到了Robert Knight 在Office 2011 for Mac中VBA Shell函数的这个问题的评论,并使用他的execShell函数构建了一个HTTPGet函数来调用curl.我已经在运行Mac OS X 10.8.3(Mountain Lion)的Mac上使用Excel for Mac 2011测试了这个.这是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    
Run Code Online (Sandbox Code Playgroud)

要使用它,请复制上面的代码,在Excel for Mac 2011中打开VBA编辑器.如果没有模块,请单击插入 - >模块.将代码粘贴到模块文件中.离开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中的值更改LondonMoscow- A4将更改为莫斯科的JSON格式预测.

显然,使用VBA,您可以解析并重新格式化JSON数据,并将其放在工作表中所需的位置.

没有对性能或可扩展性的要求,但是对于从Excel for Mac 2011进行简单的一次性访问Web服务,这似乎可以解决问题并满足我发布原始问题的需要.YMMV!


Sco*_*ley 7

John Stephens的上述答案非常棒(请注意它!),但是在最新的Excel:mac 2016中它不再适用于我,错误是代码需要更新才能在64位系统上使用.

我在相关存储库中找到的问题中获取一些提示,我能够调整John脚本中的数据类型,以便在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
Run Code Online (Sandbox Code Playgroud)