Automated search in google - html

I have over 20,000 searches I need to do in google. I want to use VBA to do an automate search in google or internet explorer and return link to excel. I have tried multiple VBA formulas and none of them seem to work. Is there a formula that will do an automate search and return link to the first site on google search to excel? Below is the formula I am currently using, but it isn't working. I am searching addresses in column A and need link to be return to column B.
Sub XMLHTTP_Count()
Dim url As String, lastRow As Long
Dim XMLHTTP As Object, html As Object
Dim start_time As Date
Dim end_time As Date
lastRow = Range("A" & Rows.Count).End(xlUp).Row
Dim cookie As String
Dim result_cookie As String
start_time = Time
Debug.Print "start_time:" & start_time
For i = 2 To lastRow
url = "https://www.google.co.in/search?q=" & Cells(i, 1) & "&rnd=" & WorksheetFunction.RandBetween(1, 10000)
Set XMLHTTP = CreateObject("MSXML2.XMLHTTP")
XMLHTTP.Open "GET", url, False
XMLHTTP.setRequestHeader "Content-Type", "text/xml"
XMLHTTP.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:25.0) Gecko/20100101 Firefox/25.0"
XMLHTTP.send
Set html = CreateObject("htmlfile")
html.body.innerHTML = XMLHTTP.ResponseText
If html.getElementById("resultStats") Is Nothing Then
str_text = "0 Results"
Else
str_text = html.getElementById("resultStats").innerText
End If
Cells(i, 2) = str_text
DoEvents
Next
end_time = Time
Debug.Print "end_time:" & end_time
Debug.Print "done" & "Time taken : " & DateDiff("n", start_time, end_time)
MsgBox "done" & "Time taken : " & DateDiff("n", start_time, end_time)
End Sub

Well, you don't need the randomizer and it looks like the 'resultStats' changed to 'result-stats'. Try the code below and see if it does what you want.
Sub GetSearchStats()
Dim url As String, lastRow As Long
Dim XMLHTTP As Object, html As Object, objResultDiv As Object, objH3 As Object, link As Object
Dim start_time As Date
Dim end_time As Date
Dim var As String
Dim var1 As Object
lastRow = Range("A" & Rows.Count).End(xlUp).row
Dim cookie As String
Dim result_cookie As String
start_time = Time
Debug.Print "start_time:" & start_time
For i = 2 To lastRow
url = "https://www.google.com/search?q=" & Cells(i, 1)
Set XMLHTTP = CreateObject("MSXML2.serverXMLHTTP")
XMLHTTP.Open "GET", url, False
XMLHTTP.setRequestHeader "Content-Type", "text/xml"
XMLHTTP.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:25.0) Gecko/20100101 Firefox/25.0"
XMLHTTP.send
Set html = CreateObject("htmlfile")
html.body.innerHTML = XMLHTTP.ResponseText
Set objResultDiv = html.getElementById("rso")
Set var1 = html.getElementById("result-stats")
Cells(i, 2).Value = var1.innerText
DoEvents
Next
end_time = Time
Debug.Print "end_time:" & end_time
Debug.Print "done" & "Time taken : " & DateDiff("n", start_time, end_time)
MsgBox "done" & "Time taken : " & DateDiff("n", start_time, end_time)
End Sub
Result:

I think I answered your initial question. This sounds like a new question , and it probably warrants a new post, but I'll go ahead and offer a second answer here, to address this question.
Sub WebPage()
Dim internet As Object
Dim internetdata As Object
Dim div_result As Object
Dim header_links As Object
Dim link As Object
Dim URL As String
Set internet = CreateObject("InternetExplorer.Application")
internet.Visible = True
URL = "https://www.google.co.in/search?q=how+to+program+in+vba"
internet.Navigate URL
Do Until internet.ReadyState >= 4
DoEvents
Loop
Application.Wait Now + TimeSerial(0, 0, 5)
Set internetdata = internet.Document
Set div_result = internetdata.getelementbyid("res")
Set header_links = div_result.getelementsbytagname("h3")
For Each h In header_links
Set link = h.ChildNodes.Item(0)
Cells(Range("A" & Rows.Count).End(xlUp).Row + 1, 1) = link.href
Next
MsgBox "done"
End Sub
Result:
You can easily convert each text field to a hyperlink if you want to make thse all clickable links. Feel free to modify the code to suit your needs.

Related

Scraping data from website to Excel using a macro...lost

I am totally new to this but here is my scope.
I am running a macro to pull data from a business system.
After this info is pulled, I want a macro to take certain fields, put them into a website form, click submit and then scrape and paste certain data results back into excel.
Everything works minus the scraping and pasting back into excel.
Help please!
I have searched all over stack overflow and watched vids to try and figure out what I need to do but I must be misunderstanding something.
Sub Track()
Range("B2").Select
'This should call to PT and deliver tracking info
Dim IE As Object
Dim tbl As Object, td As Object
Set IE = CreateObject("InternetExplorer.Application") 'Set IEapp =
InternetExplorer
IE.Visible = True
IE.Navigate "https://www.partstown.com/track-my-order"
With IEapp
Do
DoEvents
Loop Until IE.readyState = 4
'Input PO and zip
Call IE.Document.getElementById("orderNo").SetAttribute("value",
"4500969111")
'ActiveCell.Offset(0, 2).Select
Call IE.Document.getElementById("postalCode").SetAttribute("value",
"37040")
IE.Document.forms(7).Submit
Application.Wait Now + TimeValue("00:00:09")
'this is where i am stuck. I know this isnt right but tried to piece it
together
Set elemCollection = IE.Document.getelElementsByTagname("table.account-
table details _tc_table_highlighted")
For t = 0 To (elemCollection.Length - 1)
For r = 0 To (elemCollection(t).Rows.Length - 1)
For c = 0 To (elemCollection(t).Rows(r).Cells.Length - 1)
ThisWorkbook.Worksheets(1).Cells(r + 1, c + 1) =
elemCollection(t).Rows.Cells(c).innertext
Next c
Next r
Next t
End With
End Sub
Here is what I want it to pull:
Shipping column
QTY ordered
QTY shipped Product
And to display in a linear fashion:
Shipping, QTY ordered, QTY shipped, Product
Internet Explorer:
I have made this a little more verbose than usual so you can see each step.
Key things:
1) proper page loads waits with While .Busy Or .readyState < 4: DoEvents: Wend
2) selecting elements by id where possible. The # is a css id selector. css selectors are applied by querySelector method of .document and retrieve the first element in the page which matches the specified pattern
3) a timed loop is needed to wait for results to be present
4) the order qty etc info is a newline divided string. It seemed easiest to split on these newlines and then access individual items from the resultant array by index
5) I order, per your specification, the results in an array and write that array out in one go to the sheet
6) The "." is a class selector in .order-history__item-descript--min i.e. return the first element with class of order-history__item-descript--min
7) The [x=y] is an attribute = value selector in [data-label=Shipping] i.e. return the first element with data-label attribute having value Shipping
8) The combination of .details-table a is using a descendant combinator, " ", to specify I want a tag elements that have a parent with class .details-table
VBA:
Option Explicit
'VBE > Tools > References:
' Microsoft Internet Controls
Public Sub RetrieveInfo()
Dim ie As InternetExplorer, ele As Object, t As Date
Const MAX_WAIT_SEC As Long = 5
Set ie = New InternetExplorer
With ie
.Visible = True
.Navigate2 "https://www.partstown.com/track-my-order"
While .Busy Or .readyState < 4: DoEvents: Wend
With .document
.querySelector("#orderNo").Value = "4500969111"
.querySelector("#postalCode").Value = "37040"
.querySelector("#orderLookUpForm").submit
End With
While .Busy Or .readyState < 4: DoEvents: Wend
Dim shipping As String, order As String, items() As String
With .document
t = Timer
Do
On Error Resume Next
Set ele = .querySelector("[data-label=Shipping]")
On Error GoTo 0
If Timer - t > MAX_WAIT_SEC Then Exit Do
Loop While ele Is Nothing
If ele Is Nothing Then Exit Sub
shipping = ele.innerText
order = .querySelector(".order-history__item-descript--min").innerText
items = Split(order, vbNewLine)
Dim qtyOrdered As Long, qtyShipped As String, product As String
qtyOrdered = CLng(Replace$(items(0), "Qty Ordered: ", vbNullString))
qtyShipped = CLng(Replace$(items(1), "Qty Shipped: ", vbNullString))
product = .querySelector(".details-table a").Title
Dim results()
results = Array(shipping, qtyOrdered, qtyShipped, product)
ThisWorkbook.Worksheets("Sheet1").Cells(1, 1).Resize(1, UBound(results) + 1) = results
End With
.Quit
End With
End Sub
If new to HTML please look at:
https://developer.mozilla.org/en-US/docs/Web/HTML
If new to css selectors please look at:
https://flukeout.github.io/
XMLHTTP:
The whole thing can also be done with XHR. This is much faster than opening a browser.
XHR:
Use XMLHttpRequest (XHR) objects to interact with servers. You can
retrieve data from a URL without having to do a full page [render]
In this case I do an initial GET request to the landing page to retrieve the
CSRFToken to use in my re-enactment of the POST request the page makes to the server when you manually input data and press submit. You get the data you want in the server response. I pass a query string in the body of the POST send line
.send "orderNo=4500969111&postalCode=37040&CSRFToken=" & csrft ; you can see your parameters there.
Option Explicit
Public Sub GetInfo()
Dim html As HTMLDocument, csrft As String '< VBE > Tools > References > Microsoft HTML Object Library
Set html = New HTMLDocument
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", "https://www.partstown.com", False
.send
html.body.innerHTML = .responseText
csrft = html.querySelector("[name=CSRFToken]").Value
.Open "POST", "https://www.partstown.com/track-my-order", False
.setRequestHeader "Referer", "https://www.partstown.com/track-my-order"
.setRequestHeader "User-Agent", "Mozilla/5.0"
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.setRequestHeader "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
.setRequestHeader "Accept-Encoding", "gzip, deflate"
.setRequestHeader "Accept-Language", "en-US,en;q=0.9"
.send "orderNo=4500969111&postalCode=37040&CSRFToken=" & csrft
html.body.innerHTML = .responseText
End With
Dim shipping As String, order As String, items() As String
shipping = html.querySelector("[data-label=Shipping]").innerText
order = html.querySelector(".order-history__item-descript--min").innerText
items = Split(order, vbNewLine)
Dim qtyOrdered As Long, qtyShipped As String, product As String
qtyOrdered = CLng(Replace$(items(0), "Qty Ordered: ", vbNullString))
qtyShipped = CLng(Replace$(items(1), "Qty Shipped: ", vbNullString))
product = html.querySelector(".details-table a").Title
Dim results()
results = Array(shipping, qtyOrdered, qtyShipped, product)
ThisWorkbook.Worksheets("Sheet1").Cells(1, 1).Resize(1, UBound(results) + 1) = results
End Sub
Example of loop:
Option Explicit
Public Sub GetInfo()
Dim html As HTMLDocument, csrft As String, lastRow As Long, sourceValues() '< VBE > Tools > References > Microsoft HTML Object Library
Set html = New HTMLDocument
Dim ws As Worksheet, i As Long
Set ws = ThisWorkbook.Worksheets("Sheet4")
lastRow = ws.Cells(ws.rows.Count, "B").End(xlUp).Row
sourceValues = ws.Range("B2:D" & lastRow).Value
Dim results()
ReDim results(1 To UBound(sourceValues, 1), 1 To 4)
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", "https://www.partstown.com", False
.send
html.body.innerHTML = .responseText
csrft = html.querySelector("[name=CSRFToken]").Value
Stop
For i = LBound(sourceValues, 1) To UBound(sourceValues, 1)
If sourceValues(i, 1) <> vbNullString And sourceValues(i, 3) <> vbNullString Then
DoEvents
.Open "POST", "https://www.partstown.com/track-my-order", False
.setRequestHeader "Referer", "https://www.partstown.com/track-my-order"
.setRequestHeader "User-Agent", "Mozilla/5.0"
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.setRequestHeader "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
.setRequestHeader "Accept-Encoding", "gzip, deflate"
.setRequestHeader "Accept-Language", "en-US,en;q=0.9"
.send "orderNo=" & sourceValues(i, 1) & "&postalCode=" & sourceValues(i, 3) & "&CSRFToken=" & csrft
html.body.innerHTML = .responseText
Dim shipping As String, order As String, items() As String
shipping = html.querySelector("[data-label=Shipping]").innerText
order = html.querySelector(".order-history__item-descript--min").innerText
items = Split(order, vbNewLine)
Dim qtyOrdered As Long, qtyShipped As String, product As String
qtyOrdered = CLng(Replace$(items(0), "Qty Ordered: ", vbNullString))
qtyShipped = CLng(Replace$(items(1), "Qty Shipped: ", vbNullString))
product = html.querySelector(".details-table a").Title
results(i, 1) = shipping
results(i, 2) = qtyOrdered
results(i, 3) = qtyShipped
results(i, 4) = product
End If
'Application.Wait Now + TimeSerial(0, 0, 1)
Next
End With
'results written out from row 2 column E
ws.Cells(2, 5).Resize(UBound(results, 1), UBound(results, 2)) = results
End Sub

How to trigger webpage to update, with FireEvent "Onchange", when choosing from dropdown in Internet Explorer?

I am creating a macro to grab Fax Numbers from a public banking website.
I have written enough code to get to the site, select from a dropdown list, and change the selection in the dropdown list. However when I use FireEvent ("onChange"), it does not trigger the webpage to update.
I have searched for an answer, but have not found any.
Website: https://www.atb.com/contact-us/Pages/branch-locator.aspx
Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)
Sub test()
Dim ieExplorer As New InternetExplorerMedium
Dim ieField As Object
Dim ieSubmit As Object
Dim ieSelect As Object
Dim iebutton As Object
Dim buttCounter As Integer
Dim objOption As Object
Dim objCount As Integer
Dim ieForm As Object
Dim intRow As Long, faxNum As String
intRow = 2
With ieExplorer
.Visible = True
.Navigate "https://www.atb.com/contact-us/Pages/branch-locator.aspx"
Sleep 1000
Sleep 1000
Sleep 1000
Sleep 1000
Sleep 1000
Sleep 1000
Sleep 1000
Set ieSelect = .Document.getElementsByTagName("select")
Do While o < ieSelect.Length
If ieSelect(o).ID = "ba" Then
For Each i In ieSelect(o).Options
If i.Value <> "null" Then
ieSelect(o).Focus
i.Selected = True
ieSelect(o).FireEvent "onchange"
Set ieField = .Document.getElementsByTagName("p")
Do While x < ieField.Length
If InStr(ieField(x).innertext, "FAX") Then
Cells(intRow, "A").Value = i.Value
Cells(intRow, "B").Value = ieField(x).innertext
intRow = intRow + 1
End If
Loop
End If
Next
End If
o = o + 1
Loop
End With
End Sub
I would use XMLHTTP/WinHttp POST request and grab the xml and then parse that. You could adapt as a function. I would prefer to grab all the fax numbers in one go and write out to sheet. I use xpath to retrieve the title (name of branch) and the fax numbers.
You could adapt the xpath syntax to retrieve any of the listed values. E.g row returned from which you could select values:
<z:row ows_ID='1' ows_Title='Acadia Valley' ows_Transit='1.00000000000000' ows_Classification='Agency' ows_Address='Acadia Valley' ows_City='Acadia Valley' ows_Postal='T0J 0A0' ows_Phone='(403) 972-3805' ows_Fax='(403) 972-2263' ows_Hours='Mon-Fri 9:00-12:30, 13:30-16:00' ows_LAT='51.159888' ows_LONG='-110.209308' ows__ModerationStatus='0' ows__Level='1' ows_UniqueId='1;#{2973F9AC-2019-4BD1-A740-41A270BAC267}' ows_owshiddenversion='3' ows_FSObjType='1;#0' ows_Created='2015-11-18 13:58:48' ows_PermMask='0x1000030041' ows_Modified='2016-02-08 11:16:05' ows_FileRef='1;#Lists/Branches/1_.000' ows_MetaInfo='1;#' />
VBA:
Option Explicit
Public Sub GetFaxNumbers()
Dim body As String, xmlDoc As Object, request As Object
Application.ScreenUpdating = False
Set xmlDoc = CreateObject("MSXML2.DOMDocument") 'New MSXML2.DOMDocument60
body = "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:soap='http://schemas.microsoft.com/sharepoint/soap/'>"
body = body & "<soapenv:Body><GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'><listName>Branches</listName>"
body = body & "<viewFields><ViewFields><FieldRef Name='ID' /><FieldRef Name='Title' /><FieldRef Name='Transit' />"
body = body & "<FieldRef Name='Classification' /><FieldRef Name='Address' /><FieldRef Name='City' /><FieldRef Name='Postal' />"
body = body & "<FieldRef Name='Phone' /><FieldRef Name='Fax' /><FieldRef Name='Hours' /><FieldRef Name='LAT' /><FieldRef Name='LONG' />"
body = body & "</ViewFields></viewFields><rowLimit>0</rowLimit><query><Query><OrderBy><FieldRef Name='Title' Ascending='True' />"
body = body & "</OrderBy></Query></query></GetListItems></soapenv:Body></soapenv:Envelope>"
Set request = CreateObject("WinHttp.WinHttpRequest.5.1")
With request
.Open "POST", "https://www.atb.com/_vti_bin/lists.asmx", False
.setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"
.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36"
.setRequestHeader "Content-Type", "text/xml"
.send body
With xmlDoc
.validateOnParse = True
.setProperty "SelectionLanguage", "XPath"
.async = False
If Not .LoadXML(request.responseText) Then
Err.Raise .parseError.ErrorCode, , .parseError.reason
End If
End With
End With
Dim elements As Object, counter As Long, rowNum As Long
Set elements = xmlDoc.SelectNodes("//#ows_Title | //#ows_Fax")
rowNum = 1
For counter = 0 To elements.Length - 1 Step 2
With ThisWorkbook.Worksheets("Sheet1")
.Cells(rowNum, 1) = elements(counter).Text
.Cells(rowNum, 2) = elements(counter + 1).Text
End With
rowNum = rowNum + 1
Next
Application.ScreenUpdating = True
End Sub
Sample of results:
Looks like the select change is set up by this code:
$('body').find('#ba').change(function(){
var a = $(this).val();
lookyloo(a);
});
You should be able to call lookyloo using ExecScript and pass in the value
Eg:
How to find and call javascript method from vba
Tested:
Dim ie As InternetExplorer, el
Set ie = New InternetExplorerMedium
ie.Visible = True
ie.navigate "https://www.atb.com/contact-us/Pages/branch-locator.aspx"
Set el = ie.document.getElementById("ba") 'I put a break here while the page loaded...
el.selectedIndex = 5 'for example
ie.document.parentWindow.Window.execScript "lookyloo('" & el.Value & "');"
I had a similar issue and got it to work by changing "onchange" to ("onchange").

VBA Data Import from Google into Excel: Custom Time Ranges

For a VBA application in Excel, I am trying to include the "custom time range" function Google offers when narrowing down the search. So far, I am using the following code (see below), which allows to import "resultStats" from Google for a given search term into Excel but lacks the time range option.
In this specific case, I would need to determine the number of results/articles e.g. for "Elon Musk" between 01/01/2015 and 12/31/2015. Is there any practicable addition to the code below? And can this also be applied for the Google News tab instead of the regular Google Search results?
Many thanks in advance!
Sub Gethits()
Dim url As String, lastRow As Long
Dim XMLHTTP As Object, html As Object, objResultDiv As Object, objH3 As Object, link As Object
Dim start_time As Date
Dim end_time As Date
Dim var As String
Dim var1 As Object
lastRow = Range("A" & Rows.Count).End(xlUp).Row
Dim cookie As String
Dim result_cookie As String
start_time = Time
Debug.Print "start_time:" & start_time
For i = 2 To lastRow
url = "https://www.google.com/search?q=" & Cells(i, 1) & "&rnd=" & WorksheetFunction.RandBetween(1, 10000)
Set XMLHTTP = CreateObject("MSXML2.serverXMLHTTP")
XMLHTTP.Open "GET", url, False
XMLHTTP.setRequestHeader "Content-Type", "text/xml"
XMLHTTP.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:25.0) Gecko/20100101 Firefox/25.0"
XMLHTTP.send
Set html = CreateObject("htmlfile")
html.body.innerHTML = XMLHTTP.responseText
Set objResultDiv = html.getElementById("rso")
Set var1 = html.getElementById("resultStats")
Cells(i, 2).Value = var1.innerText
DoEvents
Next
end_time = Time
Debug.Print "end_time:" & end_time
Debug.Print "done" & "Time taken : " & DateDiff("n", start_time, end_time)
MsgBox "done" & "Time taken : " & DateDiff("n", start_time, end_time)
End Sub
It seems you need URL encoding so a string as shown below works when you include your cd_max and cd_min parameters. You specify news with the parameter tbm=nws.
As #chillin mentions you can achieve encoding of parameters with Application.Encodeurl().
I also tried the API method but with limited success. Though the dataRange filter can be passed in the sort parameter, you need to register for an API key , set up a custom search engine and set your requirements. Results are max 10 per query; there is an API call limit for free calls. You can specify a start number to get blocks of 10. You can also see what is URL encoded by running through the Google APIs explorer - custom search. I found it only returned 2 results which was clearly not in the region of the expected number.
Option Explicit
Public Sub GetResultCount()
Dim sResponse As String, html As HTMLDocument
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", "https://www.google.co.uk/search?q=elon+musk&safe=strict&biw=1163&bih=571&source=lnt&tbs=cdr%3A1%2Ccd_min%3A1%2F1%2F2015%2Ccd_max%3A12%2F31%2F2015&tbm=nws", False
.setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"
.send
sResponse = StrConv(.responseBody, vbUnicode)
End With
Set html = New HTMLDocument
With html
.body.innerHTML = sResponse
Debug.Print .querySelector("#resultStats").innerText
End With
End Sub
Thanks for your feedback. I have now amended the URL line as follows (including the Excel ENCODEURL function, which I applied directly for the input cells of the Excel spreadsheet) and it works perfectly:
url = "https://www.google.com/search?q=" & Cells(i, 1) & "&source=lnt&tbs=cdr%3A1%2Ccd_min%3A" & Cells(i, 2) & "%2Ccd_max%3A" & Cells(i, 3) & "&tbm=nws"

How to download pdf from a hyperlink requiring login information in outlook by VBA

I use outlook to receive my emails(cannot change this...), I want to find a way in windows to automatically process one kind of my emails which have download links.
I want to find a way to selectively download files from the emails with key words.
The procedures I can think of to achieve this is:
search my emails with key words
find the hyperlink in the emails with the key words
download the files and save them in a folder.
My current code is :
Sub Search_Inbox()
Dim olFolder As Outlook.Folder
Dim myitems As Outlook.Items
Dim bodyString As String
Dim bodyStringLines
Dim splitLine
Dim hyperlink As String
Dim i As Integer
Dim found As Integer
Set olFolder = Application.GetNamespace("MAPI").Folders("lll#163.com").Folders("Inbox").Folders("abc")
Set myitems = olFolder.Items
i = 0
found = 0
'find the hyperlink in the emails"
For Each myitem In myitems
If InStr(1, myitem.Body, "passed", vbTextCompare) > 0 Then
If InStr(1, myitem.Body, "tested", vbTextCompare) > 0 Then
'inside the target email, search for the key word
bodyString = myitem.Body
bodyStringLines = Split(bodyString, vbCrLf)
For Each splitLine In bodyStringLines
i = i + 1
keyStart = InStr(splitLine, "keyword")
keyEnd = keyStart + Len("keyword") - 1
If found = 0 Then
If keyStart > 0 Then
If keyEnd = Len(splitLine) Then
found = 1
End If
End If
Else
hyperlink = splitLine
found = 0
Exit For
End If
Next
Debug.Print "hyperlink is"
Debug.Print hyperlink
'DownloadFile1 (hyperlink)
'DownloadFile2 (hyperlink)
End If
Else
Found = False
End If
Next
Set olFolder = Nothing
Set myitems = Nothing
End Sub
But I have a problem at the downloading part. The access to the hyperlink requires filling the login information. I tried the following two methods but failed...
Sub DownloadFile1(myURL As String)
Dim saveDirectoryPath As String
'*******************************
' Intitial setup
'*******************************
saveDirectoryPath = "C:\testfile.pdf" 'where your files will be stored
'*******************************
Dim fileNameArray() As String
Dim fileName As String
Dim arrayLength As Integer
Dim DateString As String
DateString = Format(Now, "yyyy-mm-dd hh-mm-ss")
fileNameArray = Split(myURL, "/")
arrayLength = UBound(fileNameArray)
fileName = fileNameArray(arrayLength)
'Add date to the file incase there are duplicates comment out these lines if you do not want the date added
fileName = Replace(fileName, ".pdf", "_" & DateString & ".pdf")
fileName = Replace(fileName, ".PDF", "_" & DateString & ".PDF")
Dim WinHttpReq As Object
Set WinHttpReq = CreateObject("Microsoft.XMLHTTP")
WinHttpReq.Open "GET", myURL, False, "username", "password"
WinHttpReq.Send
myURL = WinHttpReq.responseBody
If WinHttpReq.Status = 200 Then
Set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type = 1
oStream.Write WinHttpReq.responseBody
oStream.SaveToFile saveDirectoryPath & fileName, 2 ' 1 = no overwrite, 2 = overwrite
oStream.Close
End If
End Sub
I failed (Access is denied) in line :
WinHttpReq.Send
I also tried the following code.
Sub DownloadFile2(myURL As String)
Dim strCookie As String, strResponse As String, _
strUrl As String
Dim xobj As Object
Dim WinHttpReq As Object
Set xobj = New WinHttp.WinHttpRequest
UN = "username"
PW = "password"
strUrl = "https://www.jedec.org/user/login"
xobj.Open "POST", strUrl, False
xobj.SetRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36"
xobj.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded"
xobj.Send "username=" & UN & "&password=" & PW & "&login=login"
strResponse = xobj.ResponseText
strUrl = myURL
xobj.Open "GET", strUrl, False
xobj.SetRequestHeader "Connection", "keep-alive"
xobj.SetRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36"
xobj.Send
strCookie = xobj.GetResponseHeader("Set-Cookie")
strResponse = xobj.ResponseBody
If xobj.Status = 200 Then
Set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type = 1
oStream.Write xobj.ResponseBody
oStream.SaveToFile "C:\testfile.pdf", 1
oStream.Close
End If
End Sub
2018/03/01 problem (solved ): User-defined type not defined, at line:
Set xobj = New WinHttp.WinHttpRequest
Solved: Here is a trick that you should include the reference of Microsoft WinHTTP Service.
2018/03/02 problem (unsolved): The URL does not use a recognized protocol, at line:
xobj.Open "GET", strUrl, False
Anyone has any ideas about how to fix this?
reference for extracting information from email body:
https://www.datanumen.com/blogs/extract-show-hyperlink-addresses-email-via-outlook-vba/
http://www.vbaexpress.com/forum/showthread.php?49021-Download-File-from-Hyperlink-in-Body-of-Emailhttp://www.vbaexpress.com/forum/showthread.php?49021-Download-File-from-Hyperlink-in-Body-of-Email
reference for downloading file from hyperlink which requires login info. :
How to download a PDF that is in a hyperlink using VB in Outlook 2016
Vba download file from internet WinHttpReq with login not working

Unable to fetch data which are in json format from a webpage

After running my vba script for the purpose of parsing data from a webpage I could see that it shows "object required" error. I can see the desired data in the msgbox which is set before the error causing line. As i haven't worked with json format yet, I can't make the execution successful. Any help would be appreciated. Here is what i'm up to:
Sub JsonData()
Dim http As New MSXML2.XMLHTTP60
Dim PostData As String, JSONa As Object, ele As Object
PostData = "region=US&latitude=61.7958256&longitude=-148.8045856&location=Sutton-Alpine%2C%20AK&source=US-STANDALONE&radius=25&pageNumber=1&pageSize=10&sortBy=&industryFilter=340&serviceFilter=550,90"
With http
.Open "GET", "https://proadvisorservice.intuit.com/v1/search?" & PostData, False
.setRequestHeader "Content-Type", "application/json; charset=utf-8"
.setRequestHeader "Accept", "application/json;version=1.1.0"
.send
Set JSONa = JsonConverter.ParseJson(.responseText)
End With
MsgBox http.responseText
For Each ele In JSONa
i = i + 1
Cells(i, 1).Value = ele("firstName")
Cells(i, 2).Value = ele("lastName")
Cells(i, 3).Value = ele("city")
Next ele
End Sub
The search results are VBA.Collection where each itemof this collection contains then another Scripting.Dictionary. Hope what you ask for is the following. HTH
Dim results As VBA.Collection
Set results = JSONa("searchResults")
Dim result As Scripting.Dictionary
For Each result In results
i = i + 1
Cells(i, 1).Value = result("firstName")
Cells(i, 2).Value = result("lastName")
Cells(i, 3).Value = result("city")
Next result