我需要从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上。
有任何建议,还是没有希望?
答案 0 :(得分:21)
进一步研究,我遇到了Robert Knight对这个问题VBA Shell function in Office 2011 for Mac的评论,并使用他的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
要使用此功能,请复制上面的代码,在Excel for Mac 2011中打开VBA编辑器。如果您没有模块,请单击“插入” - >“模块”。将代码粘贴到模块文件中。离开VBA编辑器(clover-Q)。
以下是使用天气预报网络服务(http://openweathermap.org/wiki/API/JSON_API)
的具体示例单元格A1将保留为城市名称。
在单元格A2中,输入网址字符串: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!
答案 1 :(得分:6)
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
答案 2 :(得分:0)
另一个选项(如果您的卷曲不在/ 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