Как я могу отправить запрос HTTP POST на сервер из Excel, используя VBA?


Ответы:


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

Кроме того, для большего контроля над HTTP-запросом вы можете использовать WinHttp.WinHttpRequest.5.1вместо MSXML2.ServerXMLHTTP.


9
Для большего контроля над HTTP-запросом вы можете использовать «WinHttp.WinHttpRequest.5.1» вместо «MSXML2.ServerXMLHTTP»
Мэтью Мердок

5
Следует отметить, что вы также можете использовать это для выдачи HTTP PUT, изменив «POST» на «PUT». Содержимое для PUT отправляется в методе .send (). Любые дополнительные заголовки, которые вам нужно установить, могут быть выполнены также в соответствии с синтаксисом, использованным в примере User-Agent.
radicand

7
Пожалуйста, не используйте скобки вокруг параметров, если вы не используете возвращаемое значение Sub: Синтаксис VBA не допускает скобки вокруг параметров Sub (хотя они необходимы для функций), поэтому эти скобки на самом деле являются арифметическими скобками, используемыми для пояснения приоритета оператора. Помимо введения в заблуждение и неясности, это может в конечном итоге привести к ошибке времени выполнения, если аргумент является объектом. И хотя это явно не запрашивается, обычно вы хотите использовать HTTP-ответ, который вы могли бы упомянуть, чтобы получить его objHTTP.responseText.
Левиафан

4
@Leviathan парены на самом деле делают больше, чем просто: они заставляют среду выполнения VBA оценивать выражение как значение и передают его методу ByVal независимо от того, говорит подпись метода ByRefили нет. Вот почему их использование с объектными переменными типа, который не имеет члена по умолчанию, вызывает ошибки во время выполнения; и используя их на объекте, который имеет элемент по умолчанию, передает значение этого элемента по умолчанию вместо фактического объекта.
Матье

1
Миллион раз спасибо. Я не знаю почему, потому что я не видел его ни в каких других примерах, но заголовок «User-Agent» был для меня решающим, потому что иначе тело не было отправлено в моем запросе.
красное октября 13

51

Если вам это нужно для работы на 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 для Mac 2008, где нет VBA. Excel для Mac 2011 вернул VBA.

Для получения более подробной информации, вы можете увидеть мое полное резюме о « использовании веб-служб из Excel ».


3
+1: мне это нужно только в Windows, но кроссплатформенное решение может принести пользу кому-то еще.
Мэтью Мердок

Я не думаю, что вы можете получить доступ к HTML-коду, вы можете получить информацию только на отображаемой веб-странице (не фактический HTML-код)
user1493046

1
+1 для кроссплатформенного решения и +1 (если бы я мог) за полное резюме со ссылкой на гист и все. Спасибо!!
авиаудар

Я должен был поддерживать и Windows, и Mac, и это решение было правильным! Обратите внимание, что когда вы указываете PostText, URL должен обрабатывать запросы POST, в противном случае он должен обрабатывать запросы GET.
Amolk

1
Можно ли вывести результаты в переменную вместо диапазона? Нужно сделать несколько разборов Json.
Stanislasdrg Восстановить Монику

42

В дополнение к ответу Билла Ящера :

Большинство бэкэндов анализируют необработанные почтовые данные. Например, в PHP у вас будет массив, $_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 "}}"
скрипка

6

Вы можете использовать ServerXMLHTTPв проекте VBA, добавив ссылку на MSXML.

  1. Откройте редактор VBA (обычно путем редактирования макроса)
  2. Перейти к списку доступных ссылок
  3. Проверьте Microsoft XML
  4. Нажмите ОК.

(из ссылок на MSXML в проектах VBA )

Документация ServerXMLHTTP MSDN содержит полную информацию обо всех свойствах и методах ServerXMLHTTP.

Короче говоря, это работает в основном так:

  1. Вызовите метод open для подключения к удаленному серверу.
  2. Вызов отправить отправить запрос.
  3. Прочитайте ответ через responseXML , responseText , responseStream или responseBody

1
эта ссылка использует jscript, а не VBA
Джон Хенкель

1
Спасибо @ДжонХенкель. Я внес некоторые изменения, чтобы обновить этот ответ.
Марк Бик,

3

Чтобы завершить ответ других пользователей:

Для этого я создал объект «WinHttp.WinHttpRequest.5.1» .

Отправить запрос с некоторыми данными из Excel, используя 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")

Отправьте запрос на получение с аутентификацией токена из Excel, используя 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

Дэвид, как только ты отправишь запрос, как ты читаешь ответ?
ps0604

Ответ внутри TCRequestItem Object, вы можете прочитать его как: TCRequestItem.ResponseTextпосле выполненияTCRequestItem.send
Дэвид Q

0

Я сделал это до использования библиотеки MSXML, а затем с помощью объекта XMLHttpRequest, см. Здесь .


1
Файл не найден.
СуШуан
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.