如何使用VBA从Excel向服务器发送HTTP POST请求?

166

从Excel电子表格执行HTTP POST请求需要哪些VBA代码?

6个回答

174
Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
URL = "http://www.somedomain.com"
objHTTP.Open "POST", URL, False
objHTTP.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
objHTTP.send ""

或者,为了更好地控制HTTP请求,您可以使用 WinHttp.WinHttpRequest.5.1 替代 MSXML2.ServerXMLHTTP


10
为了更好地控制HTTP请求,您可以使用“WinHttp.WinHttpRequest.5.1”代替“MSXML2.ServerXMLHTTP”。 - Matthew Murdoch
6
值得注意的是,您也可以通过将“POST”更改为“PUT”来使用此方法发出HTTP PUT请求。PUT内容放在.send()方法中。如果您需要设置任何额外的标头,则可以按照User-Agent示例中使用的语法进行设置。 - radicand
10
如果您不使用Sub的返回值,请不要在参数周围使用括号:VBA语法不允许在Sub的参数周围使用括号(虽然它们对于函数是必需的),因此这些括号实际上是用于澄清运算符优先级的算术括号。除了具有误导性和不清晰之外,如果参数是对象,则最终可能会导致运行时错误。虽然没有明确要求,但通常您希望使用HTTP响应,您可以提到可以通过“objHTTP.responseText”检索该响应。 - Leviathan
6
括号的作用不仅限于此:它们使VBA运行时将表达式作为一个值进行评估,并将其传递给方法ByVal,而不管方法的签名是否声明了“ByRef”。这就是为什么对于没有默认成员的类型的对象变量使用括号会导致运行时错误;而对于具有默认成员的对象使用括号,则传递该默认成员的值而不是实际对象。请注意,本翻译尽可能保证原意,同时简化表述,如有理解偏差请谅解。 - Mathieu Guindon
2
一个 JSON 负载怎么样...我们如何在 send 中传递它? - Amrit
显示剩余2条评论

60

除了Bill the Lizard的答案之外:

大多数后端都会解析原始的POST数据。例如,在PHP中,您将拥有一个名为$_POST的数组,其中将存储在POST数据中的各个变量。在这种情况下,您必须使用额外的标题"Content-type: application/x-www-form-urlencoded"

Set objHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
URL = "http://www.somedomain.com"
objHTTP.Open "POST", URL, False
objHTTP.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
objHTTP.setRequestHeader "Content-type", "application/x-www-form-urlencoded"
objHTTP.send "var1=value1&var2=value2&var3=value3"
否则,您必须读取变量"$HTTP_RAW_POST_DATA"上的原始帖子数据。

1
我正在尝试发布此请求(带有花括号),但出现编译错误...您能帮忙吗:"{"request":{"carName":"Honda","model" : "1A5"}}" - fiddle
@fiddle 你对那个字符串进行了URL编码吗?花括号不是太重要,引号才是问题(会终止VBA中的字符串)。 - Ruscal

59

如果需要它在Mac和Windows上都能工作,你可以使用QueryTables:

With ActiveSheet.QueryTables.Add(Connection:="URL;http://carbon.brighterplanet.com/flights.txt", Destination:=Range("A2"))
    .PostText = "origin_airport=MSN&destination_airport=ORD"
    .RefreshStyle = xlOverwriteCells
    .SaveData = True
    .Refresh
End With

注意:

  • 关于输出...我不知道是否可能将结果返回到调用VBA函数的同一个单元格中。在上面的示例中,结果被写入A2。
  • 关于输入...如果你希望在更改某些单元格时刷新结果,请确保这些单元格是你的VBA函数的参数。
  • 这在Excel for Mac 2008上不起作用,因为它没有VBA。 Excel for Mac 2011重新引入了VBA。

欲了解更多详情,您可以查看我的有关“从Excel使用Web服务”的完整总结。


4
我只需要在Windows上使用它,但跨平台的解决方案可能会让其他人受益。 - Matthew Murdoch
我认为你实际上无法访问HTML代码,你只能获取呈现的网页上的信息(而不是实际的HTML代码)。 - user1493046
1
+1 个跨平台解决方案,+1(如果可以的话)带有 Gist 链接和完整摘要的总结。谢谢! - airstrike
我必须支持Windows和Mac,这个解决方案非常适合!请注意,当您指定PostText时,URL应该处理POST请求,否则它应该处理GET请求。 - amolk
2
是否可以将结果输出到变量而不是范围?需要进行一些Json解析。 - Standaa - Remember Monica

16

为了完成其他用户的回应,我创建了一个名为"WinHttp.WinHttpRequest.5.1"的对象。

使用VBA从Excel发送带有一些数据的POST请求:

Dim LoginRequest As Object
Set LoginRequest = CreateObject("WinHttp.WinHttpRequest.5.1")
LoginRequest.Open "POST", "http://...", False
LoginRequest.setRequestHeader "Content-type", "application/x-www-form-urlencoded"
LoginRequest.send ("key1=value1&key2=value2")

使用VBA从Excel发送具有令牌身份验证的GET请求:

Dim TCRequestItem As Object
Set TCRequestItem = CreateObject("WinHttp.WinHttpRequest.5.1")
TCRequestItem.Open "GET", "http://...", False
TCRequestItem.setRequestHeader "Content-Type", "application/xml"
TCRequestItem.setRequestHeader "Accept", "application/xml"
TCRequestItem.setRequestHeader "Authorization", "Bearer " & token
TCRequestItem.send

David,一旦你发送请求,你如何读取响应? - ps0604
响应内容在 TCRequestItem 对象内部,您可以通过执行 TCRequestItem.send 后读取 TCRequestItem.ResponseText 来获取它。 - dvque
请问,@david.q,那个“token”变量是从哪来的? - Yorga Babuscan

8
通过在VBA项目中添加对MSXML的引用,可以在VBA项目中使用ServerXMLHTTP
操作步骤如下:
  1. 打开VBA编辑器(通常通过编辑宏来实现)
  2. 转到“可用引用”列表
  3. 勾选 Microsoft XML
  4. 单击确定。
有关ServerXMLHTTP的所有属性和方法的详细信息,请参阅ServerXMLHTTP MSDN文档
简而言之,它的工作原理基本如下:
  1. 调用open方法连接到远程服务器
  2. 调用send方法发送请求。
  3. 通过responseXMLresponseTextresponseStreamresponseBody读取响应。
(引自在VBA项目中引用MSXML

1
那个链接使用的是JScript而不是VBA。 - John Henckel
1
感谢@JohnHenckel。我已经做了一些更改,使那个答案更新到最新状态。 - Mark Biek

1

我以前使用过MSXML库和XMLHttpRequest对象来完成这个,可以看这里


1
文件未找到。 - SuShuang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接