【问题标题】:How do I issue an HTTP GET from Excel VBA for Mac如何从 Excel VBA for Mac 发出 HTTP GET
【发布时间】:2023-04-02 13:19:01
【问题描述】:

我需要从 Excel for Mac 2011 向 Web 服务发出带有查询字符串的 HTTP Get。我已经看到了使用 QueryTables (How can I send an HTTP POST request to a server from Excel using VBA?) 的答案,但它们使用的是 POST 方法,而不是 GET 方法。我还发现在 Windows 机器上这很容易,但我被困在 Mac 上。

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

【问题讨论】:

    标签: excel vba macos http-get


    【解决方案1】:

    在做进一步的研究时,我发现了 Robert Knight 对这个问题的评论 VBA Shell function in Office 2011 for Mac 并使用他的 execShell 函数构建了一个 HTTPGet 函数来调用 curl。我已经在运行 Mac OS X 10.8.3 (Mountain Lion) 和 Excel for Mac 2011 的 Mac 上对此进行了测试。这是 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    
    

    要使用它,请复制上面的代码,在 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 中的值从 London 更改为 Moscow - A4 将更改为莫斯科的 JSON 格式预测。

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

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

    【讨论】:

    • 我可以在哪里获取文件“libc.dylib”到我的 MacBook?
    • 在我的 macbook 上它在 /usr/lib/libc.dylib 打开一个终端试试 find / -name libc.dylib
    【解决方案2】:

    上面来自 John Stephens 的答案非常棒(请点赞!),但它在最近的 Excel:mac 2016 中不再适用于我,错误是代码需要更新以在 64 位上使用系统。

    an issue I found in a related repository 那里得到一些提示,我能够调整 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
    

    【讨论】:

      【解决方案3】:

      另一个选项(如果您的 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
      

      【讨论】:

        猜你喜欢
        • 2016-03-01
        • 2016-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多