Vba excel winhttp winhttprequest

To complete the response of the other users:

For this I have created an «WinHttp.WinHttpRequest.5.1» object.

Send a post request with some data from Excel using 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")

Send a get request with token authentication from Excel using 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

Пользовательские функции VBA Excel для парсинга сайтов, html-страниц и файлов, возвращающие их текстовое содержимое. Примеры записи текста в переменную.

Парсинг html-страниц (msxml2.xmlhttp)

Пользовательская функция GetHTML1 (VBA Excel) для извлечения (парсинга) текстового содержимого из html-страницы сайта по ее URL-адресу с помощью объекта «msxml2.xmlhttp»:

Function GetHTML1(ByVal myURL As String) As String

On Error Resume Next

    With CreateObject(«msxml2.xmlhttp»)

        .Open «GET», myURL, False

        .send

        Do: DoEvents: Loop Until .readyState = 4

        GetHTML1 = .responseText

    End With

End Function

Парсинг сайтов (WinHttp.WinHttpRequest.5.1)

Пользовательская функция GetHTML2 (VBA Excel) для извлечения (парсинга) текстового содержимого из html-страницы сайта по ее URL-адресу с помощью объекта «WinHttp.WinHttpRequest.5.1»:

Function GetHTML2(ByVal myURL As String) As String

On Error Resume Next

    With CreateObject(«WinHttp.WinHttpRequest.5.1»)

        .Open «GET», myURL, False

        .send

        Do: DoEvents: Loop Until .readyState = 4

        GetHTML2 = .responseText

    End With

End Function

Парсинг файлов (ADODB.Stream)

Пользовательская функция GetText (VBA Excel) для извлечения (парсинга) текстового содержимого из файла (.txt, .csv, .mhtml), сохраненного на диск компьютера, по его полному имени (адресу) с помощью объекта «ADODB.Stream»:

Function GetText(ByVal myFile As String) As String

On Error Resume Next

    With CreateObject(«ADODB.Stream»)

        .Charset = «utf-8»

        .Open

        .LoadFromFile myFile

        GetText = .ReadText

        .Close

    End With

End Function

Примеры записи текста в переменную

Общая формула записи текста, извлеченного с помощью пользовательских функций VBA Excel, в переменную:

Dim htmlText As String

htmlText = GetHTML1(«Адрес сайта (html-страницы)»)

htmlText = GetHTML2(«Адрес сайта (html-страницы)»)

htmlText = GetText(«Полное имя файла»)

Конкретные примеры:

htmlText = GetHTML1(«https://internettovary.ru/nabor-dlya-vyrashchivaniya-veshenki/»)

htmlText = GetHTML2(«https://internettovary.ru/nabor-dlya-vyrashchivaniya-veshenki/»)

htmlText = GetText(«C:UsersEvgeniyDownloadsНовый текстовый документ.txt»)

htmlText = GetText(«C:UsersEvgeniyDownloadsИспользование msxml2.xmlhttp в Excel VBA.mhtml»)

В понятие «парсинг», кроме извлечения текстового содержимого сайтов, html-страниц или файлов, входит поиск и извлечение конкретных данных из всего полученного текстового содержимого.

Пример извлечения email-адресов из текста, присвоенного переменной, смотрите в последнем параграфе статьи: Регулярные выражения (объекты, свойства, методы).

Парсинг содержимого тегов

Извлечение содержимого тегов с помощью метода getElementsByTagName объекта HTMLFile:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

Sub Primer1()

Dim myHtml As String, myFile As Object, myTag As Object, myTxt As String

    ‘Извлекаем содержимое html-страницы в переменную myHtml с помощью функции GetHTML1

    myHtml = GetHTML1(«https://internettovary.ru/sadovaya-nozhovka-sinitsa/»)

    ‘Создаем объект HTMLFile

    Set myFile = CreateObject(«HTMLFile»)

    ‘Записываем в myFile текст из myHtml

    myFile.body.innerHTML = myHtml

    ‘Присваиваем переменной myTag коллекцию одноименных тегов, имя которого

    ‘указанно в качестве аргумента метода getElementsByTagName

    Set myTag = myFile.getElementsByTagName(«p»)

    ‘Выбираем, содержимое какого тега по порядку, начинающегося с 0, нужно извлечь

    myTxt = myTag(5).innerText

    MsgBox myTxt

    ‘Большой текст может не уместиться в MsgBox, тогда для просмотра используйте окно Immediate

    ‘Debug.Print myTxt

End Sub

С помощью этого кода извлекается текст, расположенный между открывающим и закрывающим тегами. В примере — это текст 6-го абзаца (p) между 5-й (нумерация с 0) парой отрывающего <p> и закрывающего </p> тегов.

Примеры тегов, используемых в html: "p", "title", "h1", "h2", "table", "div", "script".

Пример извлечения содержимого тега "title":

Sub Primer2()

Dim myHtml As String, myFile As Object, myTag As Object, myTxt As String

    myHtml = GetHTML1(«https://internettovary.ru/sadovaya-nozhovka-sinitsa/»)

    Set myFile = CreateObject(«HTMLFile»)

    myFile.body.innerHTML = myHtml

    Set myTag = myFile.getElementsByTagName(«title»)

    myTxt = myTag(0).innerText

    MsgBox myTxt

End Sub

Парсинг содержимого Id

Извлечение текстового содержимого html-элементов, имеющих уникальный идентификатор — Id, с помощью метода getElementById объекта HTMLFile:

Sub Primer3()

Dim myHtml As String, myFile As Object, myTag As Object, myTxt As String

    myHtml = GetHTML1(«https://internettovary.ru/sadovaya-nozhovka-sinitsa/»)

    Set myFile = CreateObject(«HTMLFile»)

    myFile.body.innerHTML = myHtml

    ‘Присваиваем переменной myTag html-элемент по указанному в скобках Id

    Set myTag = myFile.getElementById(«attachment_465»)

    ‘Присваиваем переменной myTxt текстовое содержимое html-элемента с Id

    myTxt = myTag.innerText

    MsgBox myTxt

    ‘Большой текст может не уместиться в MsgBox, тогда для просмотра используйте окно Immediate

    ‘Debug.Print myTxt

End Sub

Для реализации представленных здесь примеров могут понадобиться дополнительные библиотеки. В настоящее время у меня подключены следующие (к данной теме могут относиться последние шесть):

  • Visual Basic For Applications
  • Microsoft Excel 16.0 Object Library
  • OLE Automation
  • Microsoft Office 16.0 Object Library
  • Microsoft Forms 2.0 Object Library
  • Ref Edit Control
  • Microsoft Scripting Runtime
  • Microsoft Word 16.0 Object Library
  • Microsoft Windows Common Controls 6.0 (SP6)
  • Microsoft ActiveX Data Objects 6.1 Library
  • Microsoft ActiveX Data Objects Recordset 6.0 Library
  • Microsoft HTML Object Library
  • Microsoft Internet Controls
  • Microsoft Shell Controls And Automation
  • Microsoft XML, v6.0

С этим набором библиотек все примеры работают. Тестирование проводилось в VBA Excel 2016.


  • Remove From My Forums
  • Question

  • How do I add a reference (what magic name/path do I use) for WinHttpRequest from Excel VBA?

    I want to access a site that needs credentials.

    Another option?

    Excel 2010

Answers

  • >>>>How do I add a reference (what magic name/path do I use) for WinHttpRequest from Excel VBA?

    Set a reference to Microsoft WinHTTP Services. You can do that by clicking on menu tools~~> references

    Here is an example. I just wrote this example. I have not tested it.

    Const HTTPREQUEST_SETCREDENTIALS_FOR_SERVER = 0
    
    Private Sub Sample()
     Dim httpRequest As New WinHttpRequest
     Dim UName As String, Upass As String
     
     httpRequest.Open "GET", "http://BlahBlah.com"
     
     UName = "Siddharth Rout"
     Upass = "Blah Blah"
     
     '~~> Here you have to set credentials
     httpRequest.SetCredentials UName, Upass, _
     HTTPREQUEST_SETCREDENTIALS_FOR_SERVER
    
     '~~> Here you send the request
     httpRequest.Send
    
     '~~> Here we get this response
     MsgBox httpRequest.ResponseText
    End Sub
    


    Sid (A good exercise for the Heart is to bend down and help another up)

    Please do not email me your questions. I do not answer questions by email unless I get paid for it :) If you want, create a thread in Excel forum and email me the link and I will help you if I can.

    • Proposed as answer by

      Monday, August 8, 2011 7:32 AM

    • Marked as answer by
      Macy Dong
      Thursday, August 11, 2011 2:26 AM

  • Hello Bob

    1) On Windows 7 + Office 2010, I was able to add the reference to Microsoft WinHTTP Services. It didn’t give me any error.

    2) Path should be c:windowssystem32winhttp.dll


    Sid (A good exercise for the Heart is to bend down and help another up) Please do not email me your questions. I do not answer questions by email unless I get paid for it :) If you want, create a thread in Excel forum and email me the link and I will help
    you if I can.

    • Proposed as answer by
      Macy Dong
      Monday, August 8, 2011 7:32 AM
    • Marked as answer by
      Macy Dong
      Thursday, August 11, 2011 2:26 AM

  • Интернет
  • Логин и пароль
  • Интернет-порталы

Приведённый ниже код выполняет авторизацию на Яндексе, отправляя GET и POST запрос

На время POST запроса отключается автоматический редирект, чтобы сохранить Cookies, переданные в ответе сервера

PS: Код предназначен для специалистов!
Я не готов отвечать на вопросы, почему у вас не получилось авторизоваться, и что делать с этим макросом дальше (как получать данные)

Public CookiesStore As Object        ' as Dictionary

 
Sub test_Yandex_Authentication()        ' пример использования

    If YM_Auth("MyLogin", "MyPassword") Then
        Debug.Print "Авторизация выполнена"
        Debug.Print "Сохранённые куки:", GetCookiesFromStore
    Else
        Debug.Print "Ошибка авторизации"
    End If
End Sub
Function YM_Auth(ByVal YM_login$, ByVal YM_password$) As Boolean
    ' © 2014 EducatedFool   ExcelVBA.ru
    ' функция выполняет авторизацию на Яндексе, принимая в качестве параметров логин и пароль
    ' возвращает TRUE, если авторизация выполнена

    ' в глобальном словаре CookiesStore сохраняет все куки, ответственные за авторизацию
    ' во всех дальнейших запросах надо использовать добавление заголовка COOKIE из этого хранилища
    ' при помощи строки кода .SetRequestHeader "Cookie", GetCookiesFromStore

On Error Resume Next
    Dim RequestTimeout&, wHTTP As Object, Response$, ResponseHeaders$, URL$
    Const StartURL$ = "http://market.yandex.ru/"
    Const AuthURL$ = "https://passport.yandex.ru/auth"
 
    RequestTimeout& = 6        ' таймаут (в секундах) ожидания ответа от сервера
    Set wHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
    Set CookiesStore = CreateObject("Scripting.Dictionary")        ' ОБЯЗАТЕЛЬНО НУЖНА ГЛОБАЛЬНАЯ ПЕРЕМЕННАЯ CookiesStore !

    With wHTTP
        ' открываем произвольную страницу Яндекса, чтобы получить ID сессии
        .Open "GET", StartURL$, True
        AddStaticHeaders wHTTP        ' добавляем заголовки запроса (представляясь браузером Chrome)
        .Send
 
        If .WaitForResponse(RequestTimeout&) Then        ' если дождались ответа от сервера
            SaveCookiesFromResponseHeaders .GetAllResponseHeaders        ' запоминаем куки

            .Open "POST", AuthURL$, True        ' выполняем POST запрос для авторизации
            ' отключаем авторедирект, чтобы получать cookies при каждом редиректе
            .Option(WinHttpRequestOption_EnableRedirects) = False
 
            AddStaticHeaders wHTTP        ' добавляем заголовки запроса (представляясь браузером Chrome)
            .SetRequestHeader "Cookie", GetCookiesFromStore
            .SetRequestHeader "Host", "passport.yandex.ru" 
 
            Dim POST() As Byte, PostData$, timestamp$        ' отправка данных учётной записи
            timestamp$ = (Now - 25569) * 86400000        ' время в формате UNIX
            PostData$ = "login=" & YM_login$ & "&passwd=" & YM_password$ & _
                        "&timestamp=" & timestamp$ & "&retpath=http://market.yandex.ru/"
            POST = StrConv(PostData, vbFromUnicode)
            .Send (POST): DoEvents
 
            If .WaitForResponse(RequestTimeout&) Then
                If .Status Like "30*" Then        ' если произошёл редирект, - значит, мы авторизовались успешно
                    SaveCookiesFromResponseHeaders .GetAllResponseHeaders        ' запоминаем куки
                    YM_Auth = True
                End If
            Else
                Debug.Print "Request Timeout (" & RequestTimeout & " seconds)", AuthURL$        ' истекло время ожидания
            End If
        Else
            Debug.Print "Request Timeout (" & RequestTimeout & " seconds)", StartURL$        ' истекло время ожидания
        End If
        .Option(WinHttpRequestOption_EnableRedirects) = True
    End With
    Set wHTTP = Nothing
End Function
Sub AddStaticHeaders(ByRef wHTTP As Object)
    On Error Resume Next
    With wHTTP
        '.SetRequestHeader "Host", "market.yandex.ru"
        .SetRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36"
        .SetRequestHeader "Accept-Language", "ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4"
        .SetRequestHeader "Connection", "keep-alive": .SetRequestHeader "Cache-Control", "no-cache"
        .SetRequestHeader "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
        .SetRequestHeader "Content-Type", "application/x-www-form-urlencoded"
        .SetRequestHeader "Origin", "http://market.yandex.ru"
        .SetRequestHeader "Referer", "http://market.yandex.ru/"
    End With
End Sub
Function TextBetween(ByVal txt$, ByVal part1$, ByVal part2$, ByVal sep$) As String
    ' функция ищет в текстовой строке TXT блоки, начинающиеся текстом part1$, и заканчивающиеся текстом part2$
    ' возвращает массив найденных значений (объединённых в одну строку через разделитель sep$)
    On Error Resume Next
    Dim arr, i, res$
    Select Case ""
        Case part1$ & part2$: TextBetween = txt: Exit Function
        Case part1$: arr = Split(txt, part2$): arr(UBound(arr)) = ""
        Case part2$: arr = Split(txt, part1$): arr(0) = ""
        Case Else: arr = Split(txt, part1$)
            arr(0) = ""
            For i = LBound(arr) To UBound(arr)
                If InStr(1, arr(i), part2$, vbTextCompare) Then arr(i) = Split(arr(i), part2$)(0) Else arr(i) = ""
            Next i
    End Select
    txt = Join(arr, sep$)
    If sep$ = "" Then TextBetween = txt: Exit Function
    While InStr(1, txt$, sep$ & sep$, vbBinaryCompare): txt$ = Replace(txt$, sep$ & sep$, sep$): Wend
    If txt$ Like "*" & sep$ Then txt = Left(txt, Len(txt) - Len(sep$))
    If txt$ Like sep$ & "*" Then txt = Mid(txt, Len(sep$) + 1)
    TextBetween = txt
End Function
Function GetRedirectLocation(ByVal ResponseHeaders$, Optional CurrentURL$) As String
    ' если в заголовках ResponseHeaders$ есть заголовок Location,
    ' то функция возвращает путь для редиректа
    On Error Resume Next
    ResponseHeaders$ = Replace(ResponseHeaders$, "-Location", "")
    If InStr(1, ResponseHeaders$, "Location: ", vbTextCompare) = 0 Then Exit Function
 
    Dim URL$, BaseURL$: URL$ = Split(TextBetween(ResponseHeaders$, "Location: ", vbNewLine, vbNewLine), vbNewLine)(0)
    If IsURL(URL$) Then
        GetRedirectLocation = URL$
    Else
        If (URL$ Like "/*") And IsURL(CurrentURL$) Then
            BaseURL$ = Split(CurrentURL$, "://")(0) & "://" & Split(Split(CurrentURL$, "://")(1), "/")(0)
            GetRedirectLocation = BaseURL$ & URL$
        End If
    End If
    If Len(GetRedirectLocation) Then Debug.Print "redirect to " & GetRedirectLocation
End Function
 
Function IsURL(ByVal txt$) As Boolean
    IsURL = IsURL Or (txt$ Like "http://?*.?*")
    IsURL = IsURL Or (txt$ Like "https://?*.?*")
End Function
 
Function SaveCookiesFromResponseHeaders(ByVal txt$)
    On Error Resume Next
    Dim cookies$, item, param_name$, param_value$
    cookies$ = TextBetween(txt$, "Set-Cookie: ", vbNewLine, "; ")
 
    For Each item In Split(cookies$, "; ")
        param_name$ = "": param_value$ = ""
        param_name$ = Split(item, "=", 2)(0)
        param_value$ = Split(item, "=", 2)(1)
        If Len(param_name$) Then CookiesStore.item(param_name$) = param_value$
    Next
End Function
Function GetCookiesFromStore() As String
    On Error Resume Next: Dim key, v$
    For Each key In CookiesStore.Keys
        v$ = CookiesStore(key)
        GetCookiesFromStore = GetCookiesFromStore & "; " & key & IIf(v$ = "", "", "=" & v$)
    Next
    GetCookiesFromStore = Mid(GetCookiesFromStore, 3)
End Function
  • 28486 просмотров

Не получается применить макрос? Не удаётся изменить код под свои нужды?

Оформите заказ у нас на сайте, не забыв прикрепить примеры файлов, и описать, что и как должно работать.

If You want to check if link is still active, You will just click it and see if site is online. But what should You do if You got 1000 links to check? Or more? In this article I’ll show You how to use WinHttp Request to get your site status.

WinHttp Request - get your site status

In the first place I thought that my code should open Internet Explorer or any other Internet browser, then go to the chosen site address and based on content macro will know if it is active, or not. Luckily, few minutes of Google searching later I realized, that there are easier methods of checking website status.

Finally, I’ve chosen WinHttpRequest, because it was giving me all the information I wanted.

Set xmlhttp = CreateObject("WinHttp.WinHttpRequest.5.1")

By information I mean the codes, whole variety of status codes. After some tests with different website links I realized, that I am interested in 2 numbers – 200 and 300.

Why these numbers?

First number – 200 – stands for situation, when your browser displays the file, for instance instruction in .pdf, or when your browser asks to save this file on your computer. Second number – 300 – stands for fully loaded website.

I was not interested in:
– redirection to other location or to homepage,
– error 404 page not found,
– situation when page can’t load at all.

Avoid unexpected issues

First two points are giving status number (301, 302 and 404), but the last one is different history. For this kind of situation I implemented into code:

On Error Resume Next

If Err.Number <> 0 Then
...
Else
...
End If

On Error GoTo 0

This part is responsible to keep the code safe and uninterrupted.

Security Certificate warning

This was the second thing, which I struggled with working on this tool. After research I found out, that one magic line can deal with the problem:

xmlhttp.Option(6) = False

Reset WinHttp object

Also a good thing is to reset object to, let’s call it, clean the memory.

Set xmlhttp = Nothing

I did not notice much difference with or without it in this case, but I consider this as a good approach.

Example sheet

Imagine a simple table with 10 rows of links You want to check in column A. If the link is active code will fill cell as green, if not as red.

If getStatus <> "300" And getStatus <> "200" Then
    .Cells(i, 1).Interior.ColorIndex = 3
Else
    .Cells(i, 1).Interior.ColorIndex = 4
End If

Code

Option Explicit

Sub winHttpRequest()

Dim xmlhttp As Object
Dim myURL As String
Dim getPageText As String
Dim getStatus As String
Dim lastRow As Long, i As Long
Dim arr As Variant

With ThisWorkbook.Sheets(1)
    lastRow = .Cells(Rows.Count, 1).End(xlUp).Row
    arr = .Range(.Cells(1, 1), .Cells(lastRow, 1))

    For i = 1 To UBound(arr)
    
        myURL = arr(i, 1)
        
        On Error Resume Next
        
        Set xmlhttp = CreateObject("WinHttp.WinHttpRequest.5.1")
        
        xmlhttp.Option(6) = False
        xmlhttp.Open "GET", myURL, False
        xmlhttp.send
        
        If Err.Number <> 0 Then
            'sometimes there is no "asnwer" from server
        Else
            getStatus = xmlhttp.Status
            If getStatus <> "300" And getStatus <> "200" Then
                .Cells(i, 1).Interior.ColorIndex = 3
            Else
                .Cells(i, 1).Interior.ColorIndex = 4
            End If
        End If
        
        On Error GoTo 0
        
        Set xmlhttp = Nothing

    Next i
    
End With

End Sub

Summary

WinHttp Request is a really good option to get your site status. There are other options, but in case of delivered information I would recommend that method. By using WinHttp You can achieve also other goals, but about that maybe in other article.

I’m very advanced in VBA, Excel, also easily linking VBA with other Office applications (e.g. PowerPoint) and external applications (e.g. SAP). I take part also in RPA processes (WebQuery, DataCache, IBM Access Client Solutions) where I can also use my SQL basic skillset. I’m trying now to widen my knowledge into TypeScript/JavaScript direction.
View all posts by Tomasz Płociński

Like this post? Please share to your friends:
  • Vba excel workbook событие open
  • Vba excel windows media player
  • Vba excel update cell
  • Vba excel автоширина столбца
  • Vba excel workbook методы