【问题标题】:HTTP Get Request Using VBA in OSX Excel在 OSX Excel 中使用 VBA 获取 HTTP 请求
【发布时间】:2016-07-05 19:23:39
【问题描述】:

我正在编写一个非常简单的宏,它需要向服务器发出 HTTP GET 请求并且响应并不重要(它会在服务器上启动一个进程)。 HTTP GET 不需要身份验证。

我正在使用以下代码“成功”地执行此操作(服务器日志表明请求已发送到服务器,但服务器正在运行 HTTP 406):

Function callAPI(Url As String)
    With ActiveSheet.QueryTables.Add(Connection:="URL;" & Url, Destination:=Range("D15"))
    .PostText = ""
    .RefreshStyle = xlOverwriteCells
    .SaveData = True
    .Refresh
    End With
End Function

但我从服务器收到以下响应:

Unable to open http://someurl.com Cannot locate the Internet server or proxy server.

我可以看到服务器返回一个 HTTP 406,经过一些研究,因为 GET 请求没有发送正确的 Content-Type 标头。

所以我的问题是 - 如何告诉 ActiveSheet.QueryTables.Add 设置标头,或者如何修改我的 NGINX 配置以支持这个特定的 GET CALL

【问题讨论】:

  • 也许检查一下这个stackoverflow.com/questions/15981960/…,它基本上是说使用cURL而不是使用QueryTables方法作为一种HTTP GET方式。您将能够通过这种方式设置请求标头。

标签: macos vba excel nginx


【解决方案1】:

这是一段同时支持 OSX 和 Windows 的代码。我会感谢作者,因为我当然不是从头开始写的,但我已经忘记了它的来源:

#If Win32 Then

Function getHTTP(URL As String, sQuery As String) As String
    Dim strResult As String
    Dim objHTTP As Object
    Set objHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
    objHTTP.Open "GET", URL & "?" & sQuery, False
    objHTTP.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
    objHTTP.send("")
    strResult = objHTTP.responseText
    getHTTP = strResult
End Function


#Else


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 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 getHTTP(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
    getHTTP = sResult
End Function

#End If

【讨论】:

  • 看起来不错。但在 Mac Excel 15 上对我不起作用。“Private Declare Function popen”这些行是红色的?!
  • 是的,最新版本的 excel 打破了这个问题,我还没有找到解决办法。
  • 使用 Private Declare PtrSafe 函数...应该可以了!
【解决方案2】:

这对我在 Mac Excel 15.4 上也不起作用。我在 VBA-Tools Github 上找到了一个有用的版本:

https://github.com/VBA-tools/VBA-Web/issues/248

这是对我有用的版本:

Private Declare PtrSafe Function web_popen Lib "libc.dylib" Alias "popen" (ByVal command As String, ByVal mode As String) As LongPtr
Private Declare PtrSafe Function web_pclose Lib "libc.dylib" Alias "pclose" (ByVal file As LongPtr) As Long
Private Declare PtrSafe Function web_fread Lib "libc.dylib" Alias "fread" (ByVal outStr As String, ByVal size As LongPtr, ByVal items As LongPtr, ByVal stream As LongPtr) As Long
Private Declare PtrSafe Function web_feof Lib "libc.dylib" Alias "feof" (ByVal file As LongPtr) As LongPtr

Public Function executeInShell(web_Command As String) As String

    Dim web_File As LongPtr
    Dim web_Chunk As String
    Dim web_Read As Long

    On Error GoTo web_Cleanup

    web_File = web_popen(web_Command, "r")

    If web_File = 0 Then
        Exit Function
    End If

    Do While web_feof(web_File) = 0
        web_Chunk = VBA.Space$(50)
        web_Read = web_fread(web_Chunk, 1, Len(web_Chunk) - 1, web_File)
        If web_Read > 0 Then
            web_Chunk = VBA.Left$(web_Chunk, web_Read)
            executeInShell = executeInShell & web_Chunk
        End If
    Loop

web_Cleanup:

    web_pclose (web_File)

End Function


Function getHTTP(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 = executeInShell(sCmd)
    getHTTP = sResult
End Function

【讨论】:

  • 这适用于 Windows 吗?我在 Mac 上开发,但希望它在 Windows 上兼容。
猜你喜欢
  • 2020-01-04
  • 2018-11-24
  • 2021-09-12
  • 1970-01-01
  • 1970-01-01
  • 2020-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多