how can htmlagilitypack check if nodes exist on webpage? - html-agility-pack

Using Vb.net and HtmlAgilityPack is there a way to check if the node exists on the webpage before selecting the node ?
While running my program, if the node doesn't exist at all on the page, I am getting a null exception error message.
I don't want to use
If firsttag(0).InnerText IsNot Nothing Then
as by using this, the program is already trying to get the value of the node.
I would like to scan the webpage first to see if the node exists
Dim firsttag As HtmlAgilityPack.HtmlNodeCollection = docnews.DocumentNode.SelectNodes("//div[(#class='byline')]")
Is there anything like
if firsttage(0) search does not exist then Continue For Else

Check whether firstTag returns Nothing or if it returns an empty list:
If (firstTag IsNot Nothing and firstTag.Any() and firstTag.First().InnerText IsNot Nothing Then

Related

Schroedinger's object?

I tried to check, if an object (or layer) does exist in a document.
This script works, if there is a pageItem with name x. But it fails if not. (so far so good)
The strange part is: even if this object named "x" doesn't exist, A returns an object. If I'm asking it for its name, id, index or anything the script stops because of an error.
//Schroedinger's object
A=app.activeDocument.pageItems.itemByName("x")
$.writeln(A) //returns: [object PageItem]
$.writeln(A.id) //Error. doesn't exist
So please try it out with a blank new document in InDesign and run the script. I don't understand this phenomenon.
At least you can verify it's existance with A.isValid (that's what I am using now, hoping for the best)
Your approach is correct.
.itemByName() always returns a PageItem object (provided that you passed some string as the argument). But the returned object will only be valid if a corresponding item exists in the document. You should use the .isValid property to verify whether the returned object is valid.

Creating a view and agent in multiple databases

The problem I am encountering is that some of the messages are not accessible by the user ID file, I would like to skip these files instead of the agent crashing out. The error message received is as follows:
Using the view approach if this happened I was able to delete the document temporarily and re-run the agent but if there is a way to skip documents it would be a great help.
Thanks for the help guys.
Ok I have amended the code to a point where I am almost comfortable with it.
Sub Initialize
Dim s As New notessession
Dim db As notesdatabase
Dim view As notesview
Dim doc As notesdocument
Dim nextdoc As notesdocument
Set db = s.currentdatabase
If view Is Nothing Then
Set view = db.CreateView("Encrypted",{Encrypt="1"})
End If
Set doc = view.getfirstdocument
On Error Goto ErrorHandler
While Not doc Is Nothing
nextDocument:
Set nextdoc = view.getnextdocument(doc)
'The below loop is mandatory to ensure that all $File entries are unecrypted
Forall i In doc.items
If i.isencrypted Then
i.isencrypted=False
End If
End Forall
'Must have at least 1 field encrypted in order to call Encrypt method
Dim temp As New NotesItem(doc,"tempjunk","temp")
temp.IsEncrypted=True
Call doc.encrypt
Call doc.save(True, False)
'This portion can now remove the fields relative to encrypting the
'single token encrypted field.
Call doc.removeitem("$Seal")
Call doc.removeitem("$SealData")
Call doc.removeitem("SecretEncryptionKeys")
Call doc.removeitem("Encrypt")
Call doc.removeItem("tempjunk")
Call doc.save(True, False)
Set doc = nextdoc
Wend
Exit Sub
ErrorHandler:
On Error Resume nextDocument
Exit Sub
End Sub
The error handling is not playing nice;
On Error Resume nextDocument is showing up as an error.
I have tried suppressing all of the error warnings which seems to attempt to strip the encryption but I think they body of the messages is being destroyed as a result.
It is no problem to create an agent in a container database and let that agent access documents in all "target" databases and modify them accordingly - No need to copy that agent to all databases.
Only restriction: If the databases are on another server, then on the server security tab of the target server you have to enter the server with the container database as trusted server.
AND: If your agent runs longer than the allowed maximum run time for agents on the server, then it will be killed prematurely.
There is no need to create views in the target databases, you can use NotesDatabase.Search() to get the corresponding documents in the databases...
You can create views by copying them from another database. Say you create a view "Encrypted" in your db with the agent.
Then add a piece of code to get a handle of this view as a NotesDocument:
Dim dbThis As NotesDatabase
Dim viewTemplate As NotesView
Dim docView As NotesDocument
Set dbThis = s.currentDatabase
Set viewTemplate = dbThis.getView("Encrypted")
Set docView = dbThis.Getdocumentbyunid(viewTemplate.Universalid)
In the agent loop, test if view Encrypted exists, if not copy the "view template":
Set view = db.getview("Encrypted")
If view Is Nothing Then
Call docView.Copytodatabase(db)
Set view = db.getview("Encrypted")
End If
Finally, if you insist, a similar procedure might be used to copy the agent to all databases, but for me the idea of running the agent in one db sounds better.
Edited: In the view of full disclosure - of course you can create a view (I guess that was the original question).
If view Is Nothing Then
Set view = db.Createview("Encrypted", {Encrypt="1"})
End If
Or do one-shot dbSearch suggested by Torsten, with a good re-mark of Richard - if you intend to run your code several times - say if encrypted documents might get created again or re-encrypted, rather go for the view.
My method is a bit old fashioned (pre-dates availability of createView) and works well if you need more than selection formula, so you can pre-build a complicated view for re-use.
Performance-wise: whatever method you will choose either creating view using createView or copying from other db or doing dbSearch there is going to be a certain slow-down while the view gets built or dbSearch executes. Karl-Henry's approach will avoid this search/view build, but will be relatively slow if there are not many encrypted documents.
Whichever method you choose - here is a small tip to boost performance. Make your loops like this to release memory as you go; for example, assuming Karl-Henry's approach:
Dim doc1 as NotesDocument
Set doc = col.GetFirstDocument()
Do Until doc Is Nothing
Set doc1 = col.GetNextDocument(doc)
formname = doc.GetItemValue("Form")(0)
If IsElement(exclude(formname))=False Then
Call RemoveEncryption(doc) '*** Your function to remove encryption
End If
' releasing memory when processing thousands of documents improves performance and avoids crashes
Delete doc
Set doc = doc1
Loop
Now again, as you are talking only about migration (so one shot) of 20+ databases, the speed or implementation details should not be that critical.
If you have to process all (or almost all) documents in each database, you can use db.AllDocuments. It is more efficient than using db.Search() with an #All formula.
If you want to exclude certain documents, perhaps based on the form name, I would build a list of forms to exclude, and then use IsElement to check each document being processed against that list.
Dim exclude List As Boolean
exclude("FormA")=True
exclude("FormB")=True
Set col = db.AllDocuments
Set doc = col.GetFirstDocument()
Do Until doc Is Nothing
formname = doc.GetItemValue("Form")(0)
If IsElement(exclude(formname))=False Then
Call RemoveEncryption(doc) '*** Your function to remove encryption
End If
Set doc = col.GetNextDocument(doc)
Loop
Something like that. By the way, you can create the list as any data type. I just choose Boolean as it is a small data type, and that it makes the code easier to read. The IsElement() function just check if the element exists, it does not use the value you set.
You would wrap the code above in a function and call it once per database.
Appended answer, based on additional info in original question:
That should not be hard, just add error handling to your code.
Before you start to loop throung the document:
On Error Goto errHandler
Before you get the next document in the loop:
nextDocument:
At the end of your code:
Exit Sub
errHandler:
Resume nextDocument
End Sub
Try that.

QTP - if object exists in object repository

In QTP is there any way in the code to check to see if a specific object exists in the object repository. I have tried the following code:
If JavaWindow(className).JavaDialog(dialogName).Exist Then
doThisStuff
Else
doThisStuffInstead
End If
But from what I have gleamed from the Internets, this is similar to a isVisible method, only resulting in true if the specified object is currently visible. When I use the above code I receive a "JavaDialog object was not found in the Object Repository." Is there a method or any way to prevent this very error and check to see if the object does indeed exist?
Thank you for your time
I'm not sure what you're trying to accomplish here, one typically knows if an object exists in the object repository before using it. The doubt is usually whether there is a corresponding control in the AUT (Application Under Test).
If you really face the situation that sometimes the object is in the repository and sometimes it isn't (I can think of several ways for this to happen but none of them make much sense) then you can use VBScript's error handling mechanism.
On Error Resume Next ' Turn off error handling
' Just check if object is in repository, there's no need to do anything with it
Dim Exists: Exists=JavaWindow(className).JavaDialog(dialogName).Exist
If Err.Number <> 0 Then
doThisStuff 'Exists is still empty
Else
doThisStuffInstead ' Exists is properly set
End If
On Error Goto 0 ' Resume regular error handling
So, from the error you get, either the dialog that appears is different from the one you've stored in the repository or you don't have it there.
Have you checked it is really present in the Repository? You can try to just locate this element button.
Using the method of "if object not in the repository - skip the step" is not really a good idea. 1. Why would you want to skip the test/part of the test if the object was not saved in the repository?
2. If it's not there, so you need to make sure to store it.
I would assume that this "missing" object might have some values by which it's matched to the object from the repository different from test to test. You can tune the "matching" mechanism by manually setting the values by which you want QTP to locate it.

Check for COM Object Collection Propertys Existence

I have been pondering this one for a while. I am programatically (in VB6) sifting through Outlook PSTs, indexing items that are in them. I have happened on to one that is a little corrupted and this is where I am having difficulty. My program attaches the PST and starts drilling down through the folders (olFolder). These Outlook created objects are supposed to have a collection that would normally hold sub folders (appropriately named Folders).
During the execution of my code I recursively call the process folder function to process all folders in the current folder, but I have one that does not have a collection. This causes an exception because I am checking the count of folders in the collection and there is nothing to check. I understand how to check for the existence of an object, but I am having a hard time checking for the existence of a collection in and object.
Update
The expression:
If Not fl.Folders Is Nothing Then
ends up throwing the exception too. The exception that I am getting is the following:
Could not complete the operation because the service provider does not support it.
This is only when trying to access this corrupted folder which appears to have a Folders Collection Property that is FUBARed.
Final
Alright; in this case I am just going to put in some in-line error handling.
If Not Err.Number = -2147221246 Then
'Do the thing with the other thing
End If
Err.Clear
If you are talking about checking whether obj.Coll.Count = 0, then see if obj.Coll Is Nothing.
well when i work web services on vb6 i have check some cases if property exist. i used that method.
It is slow but i hope that help you.
Public Function HasProperty(ByRef obj As Object, ByVal nameProperty As String) As Boolean
On Local Error GoTo hasProperty_Error
Dim Result
Result = CallByName(obj, nameProperty, VbGet)
hasProperty = True
hasProperty_Done:
Exit Function
hasProperty_Error:
If Err.Number = 438 Then
hasProperty = False
End If
Resume hasProperty_Done
End Function

ms access linked image relitive path

I have an Image object.
I have the Picture type set to linked, so I can change the picture if I want.
I have the Picture property set to the picture name.
I would think that access would use relitive addressing and simple looking in the current directory for the image. But it does not and I get an error telling me it cannot find the picture.
Anyone have a solution? (Other than setting the Picture type to embedded or using the full file address?)
Thanks!
Update:
Tried this:
Private Sub Form_Load()
Dim file As String
file = CurrentDb().Name
file = Replace(file, ".mdb", ".bmp")
Me.Image46.Picture = file
End Sub
It works, except I still get the error message. I click O.K. and it works. Just need the error message to go away.
SOLUTION: Use the above code (or the code posted in the answer below) and then set the 'picture type' to "embedded" and then delete the 'picture' field so that it says "(none)".
Save and run.
It should work.
THANKS!
You could set the property on the forms OnLoad event like this
Me.imgMy_image.picture=getDBPath & “mypicture.bmp”
Here is the getDBPath function
Public Function GetDBPath() As String
Dim strFullPath As String
Dim I As Integer
strFullPath = CurrentDb().Name
For I = Len(strFullPath) To 1 Step -1
If Mid(strFullPath, I, 1) = "\" Then
GetDBPath = Left(strFullPath, I)
Exit For
End If
Next
End Function
Before anyone comments yes I know in access 2000 and above you can use currentproject.path but I’m stuck in the land that time forgot so need that custom function, it still works with later versions of access
Current folder depends of the way you open database in Access. At least, if you open it thru "File-Open", current folder changes to the folder of MDB file. But if you open via double-clicking MDB in explorer, it does not.

Resources