Comment puis-je envoyer une requête HTTP POST à ​​un serveur depuis Excel à l'aide de VBA?

135

Quel code VBA est requis pour effectuer un HTTP POST à ​​partir d'une feuille de calcul Excel?

Matthieu Murdoch
la source

Réponses:

147
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("")

Sinon, pour un meilleur contrôle sur la requête HTTP, vous pouvez utiliser WinHttp.WinHttpRequest.5.1à la place de MSXML2.ServerXMLHTTP.

Bill le lézard
la source
9
Pour un meilleur contrôle sur la requête HTTP, vous pouvez utiliser "WinHttp.WinHttpRequest.5.1" au lieu de "MSXML2.ServerXMLHTTP"
Matthew Murdoch
5
Il est à noter que vous pouvez également l'utiliser pour émettre un HTTP PUT en changeant "POST" en "PUT". Le contenu de PUT va dans la méthode .send (). Tous les en-têtes supplémentaires que vous devez définir peuvent également être définis en suivant la syntaxe utilisée dans l'exemple User-Agent.
radicand
7
Veuillez ne pas utiliser de parenthèses autour des paramètres si vous n'utilisez pas la valeur de retour de Sub: La syntaxe VBA n'autorise pas les parenthèses autour des paramètres de Sub (elles sont cependant nécessaires pour les fonctions), donc ces parenthèses sont en fait des parenthèses arithmétiques utilisées pour clarifier la priorité des opérateurs. En plus d'être trompeur et peu clair, cela peut éventuellement entraîner une erreur d'exécution si l'argument est un objet. Et bien que cela ne soit pas explicitement demandé, vous voudrez généralement utiliser la réponse HTTP, dont vous pourriez mentionner qu'elle peut être récupérée par objHTTP.responseText.
Leviathan
4
@Leviathan les parens font en fait plus que cela: ils font que le moteur d'exécution VBA évalue l'expression comme une valeur et la transmet à la méthode ByVal, que la signature de la méthode le dise ByRefou non. C'est pourquoi leur utilisation avec des variables d'objet d'un type qui n'a pas de membre par défaut provoque des erreurs d'exécution; et de les utiliser sur un objet qui fait un membre par défaut, la valeur passe de ce membre par défaut au lieu de l'objet réel.
Mathieu Guindon
1
Un million de fois merci. Je ne sais pas pourquoi, car je ne l'ai vu dans aucun autre exemple, mais l'en-tête "User-Agent" était crucial pour moi, car sinon le corps n'était pas envoyé dans ma requête.
redOctober13
51

Si vous en avez besoin pour fonctionner à la fois sur Mac et Windows, vous pouvez utiliser 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

Remarques:

  • Concernant la sortie ... je ne sais pas s'il est possible de renvoyer les résultats dans la même cellule qui a appelé la fonction VBA. Dans l'exemple ci-dessus, le résultat est écrit dans A2.
  • Concernant l'entrée ... Si vous souhaitez que les résultats s'actualisent lorsque vous modifiez certaines cellules, assurez-vous que ces cellules sont l'argument de votre fonction VBA.
  • Cela ne fonctionnera pas sur Excel pour Mac 2008, qui n'a pas VBA. Excel pour Mac 2011 a récupéré VBA.

Pour plus de détails, vous pouvez consulter mon résumé complet sur «l' utilisation des services Web d'Excel ».

Seamus Abshere
la source
3
+1: Je n'en ai besoin que sur Windows mais une solution multiplateforme pourrait profiter à quelqu'un d'autre.
Matthew Murdoch
Je ne pense pas que vous puissiez accéder au code html, vous ne pouvez obtenir les informations que sur la page Web rendue (pas le code html réel)
user1493046
1
+1 pour la solution multiplateforme et +1 (si je pouvais) pour le résumé complet avec lien essentiel et tout. Merci!!
frappe aérienne du
Je devais prendre en charge Windows et Mac, et cette solution était juste! Notez que lorsque vous spécifiez PostText, l'URL doit traiter les requêtes POST, sinon elle doit traiter les requêtes GET.
amolk
1
Est-il possible de sortir les résultats dans une variable au lieu d'une plage? Besoin de faire une analyse Json.
Stanislasdrg réintègre Monica le
42

En plus de la réponse de Bill the Lizard :

La plupart des backends analysent les données de publication brutes. En PHP par exemple, vous aurez un tableau $_POSTdans lequel des variables individuelles dans les données de publication seront stockées. Dans ce cas, vous devez utiliser un en-tête supplémentaire "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")

Sinon, vous devez lire les données de publication brutes sur la variable "$HTTP_RAW_POST_DATA".

ce code
la source
1
J'essaye de poster cette demande (avec des accolades) et j'obtiens des erreurs de compilation ... pouvez-vous aider: "{" request ": {" carName ":" Honda "," model ":" 1A5 "}}"
violon
6

Vous pouvez utiliser ServerXMLHTTPdans un projet VBA en ajoutant une référence à MSXML.

  1. Ouvrez l'éditeur VBA (généralement en éditant une macro)
  2. Aller à la liste des références disponibles
  3. Vérifiez Microsoft XML
  4. Cliquez sur OK.

(à partir du référencement MSXML dans les projets VBA )

La documentation MSDN ServerXMLHTTP contient des détails complets sur toutes les propriétés et méthodes de ServerXMLHTTP.

En bref, cela fonctionne essentiellement comme ceci:

  1. Appelez la méthode ouverte pour vous connecter au serveur distant
  2. Appelez envoyer pour envoyer la demande.
  3. Lire la réponse via responseXML , responseText , responseStream ou responseBody
Mark Biek
la source
1
ce lien utilise jscript, pas VBA
John Henckel
1
Merci @JohnHenckel. J'ai apporté quelques modifications pour mettre cette réponse à jour.
Mark Biek
3

Pour compléter la réponse des autres utilisateurs:

Pour cela, j'ai créé un objet "WinHttp.WinHttpRequest.5.1" .

Envoyez une demande de publication avec des données d'Excel en utilisant VBA:

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")

Envoyez une demande d'obtention avec l'authentification par jeton d'Excel à l'aide de VBA:

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 Q
la source
David, une fois que vous envoyez la demande, comment lisez-vous la réponse?
ps0604
La réponse est à l'intérieur TCRequestItem Object, vous pouvez la lire comme: TCRequestItem.ResponseTextaprès l'avoir faitTCRequestItem.send
David Q
0

Je l'ai fait avant d'utiliser la bibliothèque MSXML, puis d'utiliser l'objet XMLHttpRequest, voir ici .

Sijin
la source
1
Fichier non trouvé.
SuShuang