Làm cách nào tôi có thể gửi yêu cầu POST HTTP đến máy chủ từ Excel bằng VBA?


Câu trả lời:


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

Ngoài ra, để kiểm soát tốt hơn yêu cầu HTTP, bạn có thể sử dụng WinHttp.WinHttpRequest.5.1thay thế MSXML2.ServerXMLHTTP.


9
Để kiểm soát tốt hơn yêu cầu HTTP, bạn có thể sử dụng "WinHttp.WinHttpRequest.5.1" thay vì "MSXML2.ServerXMLHTTP"
Matthew Murdoch

5
Đáng chú ý là bạn cũng có thể sử dụng điều này để phát hành PUT HTTP bằng cách thay đổi "POST" thành "PUT". Nội dung cho PUT đi theo phương thức .send (). Bất kỳ tiêu đề bổ sung nào bạn cần đặt cũng có thể được thực hiện theo cú pháp được sử dụng trong ví dụ Tác nhân người dùng.
radicand

7
Vui lòng không sử dụng dấu ngoặc đơn xung quanh các tham số nếu bạn không sử dụng giá trị trả về của Sub: Cú pháp VBA không cho phép dấu ngoặc quanh các tham số của Sub (tuy nhiên chúng cần cho các hàm), vì vậy các dấu ngoặc đơn này thực sự được sử dụng để làm rõ các ưu tiên của toán tử. Ngoài việc gây hiểu lầm và không rõ ràng, điều này cuối cùng có thể dẫn đến lỗi thời gian chạy nếu đối số là một đối tượng. Và mặc dù không được yêu cầu rõ ràng, thông thường bạn sẽ muốn sử dụng phản hồi HTTP, mà bạn có thể đề cập có thể được truy xuất bằng cách objHTTP.responseText.
Leviathan

4
@Leviathan parens thực sự làm được nhiều hơn thế: họ làm cho thời gian chạy VBA đánh giá biểu thức là một giá trịchuyển nó cho phương thức ByVal bất kể chữ ký của phương thức có nói ByRefhay không. Đó là lý do tại sao việc sử dụng chúng với các biến đối tượng thuộc loại không có thành viên mặc định gây ra lỗi thời gian chạy; và sử dụng chúng trên một đối tượng mà không có thành viên mặc định, qua giá trị mà thành viên mặc định thay vì các đối tượng thực tế.
Mathieu Guindon

1
Một triệu lần cảm ơn bạn. Tôi không biết tại sao, vì tôi đã không thấy nó trong bất kỳ ví dụ nào khác, nhưng tiêu đề "Tác nhân người dùng" rất quan trọng đối với tôi, vì nếu không thì cơ thể sẽ không được gửi theo yêu cầu của tôi.
redOc / 1013

51

Nếu bạn cần nó để hoạt động trên cả Mac và Windows, bạn có thể sử dụng 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

Ghi chú:

  • Về đầu ra ... Tôi không biết liệu có thể trả kết quả về cùng một ô được gọi là hàm VBA hay không. Trong ví dụ trên, kết quả được viết thành A2.
  • Về đầu vào ... Nếu bạn muốn kết quả được làm mới khi bạn thay đổi một số ô nhất định, hãy đảm bảo các ô đó là đối số cho hàm VBA của bạn.
  • Điều này sẽ không hoạt động trên Excel cho Mac 2008, không có VBA. Excel cho Mac 2011 đã trở lại VBA.

Để biết thêm chi tiết, bạn có thể xem tóm tắt đầy đủ của tôi về " sử dụng dịch vụ web từ Excel ."


3
+1: Tôi chỉ cần nó trên Windows nhưng một giải pháp đa nền tảng có thể mang lại lợi ích cho người khác.
Matthew Murdoch

Tôi không nghĩ rằng bạn thực sự có thể truy cập mã html, bạn chỉ có thể lấy thông tin trên trang web được hiển thị (không phải mã html thực tế)
user1493046

1
+1 cho giải pháp đa nền tảng và +1 (nếu tôi có thể) cho bản tóm tắt đầy đủ với liên kết chính và tất cả. Cảm ơn!!
không kích

Tôi đã phải hỗ trợ cả windows và mac, và giải pháp này đã đúng! Lưu ý rằng khi bạn chỉ định PostText, URL sẽ xử lý các yêu cầu POST, nếu không, nó sẽ xử lý các yêu cầu GET.
amol

1
Có thể xuất kết quả cho một biến thay vì Phạm vi không? Cần phải làm một số phân tích Json.
Stanislasdrg Tái lập Monica

42

Ngoài anwser của Bill the Lizard :

Hầu hết các phụ trợ phân tích dữ liệu bài thô. Trong PHP chẳng hạn, bạn sẽ có một mảng $_POSTtrong đó các biến riêng lẻ trong dữ liệu bài đăng sẽ được lưu trữ. Trong trường hợp này, bạn phải sử dụng một tiêu đề bổ sung "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")

Nếu không, bạn phải đọc dữ liệu bài thô trên biến "$HTTP_RAW_POST_DATA".


1
Tôi đang cố gắng gửi yêu cầu này (với dấu ngoặc nhọn) và gặp lỗi biên dịch ... bạn có thể giúp tôi không: "{" request ": {" carName ":" Honda "," model ":" 1A5 "}}"
fiddle

6

Bạn có thể sử dụng ServerXMLHTTPtrong một dự án VBA bằng cách thêm một tham chiếu đến MSXML.

  1. Mở Trình chỉnh sửa VBA (thường bằng cách chỉnh sửa Macro)
  2. Chuyển đến danh sách các tài liệu tham khảo có sẵn
  3. Kiểm tra Microsoft XML
  4. Nhấn OK.

(từ Tham khảo MSXML trong các Dự án VBA )

Các tài liệu ServerXMLHTTP MSDN có đầy đủ chi tiết về tất cả các thuộc tính và phương pháp ServerXMLHTTP.

Nói tóm lại, nó hoạt động cơ bản như thế này:

  1. Gọi phương thức mở để kết nối với máy chủ từ xa
  2. Gọi gửi để gửi yêu cầu.
  3. Đọc phản hồi thông qua answerXML , answerText , answerStream hoặc answerBody

1
liên kết đó sử dụng jscript, không phải VBA
John Henckel

1
Cảm ơn @ JohnHenckel. Tôi đã thực hiện một số thay đổi để cập nhật câu trả lời đó.
Mark Biek

3

Để hoàn thành phản hồi của những người dùng khác:

Đối với điều này, tôi đã tạo ra một "WinHttp.WinHttpRequest.5.1" đối tượng .

Gửi yêu cầu bài đăng với một số dữ liệu từ Excel bằng 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")

Gửi yêu cầu nhận xác thực mã thông báo từ Excel bằng 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, một khi bạn gửi yêu cầu, làm thế nào để bạn đọc phản hồi?
ps0604

Phản hồi ở bên trong TCRequestItem Object, bạn có thể đọc nó như TCRequestItem.ResponseTextsau : sau khi thực hiệnTCRequestItem.send
David Q

0

Tôi đã làm điều này trước khi sử dụng thư viện MSXML và sau đó sử dụng đối tượng XMLHttpRequest, xem tại đây .


1
Không tìm thấy tập tin.
SuShuang
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.