Undefined object defined issue - vba

I have done really good progress in my macros while getting the data in different URL's. with the code block below I am getting the error like "Undefined Object":
Sub GetData()
Dim IE As Object, doc As Object
Dim strURL As String, myDate As Date
Set IE = CreateObject("InternetExplorer.Application")
With IE
For myDate = CDate("01-05-2017") To CDate("05-05-2017")
strURL = "https://www.ukdogracing.net/racecards/" & Format(myDate, "dd-mm-yyyy") & "/monmore" ' Trim(Str(I))
.navigate strURL
Do Until .ReadyState = 4: DoEvents: Loop
Do While .Busy: DoEvents: Loop
Set doc = IE.Document
GetAllTables doc
Next myDate
.Quit
End With
End Sub
Sub GetAllTables(doc As Object)
Dim ws As Worksheet
Dim rng As Range
Dim tbl As Object
Dim rw As Object
Dim cl As Object
Dim tabno As Long
Dim nextrow As Long
Dim I As Long
Dim ThisLink As Object 'variable for <a> tags
Set ws = Worksheets.Add
For Each tbl In doc.getElementsByTagName("TABLE")
tabno = tabno + 1
nextrow = nextrow + 1
Set rng = ws.Range("B" & nextrow)
rng.Offset(, -1) = "Table " & tabno
For Each rw In tbl.Rows
For Each cl In rw.Cells
rng.Value = cl.outerText
Set rng = rng.Offset(, 1)
myDate = myDate + 1
Next cl
nextrow = nextrow + 1
Set rng = rng.Offset(1, -myDate)
myDate = 0
Next rw
Next tbl
myDate = Range("B" & Rows.Count).End(xlUp).Row 'last row with data
Do While Cells(myDate, 1).Value = "" 'will loop until first not blank found in column A (starting from last row of data, from end to start)
For Each ThisLink In doc.getElementsByTagName("a") 'we check all <a> tags
If ThisLink.innerText = Cells(myDate, 2).Value Then Cells(myDate, 1).Value = ThisLink.href 'If the innertext is the name of the race, in column A we add link
Next ThisLink
myDate = myDate - 1 'we decrease row position
Loop
End Sub
the issue is in line :
Do While Cells(myDate, 1).Value = ""
the aim of this line is that, continue to get the data from the links if the page has empty return. What is my mistake could you please help me? It is the last part of my work of macros. Thanks in advance.

I think the error you are experiencing may be to do with the value of myDate. It can't be zero.
If I do this:
Option Explicit
Sub TEST()
Dim myDate As Date
myDate = 1
Do While Cells(myDate, 1).Value = ""
myDate = myDate - 1
Loop
End Sub
I get the Object defined error. I avoid this with:
Option Explicit
Sub TEST()
Dim myDate As Date
myDate = 1
Do While Cells(myDate, 1).Value = ""
myDate = myDate - 1
If Int(myDate) = 0 Then Exit Do
Loop
End Sub

Related

Greyhound data import to excel macro formula

as part of a research project i need to extract as much data as possible from a webpage. The problem is to access each table i have to follow lots of links which I can't get to work automatically.
Its from a greyhound-data.com. So an example would be I want to extract all the racing stats for every dog that raced in swindon between 1st Jan 2017- 28th Feb 2018. When i put it in the search engine I get 57236 races in a table. I have to follow the link on name of race for each race..
http://www.greyhound-data.com/d?racename=&country=13000&startmonth=3&endmonth=2&startdate=2017&enddate=2018&maxdist=unlimitied&class=any&order=dateD&x=2
My biggest problem is I don't know how to say follow the various links. And I don't know how to loop multiple times - once for each of the races in the original list.
I have created the simple Macro query :
Sub GetData()
Dim IE As Object
Dim doc As Object
Dim strURL As String
Dim I As Integer
For I = 1 To 9
strURL = "http://www.greyhound-data.com/d?racename=&country=13000&startmonth=3&endmonth=2&startdate=2017&enddate=2018&maxdist=unlimitied&class=any&order=dateD&x=" + Trim(Str(I))
Set IE = CreateObject("InternetExplorer.Application")
With IE
.navigate strURL
Do Until .ReadyState = 4: DoEvents: Loop
Do While .Busy: DoEvents: Loop
Set doc = IE.Document
GetAllTables doc
.Quit
End With
Next I
End Sub
Sub GetAllTables(doc As Object)
Dim ws As Worksheet
Dim rng As Range
Dim tbl As Object
Dim rw As Object
Dim cl As Object
Dim tabno As Long
Dim nextrow As Long
Dim I As Long
Set ws = Worksheets.Add
For Each tbl In doc.getElementsByTagName("TABLE")
tabno = tabno + 1
nextrow = nextrow + 1
Set rng = ws.Range("B" & nextrow)
rng.Offset(, -1) = "Table " & tabno
For Each rw In tbl.Rows
For Each cl In rw.Cells
rng.Value = cl.outerText
Set rng = rng.Offset(, 1)
I = I + 1
Next cl
nextrow = nextrow + 1
Set rng = rng.Offset(1, -I)
I = 0
Next rw
Next tbl
End Sub
it retrieves the all races data from the url automatically. But can not make the next step. on each page there is a "name of the race" tab and I need to get all the data on each page for each row. It is because I need to get the information of 1st place, 2nd place and third place.
Thanks for your time I know its a bit garbled!!
My new code after changes is looking like this:
Sub GetData()
Dim IE As Object
Dim doc As Object
Dim strURL As String
Dim I As Integer
For I = 1 To 9
strURL = "http://www.greyhound-data.com/d?racename=&country=13000&startmonth=3&endmonth=2&startdate=2017&enddate=2018&maxdist=unlimitied&class=any&order=dateD&x=" + Trim(Str(I))
Set IE = CreateObject("InternetExplorer.Application")
With IE
.navigate strURL
Do Until .ReadyState = 4: DoEvents: Loop
Do While .Busy: DoEvents: Loop
Set doc = IE.Document
GetAllTables doc
.Quit
End With
Next I
End Sub
Sub GetAllTables(doc As Object)
Dim ws As Worksheet
Dim rng As Range
Dim tbl As Object
Dim rw As Object
Dim cl As Object
Dim tabno As Long
Dim nextrow As Long
Dim I As Long
Dim ThisLink As Object 'variable for <a> tags
Set ws = Worksheets.Add
For Each tbl In doc.getElementsByTagName("TABLE")
tabno = tabno + 1
nextrow = nextrow + 1
Set rng = ws.Range("B" & nextrow)
rng.Offset(, -1) = "Table " & tabno
For Each rw In tbl.Rows
For Each cl In rw.Cells
rng.Value = cl.outerText
Set rng = rng.Offset(, 1)
I = I + 1
Next cl
nextrow = nextrow + 1
Set rng = rng.Offset(1, -I)
I = 0
Next rw
Next tbl
I = Range("B" & Rows.Count).End(xlUp).Row 'last row with data
Do While Cells(I, 1).Value = "" 'will loop until first not blank found in column A (starting from last row of data, from end to start)
For Each ThisLink In doc.getElementsByTagName("a") 'we check all <a> tags
If ThisLink.innerText = Cells(I, 2).Value Then Cells(I, 1).Value = ThisLink.href 'If the innertext is the name of the race, in column A we add link
Next ThisLink
I = I - 1 'we decrease row position
Loop
End Sub
but the case is that it returns the empty table as in this link : https://imageshack.us/i/poC4yhEZp
This code, after you get all your data, will check every race from end of list to start of list. And it will add in column A the related link to race.
Sub GetAllTables(doc As Object)
Dim ws As Worksheet
Dim rng As Range
Dim tbl As Object
Dim rw As Object
Dim cl As Object
Dim tabno As Long
Dim nextrow As Long
Dim I As Long
Dim ThisLink As Object 'variable for <a> tags
Set ws = Worksheets.Add
For Each tbl In doc.getElementsByTagName("TABLE")
tabno = tabno + 1
nextrow = nextrow + 1
Set rng = ws.Range("B" & nextrow)
rng.Offset(, -1) = "Table " & tabno
For Each rw In tbl.Rows
For Each cl In rw.Cells
rng.Value = cl.outerText
Set rng = rng.Offset(, 1)
I = I + 1
Next cl
nextrow = nextrow + 1
Set rng = rng.Offset(1, -I)
I = 0
Next rw
Next tbl
I = Range("B" & Rows.Count).End(xlUp).Row 'last row with data
Do While Cells(I, 1).Value = "" 'will loop until first not blank found in column A (starting from last row of data, from end to start)
For Each ThisLink In doc.getElementsByTagName("a") 'we check all <a> tags
If ThisLink.innerText = Cells(I, 2).Value Then Cells(I, 1).Value = ThisLink.href 'If the innertext is the name of the race, in column A we add link
Next ThisLink
I = I - 1 'we decrease row position
Loop
End Sub
In HTML all <a> tags are like this:
Henlow 26 Feb 2018 HT 5
The href attribute contains the link related to text between <a> and </a>. You can get it with a.href in VBA
To know the text between <a> and </a> you can use a.InnerText
What i did is just a simple loop to check every <a> tag. If the InnerText matchs the value in the cell, then I get the href attribute.
This code will get you all the links you want in your question. Just adapt the code to your needs (I pasted them in column A, but maybe you want to do something else with them).
You need 2 references for this code to work;
Microsoft HTML Object Library
Microsoft Internet Controls
And this is the final result:

Excel VBA - Looking for Strings in "Text Block" , then look in the next

I doesnt find a solution for my problem in the WWW.
Hope you can help me:
I've imported a long text file with various information: it looks like this:
id 5
name node1
UPS_serial_number
WWNN 500507680350BD
status online
IO_group_id 0
IO_group_name io_grp0
partner_node_id 4
partner_node_name node2
config_node yes
UPS_unique_id
port_id 500507680456454
port_status active
port_speed 8Gb
port_id 500507680545644
port_status active
port_speed 8Gb
id 4
name node2
UPS_serial_number
WWNN 500507680200DDE8
status online
IO_group_id 0
IO_group_name io_grp0
partner_node_id 4
partner_node_name node1
config_node yes
UPS_unique_id
port_id 5005076803594BDE
port_status active
port_speed 8Gb
port_id 500507680235486F
port_status active
port_speed 8Gb
.
.
.
Its almost formatted in the right format like this:
[string || value]
I want to look in the first block and get the infos for name, id, WWPN - then copy the values to another worksheet.
Then look into the second block and get the same infos: name, id, WWPN and copy them.
Then next block and the next block and so on.
I have the following code:
Sub find_test()
Dim rng As Range
Dim rngCell As Variant
Dim LR As Long
Dim tRow
LR = Cells(1, 1).End(xlDown).Row
Set rng = Range("A1:A" & LR)
For Each rngCell In rng.Cells
tRow = rngCell.Row
If StrComp(rngCell.Value, "name") = 0 Then 'Node 1 Service IP
Worksheets("temp").Range("E16").Value = Worksheets("lsnodecanister").Range("B" & tRow).Value
End If
Next
End Sub
The Text blocks are almost seperated by an empty row.
Do you have any idea?
Hope it was understandable.
Thank you very much,
Best regards,
Kalain
something like
Sub SO1()
Dim lngRow As Long
Dim lngLastRowOfSection As Long
Dim rngFind As Range
Dim strName As String
lngRow = 1
Do Until Cells(lngRow + 1, 1).Value = ""
lngLastRowOfSection = Cells(lngRow, 1).End(xlDown).Row
Set rngFind = Range(Cells(lngRow, 1), Cells(lngLastRowOfSection, 1)).Find("name")
If Not rngFind Is Nothing Then
strName = rngFind.Offset(0, 1).Value
Debug.Print strName
End If
lngRow = Cells(lngLastRowOfSection, 1).End(xlDown).Row
If lngRow >= Rows.Count Then Exit Do
Loop
End Sub
I might have misunderstood the question. I think you meant that each line of your data has the name and data separated by a space. I manipulated your subroutine to put all values in column a into an array and then I split the array into columns B and C.
Sub find_test()
Dim rng As Range
Dim LR As Long
Dim tRow As Long
Dim myArray() As Variant, arrayCounter As Long
Dim lilStringArray
'
LR = ActiveSheet.Cells(ActiveSheet.Rows.Count, "A").End(xlUp).Row
ReDim myArray(1 To 1)
arrayCounter = 1
myArray = Range("A1:A" & LR)
tRow = 1
For i = LBound(myArray) To UBound(myArray)
If myArray(i, 1) <> "" Then
lilStringArray = Split(myArray(i, 1), " ")
Range("B" & tRow).Value = lilStringArray(0)
On Error Resume Next
Range("C" & tRow).Value = lilStringArray(1)
On Error GoTo 0
Else
Range("C" & tRow).Value = ""
End If
tRow = tRow + 1
Next i
End Sub

Subscript out of range (error 9) --- running debugger and going through code everything is fine

Basically, have this code which uses Vlookups and a match to find past order dates of a particular product. The sub fills text boxes in a userform with N/A if there are no past orders found in the sheet. Otherwise, finds the latest order and fills the information in the userform.
The program stops when this sub routine is called. Getting 'subscript out of range' (error 9), I run the debugger and go through the code and everything works the way it is supposed to. In both the N/A case and the case where there is past order info.
Sub PastOrderInfo()
Dim wks As Worksheet
Dim Date_Ordered As Variant
Dim PreviousDate As Variant
Dim Qty_Ordered As String
Dim Total_Cost As String
Dim Rng, RngCol As String
Dim Last_Row As Long
Dim i, NewRow As Integer
Set wks = Worksheets("Order Data")
With wks
Last_Row = .UsedRange.Rows(.UsedRange.Rows.count).Row
Rng = "A2:D" & Last_Row
RngCol = "A2:A" & Last_Row
For i = 2 To Last_Row
If i = 2 Then
On Error Resume Next
PreviousDate = Application.VLookup(CStr(ProdNum), .Range(Rng), 2, False)
On Error GoTo 0
If IsError(PreviousDate) Then
Me.TextBox4.Value = "N/A"
Me.TextBox5.Value = "N/A"
Me.TextBox6.Value = "N/A"
Exit Sub
End If
NewRow = Application.Match(CStr(ProdNum), .Range(RngCol), 0) + 2
Rng = "A" & NewRow & ":D" & Last_Row
RngCol = "A" & NewRow & ":A" & Last_Row
ElseIf i > 2 Then
On Error Resume Next
Date_Ordered = Application.VLookup(CStr(ProdNum), .Range(Rng), 2, False)
On Error GoTo 0
If IsError(Date_Ordered) Then
NewRow = NewRow - 1
Rng = "A" & NewRow & ":D" & Last_Row
Me.TextBox4.Value = CDate(PreviousDate)
Me.TextBox5.Value = Application.VLookup(CStr(ProdNum), .Range(Rng), 3, False)
Me.TextBox6.Value = Application.VLookup(CStr(ProdNum), .Range(Rng), 4, False)
Exit Sub
End If
NewRow = Application.Match(CStr(ProdNum), .Range(RngCol), 0) + NewRow
Rng = "A" & NewRow & ":D" & Last_Row
RngCol = "A" & NewRow & ":A" & Last_Row
If Date_Ordered > PreviousDate Then PreviousDate = Date_Ordered
End If
Next i
Me.TextBox4.Value = CDate(PreviousDate)
Me.TextBox5.Value = Application.VLookup(CStr(ProdNum), .Range(Rng), 3, False)
Me.TextBox6.Value = Application.VLookup(CStr(ProdNum), .Range(Rng), 4, False)
End With
End Sub
Here is the line which is the section of code which opens the userform, when I click to debug it highlights the ProDescription.Show line below the if .Range(cellselect)...:
Private Sub CommandButton1_Click()
Dim i, r, c As Integer
Dim wks As Worksheet
Dim cellselect As String
Set wks = Workbooks("Data Direct Orders2.xlsx").Worksheets("Direct Items")
With wks
If ProdNumberCmbBox.ListIndex = -1 Then
Unload Me
ErrorMsg.Show
End
Else
For r = 2 To 84
cellselect = "A" & r
If .Range(cellselect).Text = ProdNum Then
ProDescription.Show
Unload Me
End
End If
Next r
If c = 0 Then
Unload Me
ErrorMsg.Show
End
End If
End If
End With
End Sub
Here is the sub routine where the userform is initialized:
Private Sub UserForm_Initialize()
TextBox8.Value = ProdNum
Call PastOrderInfo
End Sub
Just figured it out.
The line:
Set wks = Worksheets("Order Data")
in
Sub PastOrderInfo()
Was the problem. Needed to specify the workbook, so after adding:
Set wks = Workbooks("VBA - Final Project.xlsm").Worksheets("Order Data")
It worked!

Using VBA to copy data from one worksheet into another worksheet

I have a slight problem in Excel. I need to sync up the values in the curly braces {} found in column C and put them against the user id in column F. I would like this data to be copied across to a new worksheet in the same workbook. Any ideas how I could accomplish this? You don't have to provide any code but a nudge in the right direction would be great.
E.g. on the Emails sheet
becomes this on a new sheet
In case anyone needs help, this is the solution:
Sub CopyConditional()
Dim wshS As Worksheet
Dim WhichName As String
Set wshS = ActiveWorkbook.Sheets("Emails")
WhichName = "NewSheet"
Const NameCol = "C"
Const FirstRow = 1
Dim LastRow As Long
Dim SrcRow As Long
Dim TrgRow As Long
Dim wshT As Worksheet
Dim cpt As String
Dim user As String
Dim computers() As String
Dim computer As String
On Error Resume Next
Set wshT = Worksheets(WhichName)
If wshT Is Nothing Then
Set wshT = Worksheets.Add(After:=wshS)
wshT.Name = WhichName
End If
On Error GoTo 0
If wshT.Cells(1, NameCol).value = "" Then
TrgRow = 1
Else
TrgRow = wshT.Cells(wshT.Rows.Count, NameCol).End(xlUp).Row + 1
End If
LastRow = wshS.Cells(wshS.Rows.Count, NameCol).End(xlUp).Row
For SrcRow = FirstRow To LastRow
cpt = wshS.Range("C" & SrcRow).value
user = wshS.Range("F" & SrcRow).value
If InStr(cpt, ":") Then
cpt = Mid(cpt, InStr(1, cpt, ":") + 1, Len(cpt))
End If
If InStr(cpt, ";") Then
computers = Split(cpt, ";")
For i = 0 To UBound(computers)
If computers(i) <> "" Then
wshT.Range("A" & TrgRow).value = user
wshT.Range("B" & TrgRow).value = Mid(Left(computers(i), Len(computers(i)) - 1), 2)
TrgRow = TrgRow + 1
End If
Next
Else
computer = cpt
If computer <> "" Then
wshT.Range("A" & TrgRow).value = user
wshT.Range("B" & TrgRow).value = Mid(Left(computer, Len(computer) - 1), 2)
TrgRow = TrgRow + 1
End If
End If
Next SrcRow
End Sub
You didn't ask a question. Basically what you would do is
loop through the values in column F
for each value, get the value in column C
loop through all braced values in column C
let braceValue = parse column C searching for {value}
create a row in new worksheet with column F value, braceValue

Fetched table data from a webpage not displaying first column of table

I need to fetch the price table from this page:
http://www.kieskeurig.nl/objectief/canon/ef_100mm_f2_usm/prijzen/bezorgen/167557#prijzen
So far I have developed this code to get the data
Sub TableExample()
Dim IE As Object
Dim doc As Object
Dim strURL As String
strURL = "http://www.kieskeurig.nl/objectief/canon/ef_100mm_f2_usm/prijzen/bezorgen/167557#prijzen"
' replace with URL of your choice
Set IE = CreateObject("InternetExplorer.Application")
With IE
'.Visible = True
.navigate strURL
Do Until .readyState = 4: DoEvents: Loop
Do While .Busy: DoEvents: Loop
Set doc = IE.document
GetAllTables doc
.Quit
End With
End Sub
Sub GetAllTables(doc As Object)
' get all the tables from a webpage document, doc, and put them in a new worksheet
Dim ws As Worksheet
Dim rng As Range
Dim tbl As Object
Dim rw As Object
Dim cl As Object
Dim tabno As Long
Dim nextrow As Long
Dim I As Long
Set ws = Sheets("Sheet1")
For Each tbl In doc.getElementsByTagName("TABLE")
tabno = tabno + 1
nextrow = nextrow + 1
Set rng = ws.Range("B" & nextrow)
rng.Offset(, -1) = "Table " & tabno
For Each rw In tbl.Rows
For Each cl In rw.Cells
rng.Value = cl.innerText
Set rng = rng.Offset(, 1)
I = I + 1
Next cl
nextrow = nextrow + 1
Set rng = rng.Offset(1, -I)
I = 0
Next rw
Next tbl
ws.Cells.ClearFormats
End Sub
This code does work for me
But the problem is the 1st column i.e. the supplier data is not displaying in the fetched table.
Can anyone please help me on this
Replace your GetAllTables subroutine with the following:
Sub GetAllTables(doc As Object)
' get all the tables from a webpage document, doc, and put them in a new worksheet
Dim ws As Worksheet
Dim rng As Range
Dim tbl As Object
Dim rw As Object
Dim cl As Object
Dim tabno As Long
Dim nextrow As Long
Dim I As Long
Set ws = Sheets("Sheet1")
For Each tbl In doc.getElementsByTagName("TABLE")
tabno = tabno + 1
nextrow = nextrow + 1
Set rng = ws.Range("B" & nextrow)
rng.Offset(, -1) = "Table " & tabno
For Each rw In tbl.Rows
colno = 1
For Each cl In rw.Cells
If colno = 1 and nextrow > 1 then
Set classColl = doc.getElementsByClassName("shopLogoX")
Set imgTgt = classColl(nextrow - 2).getElementsByTagName("img")
rng.Value = imgTgt(0).getAttribute("alt")
Else
rng.Value = cl.innerText
End If
Set rng = rng.Offset(, 1)
I = I + 1
colno = colno + 1
Next cl
nextrow = nextrow + 1
Set rng = rng.Offset(1, -I)
I = 0
Next rw
Next tbl
ws.Cells.ClearFormats
End Sub
The change is very little, actually. We use colno to track on which column we're in already in the row. Obviously, we check if we're in the first cell. If we are on the first column and not on the first row (header row), we create a collection of elements with class shopLogoX. This contains the img tags that have the alt attribute we want.
Tried, tested, and working. Let us know if this helps.