2016-07-05 22 views
1

我正在寫一個非常簡單的宏,需要向服務器發出HTTP GET請求,並且響應不重要(它會啓動服務器上的進程)。 HTTP GET不需要認證。在OSX Excel中使用VBA獲取HTTP請求

我用下面的代碼來做到這一點「成功」(服務器日誌顯示的請求時,它向服務器,但在服務器運行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. 

我可以看到服務器返回的,因爲之後的GET請求不被髮送正確Content-Type頭的一些研究正在發生的HTTP 406。

所以我的問題是 - 如何告訴ActiveSheet.QueryTables.Add設置標題,或者我怎麼修改我的NGINX配置來支持這個特定的GET CALL

+0

也許檢查此http://stackoverflow.com/questions/15981960/我怎麼做的問題 - 從http-get-from-excel-vba-for-mac-2011這基本上是說要將cURL外殼化,而不是使用QueryTables方法來執行HTTP GET。您將能夠以這種方式設置請求標頭。 –

回答

1

下面是一段代碼,它支持OSX和Windows。我將這種信貸的作家,因爲我當然didnt寫從頭開始,但我已經記不清在這一切的來源:

#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 
+1

看起來不錯。但在Mac Excel 15上不適用於我。「Private Declare Function popen」這些行是紅色的!! – fabian

+1

是的,最新版本的Excel打破了這一點,我發現修復。 – josephmisiti

+1

使用私有聲明PtrSafe函數...它應該是工作! – Lin

0

這不是爲我工作在Mac的Excel 15.4任。我發現VBA的工具有幫助的版本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