Syntax Error Issue on VBA - vba

I am trying to extract some values using VBA from a Website
The following code contains the array of the data I am looking for. This works perfectly and gives me the array of the data I am looking for.
document.getElementsByClassName("list-flights")(0).querySelectorAll("[class$='price']")
The result for the above is
<NodeList length="23">...</NodeList>
But when I am trying to extract the values by running the loop in a VBA by using the following code
lnth = document.getElementsByClassName("list-flights")(0).querySelectorAll("[class$='price']").Length - 1
For x = 0 To lnth
firstResult = document.getElementsByClassName("list-flights")(0).querySelectorAll("[class$='price']")(x).innerText
Next x
The code would give error at firstResult since it would not get any value. I checked on Internet Explorer there is no value if I use "(" brackets,however if I use "[" on Internet Explorer it works but VBA would not accept "[" Brackets.
document.getElementsByClassName("list-flights")(0).querySelectorAll("[class$='price']")[0]
The code above works on Internet Explorer Console but cant be used in VBA.
I am sure I am missing something would be of great help if you can advice what is the workaround on this.

To get the innerText, you can use getElementsByClassName 2 more times, one of them inside for each .. next loop since your values are in list-flights -> price -> cash js_linkInsideCell:
Set priceData = IE.document.getElementsByClassName("list-flights")(0).getElementsByClassName("price")
For Each Item In priceData
Debug.Print Item.getElementsByClassName("cash js_linkInsideCell")(0).innerHTML
Next Item
Using .querySelectorAll("[class$='price']") works as well, but it crashes IE object after parsing. Try and see if it crashes:
Set priceData = IE.document.getElementsByClassName("list-flights")(0).querySelectorAll("[class$='price']")
For Each Item In priceData
Debug.Print Item.getElementsByClassName("cash js_linkInsideCell")(0).innerHTML
Next Item
Some quick notes:
1-You can use this code to wait for IE object to load url:
Do While IE.Busy
DoEvents
Loop
2-Sometimes, even if IE object is ready, query results are not returned that fast. This means the elements you are looking for are not ready yet and do not exists so you get an error message:
Run-time error '91': Object variable or With block variable not set
To avoid this message my workaround is as follows:
Do
On Error Resume Next
Set priceData = IE.document.getElementsByClassName("list-flights")(0).getElementsByClassName("price")
Loop Until Err.Number <> 91
I hope this helps.

Related

Run-time error '5852' when iterating over revisions

I am easily annoyed by word tracking format changes (even in text that is newly inserted in a revision), so I am using a macro to accept all format changes, once they summed up:
Sub AcceptAllFormatChanges()
Dim xRev As Revision
Dim count As Integer
count = 0
For Each xRev In ActiveDocument.Revisions
If Not xRev Is Nothing Then
If xRev.Type = wdRevisionProperty Then
count = count + 1
xRev.Accept
End If
End If
Next xRev
MsgBox ("Accepted " & count & " format changes")
End Sub
This works fine most of the time, but on some documents, it gives me a run-time error '5852' - Requested object is not available on the "If xRev.Type" line. I am looking for a way to check the object that is yielded by ActiveDocument.Revisions without it throwing a run-time error. Checking for Nothing is not enough. The issue also occures when removing the xRev.Accept or when looping backwards through the revisions.
Update: I tracked down the issue to a Word Bug today. If the macro strikes, I am also unable to iterate through changes in the document using the Next Change button on the review panel. Additionally, if I open the revision panel, the number of revisions jumps back and forth between two numbers. This helped me track down those ghost revisions to a few insertions which included fields (references to other sections). I am able to correct those by deleting/reinserting, so at least now I know how to fix my documents to make the macro work again. Unfortunately, I cannot reproduce the bug in order to actually file a bug report.
The VBA question though remains open: Is there a way for the macro to skip those ghost revisions without throwing a run-time error?
Use the WdRevisionType enumeration instead of cryptic numbers in the code for checking the Type property. Also you may try to check for Nothing before getting the Type property value. The following code works like a charm for me:
Public Sub AcceptSelection()
Dim rev As Revision
For Each rev In Selection.Range.Revisions
rev.Accept
Next rev
End Sub
And the last resort is to replace the for each loop with a reverse for loop.

Type Mismatch error with Application.Match in VBA Macro

I am trying to use Application.Match to delete a series of lines from a spreadsheet before using the remaining lines to edit an existing spreadsheet. Here is the code that I am using, which gives me a Type Mismatch error. I have used similar logic with smaller datasets previously and not had a problem:
If IsError(Application.Match(Fund_Inv_Cusip_Change(LineNumber), Fund_Inv_Cusips_to_Edit, 0)) Then
If DeletionRange Is Nothing Then
Set DeletionRange = Cells(Override_Workbook_Line + 3, 1).EntireRow
Else
Set DeletionRange = Union(DeletionRange, Cells(Override_Workbook_Line + 3, 1).EntireRow)
End If
End If
Next LineNumber
DeletionRange.Delete Shift:=xlUp
Set DeletionRange = Nothing
Fund_Inv_Cusips_to_Edit is declared an array with 66,124 entries, declared as a string. FUnd_Inv_Cusip_Change is an array with 3329 entries, declared as a string. Using print(typename(fund_inv_cusips_to_edit()) in the Immediate window returns String() for each array, so I'm not certain why this is a type mismatch.
Any help would be much appreciated. I have read through a lot of posts on this board and others and not seen something that directly addresses this issue. Thank you!
Application.Match can only take 65,536 element arrays in the second argument. In the Immediate Window
?application.match(1,range("A1:A65536").Value,false)
no error
?application.match(1,range("A1:A65537").Value,false)
type mismatch error.
You could loop. It's not very efficient, but it might be quicker than you think. Or you could put it in a disconnected recordset, but it might take longer to load that up than just looping.

VBA to GetElementByID on a Web form

I'm having a bit of trouble with my VBA code filling in a form on an intranet page. It generally works okay but every so often, the ID's of the fields on this form change and I have to update my code but not until I've had lots of errors reported. Is there anyway I can use a wildcard, or loop through the possibilities before it tries to fill out the form? The bit of code I'm using is
WebBrowser1.Document.GetElementById("Template_ctl24_ctl00_Shelfmark" & x & "_TextField").value = Range("Q" & x + 11).value
But the ID can change to Template_ctl22_ctl00.... or Template_ctl25_ctl00.... for a reason unknown to me. I don't have control over that area - i'm really only front end.
So is there some variation on using a * wildcard?
Or looping through whether the ID is a 22, 24, 25 or whatever before it proceeds?
What can and can't you do with this sort of line of VBA code?
Thanks in advance
Paul
If you know where the element is positioned on the page it would be much better to locate it using something like getElementsByTagName.
However, you could use a simple loop. In the following I've assumed the attempt to reference a non-existing element results in Nothing, but perhaps it generates an error - I haven't tested. If so, you'll need to use error-handling code instead.
Dim elem As Variant
For x = 22 To 25
Set elem = WebBrowser1.Document.GetElementById("Template_ctl24_ctl00_Shelfmark" _
& x & "_TextField")
If Not elem Is Nothing Then
Exit For
End If
Next x
If elem Is Nothing Then
'Doh! not found
Else
'obtain elem.value
End If

Error on ActiveSelection.Tasks

Does anyone know what this means
Set oProjTasks = ActiveSelection.Tasks
I have a macro that generates status reports from MS project and exports them directly into MS Word. It is a slick tool when it works.
When I run it now it throws "runtime error '424': object required" at this point.
How do I fix this?
The code that you are displaying is a set statement, that is setting the object ProjTasks equal to the task that is selected in the message box. The ActiveSelection property returns a selection object that represents the active selection.
It could be that you are experiencing an issue where there are no items selected, in which case it will throw a trappable error code 424. There is a code snippet that you can modify from the MSDN that will work to prevent this type of error from occuring.
Here is the link to the MSDN article... just remember to not use this code verbatim, but modify it to work with your macro.
http://msdn.microsoft.com/en-us/library/aa169315%28v=office.11%29.aspx
You could try just wrapping the error check around the set statement. I've written a small macro on a non-empty project file:
Sub Testing()
On Error GoTo ActiveSelectionErrHandler:
Set oProjTasks = ActiveSelection.Tasks
If oProjTasks Is Nothing Then
MsgBox "No tasks in current project"
End If
ActiveSelectionErrHandler:
Set oProjTasks = ThisProject.Tasks 'or something like that
Resume Next
End Sub
This handles the error but as Steve has already expressed more work is required to integrate the code.
You will have to follow the code to make changes to handle oProjTasks being empty where it is expected to have some values. Otherwise you will see more errors perhaps where the oProjTasks is found to be empty.
Another alternative solution could be to launch the macro after selecting a project as the code you have quoted will work fine if something is selected.

GetCrossReferenceItems in msword and VBA showing only limited content

I want to make a special list of figures with use of VBA and here I am using the function
myFigures = ActiveDocument.GetCrossReferenceItems(Referencetype:="Figure")
In my word document there are 20 figures, but myFigures only contains the first 10 figures (see my code below.).
I search the internet and found that others had the same problem, but I have not found any solutions.
My word is 2003 version
Please help me ....
Sub List()
Dim i As Long
Dim LowerValFig, UpperValFig As Integer
Dim myTables, myFigures as Variant
If ActiveDocument.Bookmarks.Count >= 1 Then
myFigures = ActiveDocument.GetCrossReferenceItems(Referencetype:="Figure")
' Test size...
LowerValFig = LBound(myFigures) 'Get the lower boundry number.
UpperValFig = UBound(myFigures) 'Get the upper boundry number
' Do something ....
For i = LBound(myFigures) To UBound(myFigures) ‘ should be 1…20, but is onlu 1…10
'Do something ....
Next i
End If
MsgBox ("Done ....")
End Sub*
Definitely something flaky with that. If I run the following code on a document that contains 32 Figure captions, the message boxes both display 32. However, if I uncomment the For Next loop, they only display 12 and the iteration ceases after the 12th item.
Dim i As Long
Dim myFigures As Variant
myFigures = ActiveDocument.GetCrossReferenceItems("Figure")
MsgBox myFigures(UBound(myFigures))
MsgBox UBound(myFigures)
'For i = 1 To UBound(myFigures)
' MsgBox myFigures(i)
'Next i
I had the same problem with my custom cross-refference dialog and solved it by invoking the dialog after each command ActiveDocument.GetCrossReferenceItems(YourCaptionName).
So you type:
varRefItemsFigure1 = ActiveDocument.GetCrossReferenceItems(g_strCaptionLabelFigure1)
For k = 1 To UBound(varRefItemsFigure1)
frmBwtRefDialog.ListBoxFigures.AddItem varRefItemsFigure1(k)
Next
and then:
frmBwtRefDialog.Show vbModeless
Thus the dialog invoked several times instead of one, but it works fast and don't do any trouble. I used this for one year and didn't see any errors.
Enjoy!
Frankly I feel bad about calling this an "answer", but here's what I did in the same situation. It would appear that entering the debugger and stepping through the GetCrossReferenceItems always returns the correct value. Inspired by this I tried various ways of giving control back to Word (DoEvents; running next segment using Application.OnTime) but to no avail. Eventually the only thing I found that worked was to invoke the debugger between assignments, so I have:
availRefs =
ActiveDocument.GetCrossReferenceItems(wdRefTypeNumberedItem):Stop
availTables =
ActiveDocument.GetCrossReferenceItems(wdCaptionTable):Stop
availFigures = ActiveDocument.GetCrossReferenceItems(wdCaptionFigure)
It's not pretty but, as I'm the only person who'll be running this, it kind of works for my purposes.