Get image src by class name in VBA - vba

i am trying to get url of large image from a page
<ul id="etalage">
<li class=" product-image-thumbs" >
<img class="etalage_source_image_large" src="http://website.com/media/1200x1200/16235_1.jpg" title="" />
<img class="etalage_source_image_small" src="http://website.com/media/450x450/16235_1.jpg" title="" />
</li>
</ul>
my vba code is
Public Sub macro1()
Dim ie As Object
Dim name As String
Do Until IsEmpty(ActiveCell)
ActiveCell.Offset(0, 1).Value = "RUNNING"
URL = Selection.Value
Set ie = CreateObject("InternetExplorer.Application")
With ie
.Visible = 1
.navigate URL
While .Busy Or .readyState <> 4
DoEvents
Wend
End With
Dim Doc As HTMLDocument
Set Doc = ie.document
ActiveCell.Offset(0, 1).Value = "ERROR"
name = Trim(Doc.getElementsByClassName("product-image-thumbs")(0).innerText)
ActiveCell.Offset(0, 2).Value = name
ActiveCell.Offset(0, 1).Value = "successful"
ActiveCell.Offset(1, 0).Select
ie.Quit
Loop
End Sub
my code giving blank cell...
also please suggest me how to run this macro faster.... i have 3000 url to work on.
Thanks in advance

According to the comments, try to speed the code up this way (untested code). The inner-text of the li element is empty string becasue there is no text inside of it, there is an image element but no text. HTH
Public Sub macro1()
Dim ie As Object
Dim name As String
Dim Doc As HTMLDocument
Set ie = CreateObject("InternetExplorer.Application")
ie.Visible = 1
Do Until IsEmpty(ActiveCell)
ActiveCell.Offset(0, 1).Value = "RUNNING"
url = Selection.Value
ie.navigate url
While ie.Busy Or ie.readyState <> 4
DoEvents
Wend
Set Doc = ie.document
ActiveCell.Offset(0, 1).Value = "ERROR"
name = Trim(Doc.getElementsByClassName("product-image-thumbs")(0).innerText)
ActiveCell.Offset(0, 2).Value = name
ActiveCell.Offset(0, 1).Value = "successful"
ActiveCell.Offset(1, 0).Select
Loop
ie.Quit
End Sub
To get the src of all the images try using querySelectorAll method.
Dim img, imgs As IHTMLDOMChildrenCollection, i
Set imgs = Doc.querySelectorAll("li[class~='product-image-thumbs']>img")
For i = 0 To imgs.Length - 1
Set img = imgs.item(i)
Debug.Print img.getAttribute("src")
Next
See CSS attribute selectors.
EDIT:
If there are more img elements inside if the li.product-image-thumbs element then you have more possibilities how to get the right one img.
Get img which is placed immediately after the li :
"li[class~='product-image-thumbs']+img"
Get img inside of li by class name :
"li[class~='product-image-thumbs'] img[class~='etalage_source_image_small']"

Related

IE Automation - VBA Error - Runtime Error 70: Permission Denied

Friends, I'm very new to VBA and here I'm trying to scrape data from an internal website. The process goes like this: There are few serial numbers entered in the column A3 to End. The macro is supposed to navigate to the URL --> pick the serial number from excel --> Enter in the Search Field and Click Search. Once the result is populated on the page, it scrapes specific values and populates in the excel sheet.
The page opens up well, data is picked from excel and when the macro is reading the table cells it gives Runtime 70 Error. Below is my code for reference. Any help to fix is much appreciated.
Sub Type1_Data()
Dim ie As InternetExplorer
Dim html As MSHTML.HTMLDocument
Dim RowNumber, ColumnNumber As Long
RowNumber = 3
ColumnNumber = 0
Dim i As Long
Dim HTMLDoc As MSHTML.HTMLDocument
Dim Filt As MSHTML.IHTMLElement
Dim mtbl As MSHTML.IHTMLElement
Dim strempid As MSHTML.HTMLElementCollection
Dim strempid1 As MSHTML.HTMLElementCollection
Dim strempid2 As MSHTML.HTMLElementCollection
Dim strempid3 As MSHTML.HTMLElementCollection
Dim strempid4 As MSHTML.HTMLElementCollection
Dim strempid5 As MSHTML.HTMLElementCollection
Dim strempid6 As MSHTML.HTMLElementCollection
Set ie = New InternetExplorer
ie.Visible = False
ie.navigate ("URL")
Do While ie.READYSTATE = 4: DoEvents: Loop
Do Until ie.READYSTATE = 4: DoEvents: Loop
Set HTMLDoc = ie.document
xy:
If HTMLDoc.Title <> "Marketplace | Find a professional" Then
ie.Visible = True
GoTo xy
End If
ie.Visible = True
ThisWorkbook.Activate
Dim Ed As Integer
Ed = 3
While ThisWorkbook.Sheets("ProM Search").Cells(Ed, 1).Value <> 0
Ed = Ed + 1
Wend
Ed = Ed - 1
For i = 3 To Ed
Application.ScreenUpdating = True
Set UID = HTMLDoc.getElementById("navSelect")
Set Filt = HTMLDoc.getElementById("searchText")
Set mtbl = HTMLDoc.getElementsByTagName("Table")(23)
Application.Wait DateAdd("s", 1, Now)
HTMLDoc.getElementById("NLQTextArea").Value = ThisWorkbook.Sheets("ProM Search").Cells(i, 1).Value
HTMLDoc.getElementById("submitAction").Click
Set strempid = mtbl.getElementsByClassName("dojoxGridCell")(1)
Set strempid1 = mtbl.getElementsByClassName("dojoxGridCell")(2)
Set strempid2 = mtbl.getElementsByClassName("dojoxGridCell")(3)
Set strempid3 = mtbl.getElementsByClassName("dojoxGridCell")(7)
Set strempid4 = mtbl.getElementsByClassName("dojoxGridCell")(9)
Set strempid5 = mtbl.getElementsByClassName("dojoxGridCell")(11)
Set strempid6 = mtbl.getElementsByClassName("dojoxGridCell")(12)
ActiveCell.Offset(0, 1).Activate
ActiveCell.Value = strempid.innerText
ActiveCell.Offset(0, 1).Activate
ActiveCell.Value = strempid1.innerText
ActiveCell.Offset(0, 1).Activate
ActiveCell.Value = strempid2.innerText
ActiveCell.Offset(0, 1).Activate
ActiveCell.Value = strempid3.innerText
ActiveCell.Offset(0, 1).Activate
ActiveCell.Value = strempid4.innerText
ActiveCell.Offset(0, 1).Activate
ActiveCell.Value = strempid5.innerText
ActiveCell.Offset(0, 1).Activate
ActiveCell.Value = strempid6.innerText
ActiveCell.Offset(1, -7).Activate
DoEvents
If ActiveCell.Value = "" Then
MsgBox "Fetching Completed Successfully", vbExclamation, "ProM - Open Seat Search T2"
GoTo qt
End If
Next
qt:
ie.Quit
Set ie = Nothing
Set HTMLDoc = Nothing
End Sub
HTMLDoc.getElementById("submitAction").Click may cause a page refresh making any referenced elements become stale. Try working always of ie.document rather than setting into a variable when performing actions likely/known to cause page refresh/update. This is a common cause of a permission denied error.
Your If End If should probably be a loop with time out. You only need the one ie.visible = True. You rarely gain from setting Visible to false in my opinion. If you intend to hide it from a user you should do so from the start unless it interferes with functionality.
No point for Application.ScreenUpdating = True as it is never switched off within this sub. If this sub is called then you only need it once outside the loop. Your repeated ActiveCell.Offset(0, 1).Activate can just use a loop with Select Case and set the value direct without activate. Repeating the line Do While ie.READYSTATE = 4: DoEvents: Loop serves no purpose.
You could use Find method of range to determine the row in column 1 where 0 occurs rather than walking down the column. And tests to determine it is found and >=3.
This error means an attempt was made to write to a write-protected disk or to access a locked file. You could check if special permission is needed to access the worksheet. For detailed causes and solutions, you can refer to this doc.
Besides, you can also refer to my working sample about reading the cell value in VBA:
Sub LOADIE()
Set ieA = CreateObject("InternetExplorer.Application")
ieA.Visible = True
ieA.navigate "https://www.bing.com"
Do Until ieA.readyState = 4
DoEvents
Loop
Set doc = ieA.Document
Dim tempStr As String
tempStr = "sb_form_q"
doc.getElementById(tempStr).Value = ThisWorkbook.Sheets("SheetName").Range("E2").Value
End Sub

excel vba to send mail from excel sheet

i am trying to send mails from excel sheet, my vba is not working
error i am getting is "object doesn't suppoer this property or method" for all getelement statement.
I have data in excel sheet like recieptent, subject, message.
code i am using is,
Sub Macro2()
Do Until IsEmpty(ActiveCell)
URL = Selection.Value 'https://mail.google.com/mail/u/0/?ui=2&view=cm&fs=1&tf=1
Set ie = CreateObject("InternetExplorer.Application")
With ie
.Visible = 1
.navigate URL
While .Busy Or .readyState <> 4
DoEvents
Wend
End With
Dim Doc As HTMLDocument
Set Doc = ie.document
ie.document.getElementByName(":oa").Value = ActiveCell.Offset(0, 1).Value 'reciever_mail_id
ie.document.getElementById(":op").Value = ActiveCell.Offset(0, 2).Value 'subject
ie.document.getElementById(":nq").Value = ActiveCell.Offset(0, 3).Value 'message
ie.document.getElementById(":p0").Click 'submit button
ActiveCell.Offset(0, 4).Value = "mail sent"
ActiveCell.Offset(1, 0).Select
ie.Quit
Loop
End Sub
*my gmail id is already logged in, so no need to sign in.
**i am beginner in VBA, need help from expert.
GetElementByName does not exist.
You want to use GetElementsByName which will return an HTMLCollection rather than a simple HTMLElement.
So if there is only one element with that name write this : ie.document.getElementsByName(":oa")(0).Value

using getElementByClassName in VBA

I am using this code to get product name from a page
code of page is
<div class="product-shop col-sm-7">
<div class="product-name">
<h1 >Claro Glass 1.5 L Rectangular Air Tight Food Container with Lid- Clear GMA0215A</h1>
</div>
my vba code is
Public Sub GetValueFromBrowser()
Dim ie As Object
Dim name As String
Do Until IsEmpty(ActiveCell)
ActiveCell.Offset(0, 1).Value = "RUNNING"
URL = Selection.Value
Set ie = CreateObject("InternetExplorer.Application")
With ie
.Visible = 0
.navigate URL
While .Busy Or .readyState <> 4
DoEvents
Wend
End With
Dim Doc As HTMLDocument
Set Doc = ie.document
ActiveCell.Offset(0, 1).Value = "ERROR"
name = Trim(Doc.getElementByClassName("product-name").innerText)
ActiveCell.Offset(0, 1).Value = name
ie.Quit
Loop
End Sub
error i am getting is
run-time error '438':
Object doesn't support this property or method
GetElementsByClassName method
You are missing an s in the name of the method getElementsByClassName.
Change this name = Trim(Doc.getElementByClassName("product-name").innerText)
To this name = Trim(Doc.getElementsByClassName("product-name")(0).innerText). Substitude the (0) for the item you are targeting.
It is still possible to define your own function getElementByClassName.
This function returns the very first element with given class name in the DOM document and Nothing when no element with this class name exist in the DOM document.
Public Function getElementByClassName(doc As MSHTML.HTMLDocument, className As String) As IHTMLElement
Set getElementByClassName = doc.querySelector("[class='" & className & "']")
End Function
Usage:
Dim elm As IHTMLElement
Set elm = getElementByClassName(doc, "product-name")
If Not elm Is Nothing Then
Debug.Print elm.innerText
End If

Unable to extract table from webpage to excel using VBA (which does not have "ID" tag)

I am trying to get a data which is in a form of table in a webpage to my excel file using VBA, actually i am successful in opening and log in and navigate to table area but i am unable to copy the table date in the excel file !! The Reason being it does not have "ID" or "Name" tag assigned to it, It has only "Class" property
Below is the source code of the table from the webpage
<table cellspacing="0" cellpadding="0" class="grid" style="width: 930px;">
Also, I cannot use web query as the webpage has user name and password for login
Using online reference i tried few code below are the same i tried !!!
Set IE = CreateObject("InternetExplorer.application")
IE.Visible = True
IE.navigate ThisWorkbook.Sheets("Sheet4").Range("Link")
Do Until Not IE.busy: DoEvents: Loop
Set doc = IE.document
Do While doc.ReadyState <> "complete": DoEvents: Loop
IE.document.all("new_username").Value = ThisWorkbook.Sheets("Sheet4").Range("User")
IE.document.all("new_password").Value = ThisWorkbook.Sheets("Sheet4").Range("Pass")
IE.document.all("ok").Click
Do While doc.ReadyState <> "complete": DoEvents: Loop
Set ElementCol = IE.document.getElementsByTagName("a")
For Each link In ElementCol
If link.innerHTML = "Gateway transactions" Then
link.Click
End If
Next
Application.Wait (Now + TimeValue("0:00:04"))
IE.document.getelementsbyname("new_store_id").Item(1).Value = ThisWorkbook.Sheets("Sheet4").Range("MID")
IE.document.getelementsbyname("new_tsrch_from_d").Item(0).Value = ThisWorkbook.Sheets("Sheet4").Range("Fromdate")
IE.document.getelementsbyname("new_tsrch_from_m").Item(0).Value = ThisWorkbook.Sheets("Sheet4").Range("Frommon")
IE.document.getelementsbyname("new_tsrch_from_y").Item(0).Value = ThisWorkbook.Sheets("Sheet4").Range("Fromyear")
IE.document.getelementsbyname("new_tsrch_to_d").Item(0).Value = ThisWorkbook.Sheets("Sheet4").Range("Todate")
IE.document.getelementsbyname("new_tsrch_to_m").Item(0).Value = ThisWorkbook.Sheets("Sheet4").Range("Tomon")
IE.document.getelementsbyname("new_tsrch_to_y").Item(0).Value = ThisWorkbook.Sheets("Sheet4").Range("ToYear")
IE.document.getelementsbyname("new_tsrch_type").Item(0).Value = "15"
Application.Wait (Now + TimeValue("0:00:02"))
Set tags = IE.document.getElementsByTagName("input")
For Each tagx In tags
If tagx.Name = "ok" Then
tagx.Click
Exit For
End If
Next
Set doc = IE.document 'From here the code starts for extracting table
Set tbl = doc.getelementsbyclassname("grid")
GetTableData tbl, Sheet1.Range("A1")
End Sub
Sub GetTableData(ByRef tbl, rng As Range)
Dim cl As Object
Dim rw As Object
Dim I As Long
For Each rw In tbl.Rows ' In this line i am getting an error message "Run tine Error 438"Object Doesn't Support This Property or Method"
For Each cl In rw.Cells
rng.Value = cl.outerText
Set rng = rng.Offset(, 1)
Next cl
Set rng = rng.Parent.Cells(rng.Row + 1, 1)
Next rw
rng.Parent.Cells.WrapText = False
End SuB
I hope some one could help me !!! Thanks in advance !!!
Hi after a intense research, I found the answer, taught of posting it so someone would be benefited !! Actually the real thanks goes to "user2216436" and "Jonny" as they gave me the code in the below link How to read the nested table <td> values using VBA? I just edited to match my needs.. I really love this webpage !!!! It is awesome for beginners like me !!!!
You could also try copy pasting the table HTML to the sheet:
Dim clipboard As Object
Set clipboard = GetObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
clipboard.SetText doc.querySelector("table[class=grid]").outerHTML
clipboard.PutInClipboard
ThisWorkbook.Worksheets("Sheet1").Cells(1, 1).PasteSpecial

VBA to find text from webpages

I have created Macro which gives me all URLs present on any webpages.
We just need to provide the URL and it gives us the all links present in that webpage and paste it in one column
Private Sub CommandButton4_Click()
'We refer to an active copy of Internet Explorer
Dim ie As InternetExplorer
'code to refer to the HTML document returned
Dim html As HTMLDocument
Dim ElementCol As Object
Dim Link As Object
Dim erow As Long
Application.ScreenUpdating = False
'open Internet Explorer and go to website
Set ie = New InternetExplorer
ie.Visible = True
ie.navigate Cells(1, 1)
'Wait until IE is done loading page
Do While ie.READYSTATE <> READYSTATE_COMPLETE
Application.StatusBar = "Trying to go to website…"
DoEvents
Loop
Set html = ie.document
'Display text of HTML document returned in a cell
'Range("A1") = html.DocumentElement.innerHTML
Set ElementCol = html.getElementsByTagName("a")
For Each Link In ElementCol
erow = Worksheets("Sheet4").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
Cells(erow, 1).Value = Link
Cells(erow, 1).Columns.AutoFit
Next
'close down IE, reset status bar & turn on screenupdating
'Set ie = Nothing
Application.StatusBar = ""
Application.ScreenUpdating = True
ie.Quit
ActiveSheet.Range("$A$1:$A$2752").removeDuplicates Columns:=1, Header:=xlNo
End Sub
Now can anyone will help me to create macro to find particular text from all these URLs present in column and if that text is present then in next column it should print text "text found".
Example if we search text "New" then it should print text "Text found" in next column of the URL.
Thank you.
The key would be the function Instr, if it finds the string "New", it returns the position where it begins, otherwise it returns 0.
i=1
do until trim(Cells(i,1).Value) = vbNullString
if instr(Cells(i,1).Value,"New") then
Cells(i,2).value="Text found"
end if
i=i+1
loop
Similar to above.
Dim a As Variant
a = 2
While Cells(a, 1) <> "" And Cells(a + 1, 1) <> ""
If InStr(Cells(a, 1), "new") = 0 Then
Else
Cells(a, 2) = "Text Found"
End If
a = a + 1
Wend