ViewEntry strangeness in R5 -- "Entry is no longer in view" error

I'm developing in R5.0.8 for the Notes client.

I'm trying to write a shared action (or agent run by an action -- either is fine by me) that performs a function against a the documents selected in a view, but performs it against them in the order in which they appear in the view. I'd like the action to be available from several views, and the documents may appear in different sort orders based on the view used.

Obviously I'd rather not have to code this as an action unique to each view that uses it.

My plan was to get the current uiView from the workspace, get the view from that, get all entries from that, and step through the entries, getting the document for each entry and seeing if the document is in the NotesDocumentCollection I got from db.UnprocessedDocuments. This would be rather slow with a large view, but I'm willing to accept that.

It gets the view correctly, and I would have to assume it gets the correct ViewEntryCollection from that. But when I try to get the entry's document I get the error, "Entry is no longer in view: {View Name}".

This is the relevent code:
==== BEGIN PASTE ====
      Dim session As New NotesSession
      Dim ws As New NotesUIWorkspace
      Dim db As NotesDatabase
      Dim dc As NotesDocumentCollection
      Dim uiView As NotesUIView
      Dim view As NotesView
      Dim vec As NotesViewEntryCollection
      Dim ve As NotesViewEntry
      Dim doc As NotesDocument
      Dim vDoc As NotesDocument
      Dim intProcessCount As Integer
      
      Set db = session.CurrentDatabase
      Set dc = db.UnprocessedDocuments
      If dc.Count = 0 Then Exit Sub
            
      Set uiView = ws.CurrentView
      Set view = uiView.View
      Set vec = view.AllEntries
      
      ' Now vec has all the entries in the view, in order, and dc has the documents we're interested in.
      ' We'll have to step through vec entry by entry to see if it's a document that has been selected.
      ' If it is a document in dc, process it.
      
      intProcessCount = 0
      Set ve = vec.GetFirstEntry
      Do While Not (ve Is Nothing)
            Set vDoc = ve.Document
            If Not (vDoc Is Nothing) Then
                  Set doc = dc.GetDocument(vDoc)
                  If Not (doc Is Nothing) Then
                              ' Prevent a document from being processed twice
                        Call dc.DeleteDocument(doc)
                        intProcessCount = intProcessCount + 1
                              ' Process it here.
                        If intProcessCount = dc.Count Then Exit Do
                  End If
            End If
            Set ve = vec.GetNextEntry(ve)
      Loop
===== END PASTE =====

I've tried checking first to see if vDoc.IsDocument, but I get the same error there.

The thing is, I'm the only person on the database as it's still being developed. Nobody else is adding or removing documents, so it the error I'm getting makes no sense to me.

Any ideas what's going on here, or are ViewEntries just so unstable that they never should have been released into production?

Thanks.

-- b.r.t.
LVL 7
BarryTiceAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

p_parthaCommented:
Barry
I believe it's the indexing problem, WHy don't you do a Call vec.RemoveAll(True) in the end

Partha
0
BarryTiceAuthor Commented:
I'm never getting to the end, Partha. Besides, I have no desire to delete all my documents from the database.

Nice try, though. ;-P

Next?

-- b.r.t.
0
p_parthaCommented:
Barry
let me try to explain what i understood from your code, You loop thru the entire view and delete all the documnets that are selected but that's not what the code does, what if the user selects documents randomly, still this code walks thru each documnet adn delete uptil the count matches the number of selected documents. Also when you delete a documnet, i believe(not tested yet), even the notesviewentry handle is lost, so when you say getnextentry, there is no entry

partha
0
Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

BarryTiceAuthor Commented:
Partha --

What dc.Delete(doc) does is remove the document from the NotesDocumentCollection, not from the database. That's so if one document appears twice in a view because of the way the view categorizes things, it won't process more than once.

In the place where I have the ' Process it here comment, I make a call to another subroutine that actually does the processing of the document.

So, yes. A person could be looking at a view and select a series of documents in some random order. When the invoke my action, the action should process those documents in the order they appear in the view. If the document appears in the view more than once, it should only be processed once (from its first appearance in the view).

Actually, I see an error here in that I don't need the intProcessCount variable, as I can stop processing when dc.Count is zero. My problem though is that the very first time the loop tries to execute, it blows up with the above error. No documents are ever deleted from the database. Actually, no documents are even modified in the database, as the processing I'm doing involves exporting data to an external file. But even if my process did involve modifying documents, it's never getting to where the process would run. The very first time it hits "set vDoc = ve.Document" it bombs on me. By that time, ve is fresh, vec is fresh, why wouldn't ve be valid?

Thanks.

-- b.r.t.

(Sorry if I seemed snippy before. I thought you were joking with me, telling me to delete all my documents. I took that as the equivalent of "reboot and fdisk" that crops up in the Lounge so often. The dc.Delete(doc) command is indeed poorly named.)
0
BarryTiceAuthor Commented:
Consider this revised code, with the IntProcessCount removed.

==== BEGIN PASTE ====
     Dim session As New NotesSession
     Dim ws As New NotesUIWorkspace
     Dim db As NotesDatabase
     Dim dc As NotesDocumentCollection
     Dim uiView As NotesUIView
     Dim view As NotesView
     Dim vec As NotesViewEntryCollection
     Dim ve As NotesViewEntry
     Dim doc As NotesDocument
     Dim vDoc As NotesDocument
     
     Set db = session.CurrentDatabase
     Set dc = db.UnprocessedDocuments
     If dc.Count = 0 Then Exit Sub
         
     Set uiView = ws.CurrentView
     Set view = uiView.View
     Set vec = view.AllEntries
     
     ' Now vec has all the entries in the view, in order, and dc has the documents we're interested in.
     ' We'll have to step through vec entry by entry to see if it's a document that has been selected.
     ' If it is a document in dc, process it.
     
     Set ve = vec.GetFirstEntry
     Do While Not (ve Is Nothing)
          Set vDoc = ve.Document
          If Not (vDoc Is Nothing) Then
               Set doc = dc.GetDocument(vDoc)
               If Not (doc Is Nothing) Then
                    ' Prevent a document from being processed twice
                    Call dc.DeleteDocument(doc)
                    ' Process it here. (Calls another subroutine that performs the extract)
                    If dc.Count = 0 Then Exit Do
               End If
          End If
          Set ve = vec.GetNextEntry(ve)
     Loop
===== END PASTE =====
0
p_parthaCommented:
Sorry to confuse you with the earlier post, my rumbles got mixed up i believe :).. Can you debug and tell which line fails

partha
0
Andrea ErcolinoCommented:
From Designer Help about Document property for NotesViewEntry:
<<Returns NULL if the view entry is not a document. Returns NULL if the document is deleted after the ViewEntry object is created.>>

So I think here applies the first NULL condition, the first entry could be a category... so you use the following code:
---
     Set ve = vec.GetFirstEntry
     Do While Not( ve Is Nothing )
          If Not( Isnull( ve.Document ) ) Then
               Set doc = dc.GetDocument( ve.Document )
               If Not( doc Is Nothing ) Then
                    ' Process it here. (Calls another subroutine that performs the extract)
                    ' Prevent a document from being processed twice
                    Call dc.DeleteDocument( doc )
                    If dc.Count = 0 Then Exit Do
               End If
          End If
          Set ve = vec.GetNextEntry( ve )
     Loop
---

I didn't test it but it should work fine.
0
BarryTiceAuthor Commented:
The line that fails is set vDoc = ve.Document

When it gets to that line, I get "Entry is no longer in view", which makes no sense to me.

RAPUTA -- It's true that NULL is returned for both conditions, so it's conceivable that Notes is returning the wrong error. But before I made it this far, I tried:
if ve.IsDocument Then
    (other code here)

and I also tried
if ve.IsValid Then
    (other code here)

In both cases it failed (the first with the same error, the second by skipping the condition).

-- b.r.t.
0
p_parthaCommented:
Barry
Is it a categorized view, then you might have to use Notesviewnavigator class  and then get the handle to the notesviewentry object. Seems to be a issue.

Partha
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Sjef BosmanGroupware ConsultantCommented:
I didn't read all the comments above, so sorry if I missed an essential thing.

What I analyzed from your question is that you want to avoid that documents get processed twice. There are some solutions to that, I think.

The first works only if the number of documents stays below an (un)certain limit. What the limit is? No idea. Must be around 32K or so. The idea is to store the DocID's of the documents handled in a List. Ever used a List? It's an underrated feature of LotusScript. Disadvantage: if the list grows large, you'll soon find out that the time needed for looking through the list will grow.

    Dim docids List As Integer

In your code somewhere:
    If Not IsElement(docids(doc.universalid)) Then
        docids(doc.universalid)= 1 ' just need some value, it has to exist

The second solution is to use the ViewEntry-stuff only to collect the document-id's in the right sequence, put them into a list (note the limit!) and then use the list from start to finish with GetDocumentByUnid calls to retrieve the documents in the right order.

Another solution might be to add some sorting to the view, in a hidden column, and sort the results afterwards. Might be too impractical, but I wanted this to be noted for posterity. :)

Great things, Lists!
0
Andrea ErcolinoCommented:
BarryTice,
just give a try to my suggested code...

LotusScript is not like Perl... here NULL, Nothing, 0, "0", "", False are all different values so you must use Isnull( something ) to test if something is null!
And your script fails because you cannot assign a NULL to an object variable.
0
BarryTiceAuthor Commented:
sjef_bosman --

Thanks for the info on lists, but my chief challenge here was even getting the document from the view entry, as the view entry was returning something that wasn't playing nicely.

RAPUTA --

Thanks for the clarification on NULL. But by the time I read your comment here, I had already implemented Partha's suggestion of using the ViewNavigator class, which took care of my problem.

The final code looks something like this:

==== BEGIN PASTE ====
      Dim session As New NotesSession
      Dim ws As New NotesUIWorkspace
      Dim db As NotesDatabase
      Dim dc As NotesDocumentCollection
      Dim uiView As NotesUIView
      Dim view As NotesView
      Dim nav As NotesViewNavigator
      Dim ve As NotesViewEntry
      Dim doc As NotesDocument
      Dim vDoc As NotesDocument
      
      Set db = session.CurrentDatabase
      Set dc = db.UnprocessedDocuments
      If dc.Count = 0 Then Exit Sub
      
      Set uiView = ws.CurrentView
      Set view = uiView.View
      Set nav = view.CreateViewNav
      
      ' Now vec has all the entries in the view, in order, and dc has the documents we're interested in.
      ' We'll have to step through vec document by document to see if it's a document that has been selected.
      ' If it is a document in dc, process it.
      
      Set ve = nav.GetFirst
      Do While Not (ve Is Nothing)
            Set vDoc = ve.Document
            If Not (vDoc Is Nothing) Then
                  Set doc = dc.GetDocument(vDoc)
                  If Not (doc Is Nothing) Then
                        ' Prevent a document from being processed twice
                        Call dc.DeleteDocument(doc)
                        ' Process it here.
                        Call ProcessDocument(doc)      ' A different subroutine that performs the extraction
                        If dc.Count = 0 Then Exit Do
                  End If
            End If
            Set ve = nav.GetNext(ve)
      Loop
===== END PASTE =====

Thanks to all who contributed. Normally I try to add in extra points as a reward to everyone who participaed, but I'm all out of points.

-- b.r.t.
0
p_parthaCommented:
Thanks Barry for the points :)

Partha
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Lotus IBM

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.