Link to home
Start Free TrialLog in
Avatar of jdg995
jdg995

asked on

Detach 100s of files at once

I asked this question before, but time constraints made me accept the answer (which didn't work) before I implemented it.  NOw the topic has come up again....

Question:  I need to detach 100s of files from a Notes DB using an agent, and acting on selected documents.  When I use provided LotusScripts, I get an object variable error, so I wrote my own Java class to do it, that looks like so:

import lotus.domino.*;
import java.util.*;

public class JavaAgent extends AgentBase {

      public void NotesMain() {

            try {
                  Session session = getSession();
                  AgentContext agentContext = session.getAgentContext();
                  //Database db = agentContext.getCurrentDatabase();
                  DocumentCollection dc = agentContext.getUnprocessedDocuments();
                  Document doc = dc.getFirstDocument();
                  while (doc != null) {
                        Vector attach = new Vector();
                        attach = doc.getEmbeddedObjects();
                        int size = attach.size();
                        for (int i = 0; i < size; i ++){
                              EmbeddedObject embed = (EmbeddedObject)(attach.elementAt(i));
                              embed.extractFile("h:\\jdgray\\ar");
                        }                        
                        doc = dc.getNextDocument();
                  }
            }
            catch(Exception e) {
                  e.printStackTrace();
            }
      }
}


No errors, but nothing happens.  Any fixes, any other ideas?
Avatar of Arunkumar
Arunkumar

Hi jdg995,

TRY THIS AGENT SCRIPT.

copy this script in an agent .  Select the desired options for the agents to run.
 
create a Folder in the drive where you want to detach the files.

make sure to make the following changes to the script below.

Put the folder name ( With Full Path )  in the "FOLDERNAME" in the script

Change "NAME-OF-THE-VIEW-WHERE-YOU-HAVE-ALL-THE-DOCUMENTS-WITH-ATTACHMENTS"

Change "NAME-OF-THE-FIELD-THAT-HAS-ATTACHMENTS"

PL.Note :  The files extracted will have slightly different name.  
Filename + (Randonnumber).  This is to avoid overwriting filenames of same name
Good Luck !

:)
Arun

     
     Dim ss As New notessession
     Dim db As notesdatabase
     Dim view As notesview      
     Dim rndno As Double
     
     Dim doc As NotesDocument
     Dim rtitem As NotesRichTextItem
     
     
     Set db = ss.currentdatabase
     Set view = db.getview("NAME-OF-THE-VIEW-WHERE-YOU-HAVE-ALL-THE-DOCUMENTS-WITH-ATTACHMENTS")
     Set doc = view.getfirstdocument
     
     
     Do While Not doc Is Nothing
         
          Set rtitem = New NotesRichTextItem( doc , "NAME-OF-THE-FIELD-THAT-HAS-ATTACHMENTS" )
         
          If doc.HasEmbedded Then
               
               Forall obj In rtitem.EmbeddedObjects
                   
                    If ( obj.Type = EMBED_ATTACHMENT ) Then
                         
                         Randomize
                         rndno = Int ( Rnd() * 1000 )
                         
                         Call obj.ExtractFile( "FOLDERNAME" & o.Source & "(" & rndno &")")
                         
                                               
                    End If
                   
               End Forall
               
          End If
         
          Set doc = view.getnextdocument(doc)
         
     Loop
Avatar of jdg995

ASKER

I got the message "Object Variable not set".  I put it in the initialize tab.  Is that correct?
Ok wait.  I will debug the code and send you again.

:)
Arun
Avatar of jdg995

ASKER

I got the message "Object Variable not set".  I put it in the initialize tab.  Is that correct?
Hi,
The problem is corrected and the code a bit changed.  Please find the necessary places and fill in your variables. Put it in the initialize event itself.

:)
Arun

PS:  The path should be like "c:\FN\" it should contain a backslash at the end.


======================================
     Dim ss As New notessession
     Dim db As notesdatabase
     Dim view As notesview      
     Dim rndno As Double
     
     Dim doc As NotesDocument
     Dim rtitem As NotesRichTextItem
     
     Set db = ss.currentdatabase
     Set view = db.getview("<<<<<View Name>>>>>")
     
     Set doc = view.getfirstdocument
     
     Do While Not doc Is Nothing
         
          Set rtitem = doc.GetFirstItem( "<<<<<<<<<Field with attachments>>>>>>>>>>>" )
         
          If doc.HasEmbedded Then
               
               Forall obj In rtitem.EmbeddedObjects
                   
                    If ( obj.Type = EMBED_ATTACHMENT ) Then
                         
                         Randomize
                         rndno = Int ( Rnd() * 1000 )
                         
                         tt = Instr(1, obj.source , "." )
                         filename1 = Left(obj.source , tt - 1)
                         filenameextn = Right(obj.source, Len(Cstr(obj.source)) - tt )
                         
                         Call obj.ExtractFile( "<<<<<<<F:\AAA\>>>>>>>" & filename1 & "(" & rndno &")" & "." & filenameextn )
                         
                    End If
                   
               End Forall
               
          End If
         
          Set doc = view.getnextdocument(doc)
         
     Loop
Avatar of jdg995

ASKER

Thanks for your dilligence Arun, but I got the same error.  I am unexperienced with Notes-- is Field the column heading where the file exists?

Thanks,
Jeff
Hi,

Open the view that has the documents.
Right mouse click on any document.
You will find the Document properties.
Select the fields tab in the info box.
You have fields listed on the leftside and the rightside you can find the info of the field.
Select the first field (You can skip the fields that are starting with the $ ).
Look to right side of the info box. You can find the fieldname, datatype and all other informations.  Find the field that has a datatype of RICHTEXT.  

The Field Name is what you have to add to the scripts Field Name.

Ofcourse I guess you dont have any problems with finding the view name.

-Good Luck !

:)
Arun
Avatar of jdg995

ASKER

The design is hidden, so I can't see the fields.  I think that I should raise the point value...
Avatar of jdg995

ASKER

Adjusted points to 250
Hi,

You need not have the design access to see this properties info box.  Anyway,

Are you here in US ?
My no is 212-778-5229.
You can call me rightaway.

If not post a comment.  This code is working perfectly.  I simulated a situation here and I debugged that code.
I am damn sure that this will work.

:)
Arun

Avatar of jdg995

ASKER

Despite all assurances, the Fields tab is blank.  Anyone have any other ideas?
Avatar of jdg995

ASKER

Adjusted points to 500
Hi JEFF !

I have got it.

Try this code without the fieldname.

The viewname and the folder names are necessary.

==============================
Dim ss As New notessession
     Dim db As notesdatabase
     Dim view As notesview      
     Dim rndno As Double
     
     Dim doc As NotesDocument
     Dim rtitem As NotesRichTextItem
     
     Set db = ss.currentdatabase
     Set view = db.getview("****viewname***")
     
     Set doc = view.getfirstdocument
     
     Do While Not doc Is Nothing
         
          If doc.HasEmbedded Then
               
               Forall m In doc.Items              
                    If m.Type = RICHTEXT Then
                         FieldName = m.Name
                         Exit Forall
                    End If                    
               End Forall
               
               Set rtitem = doc.GetFirstItem( FieldName )
               
               Forall obj In rtitem.EmbeddedObjects
                   
                    If ( obj.Type = EMBED_ATTACHMENT ) Then
                         
                         Randomize
                         rndno = Int ( Rnd() * 1000 )
                         
                         tt = Instr(1, obj.source , "." )
                         filename1 = Left(obj.source , tt - 1)
                         filenameextn = Right(obj.source, Len(Cstr(obj.source)) - tt )
                         
                         Call obj.ExtractFile( "********foldername**********" & filename1 & "(" & rndno &")" & "." & filenameextn )
                         
                         Exit Do
                         
                    End If
                   
               End Forall
               
          End If
         
          Set doc = view.getnextdocument(doc)          
         
     Loop
==============================
Really a challenging Task

:)

Arun
Hi jdg995,

Here is the my previous answer to the same question asked before, Can you please tell what  the error message is?.


                      Here is the modified scripts with attachment check.

                      To run this script create a view called "Attachments"  (personal or
                      shared) and have the selection formula as Select @All

                      Create an Agent(personal or shared)

                      select "Manually from the action Menu" in the When should this
                      agent run? option.

                      select "All new and modified documents since last run" in the Which
                      documents should it act on? option
                      (Change whatever option you want )"

                      In the scropt initialize event, paste the following script

                       'Declaration Part  
                           Dim se As New notessession
                           Dim db As notesdatabase
                           Set db = se.currentdatabase
                           Dim doc As NotesDocument
                           Dim view As notesview
                           Dim rtitem As Variant
                           
                           'Set the view and document
                           Set view = db.getview("Attachments")
                           Set doc = view.getfirstdocument
                           
                           'Loop to get all the document in the view
                           While Not doc Is Nothing
                       
                           ' Change the field Rtext with your richtext field
                                Set rtitem = doc.GetFirstItem( "Rtext" )
                                 
                             ' Check for field type , if it is Rich Text and attachment exists ,
                      copy to samples directory and remove it.
                                If ( rtitem.Type = RICHTEXT And
                      Isarray(rtitem.EmbeddedObjects) ) Then
                                     Forall o In rtitem.EmbeddedObjects
                                          If ( o.Type = EMBED_ATTACHMENT ) Then
                                               Call o.ExtractFile( "c:\samples\" & o.Source )
                                               Call o.Remove
                                               Call doc.Save( False, True )
                                          End If
                                     End Forall
                                End If
                                Set doc = view.getnextdocument(doc)
                           Wend


                      Before runnig the script, crated a directory where you want to down
                      load the files and changer corresponging path in the script. Here it is
                      c:\samples. Create "samples" in C:\.

                      This scripts take all the docuements in the view "Attachments" ,
                      then check for an attachment, if available down loads to c:\samples
                      directory (if a file with same name exists , it gives error, make sure
                      this). if no attachments in that document it moves to next
                      document.

                      To run the agent.
                      Select any view, the from the Action menu select this agent.

                      Regards,
                      Antony.
Avatar of jdg995

ASKER

Comment to both of you--

I get the same message--object variable not set whatever I try.  The only time I have run a script that did not get that message was when I ran the one at http://doc.notes.net/domino_notes/4.6/help4.nsf/93230c7de8f6e1f8852563c000631dcb/9ed9c911499d141d852564d2001718f1?OpenDocument&Highlight=2,attach

Then nothing happened, but I think it was waiting for a button event.

I'm speculating that the structure of this DB won't let me run an agent?

Anyway, I'm offline until Monday.  Thanks again.
Hi ,

Are u using this script in web (domino) application?

_Antony.
Avatar of jdg995

ASKER

I'm using Notes 5.0.1b and Domino.
Check your access to run java agents on the server, in the server document, or with your Notes Admin. Then try to rerun java agent. I know the java 'debugger' is limited so maybe you can write the info to the notes log to see what/how far it's getting. I personally think you may want to try to do it in the LotusScript provided, and debug it to see what/where the Object Variable not set comes from. It usually comes from a db, or view or doc or field that is not set before trying to use it. It also may be b/c you don't have sufficient access. Sometimes even if the code is correct, Notes won't let you read the data if you have insufficient access to the data. The example is an HR db where although you can write an agent to go get the contents of a salary field, if you don't have access to it, it won't bring anything back. Also check the access of the server (id) that's running it.
Avatar of jdg995

ASKER

I'm not sure what you mean by the Notes Log.  However, when I ran the debugger, it crapped out on the get view line.  I just put the view name in quotes, right--I don't have to qualify it or anything?

(Sorry to reject, johnkean, though you may be on to something, but I need to keep this topic open)
Depending on where you run the process from, it will write any Print statements to the notes log on the server (go to file database open, then there's a notes log named like the server, to view any reports). If you run the routine from a button, you can use the messagebox or msgbox function to print out where/what a variable's value is. It sounds promising that it crapped out at the view line, b/c that means either the database set or the view set statement failed (as opposed to say the rich text field proessing). What is the statement it's failing on, ie print it out exactly in your response, and state whether it's in the java or Lotusscript routine. I think we're pretty close.
Hi jeff

This issue seems to be of most important...

Here is the issue when u write an java agent the access to ur physical drive is limited, this is due to the security restrictions applied in the structure of JVM. When u run the java agent in notes it works fine. But on the web the Browser JVM takes the precedence(most likely as far as my knowledge goes) and doesn't allow you do that. Hence you may have to find a technique to overcome the security. This can be accomplished by using java security features.

Hope this will guide u to find a solution. writing the code is not a big deal, but it all depends how u analyze it.

Best of luck,
Hemanth
Avatar of jdg995

ASKER

Sorry, but I'm now using arunkumar's LotusScript, and I don't even know how to PrintLn.  What is the syntax?  And what should I print out?
Well,

Can you explain how you execute my script.  Through a browser ?  Or from a notes view ?

-Arun
Hi jeff,

Please reject the answer so that it will be open to others.

Also points wont go to others who have not given the right answer.

-Arun
Avatar of jdg995

ASKER

I execute it through a notes view--Manually from Actions Menu.
Hi Jeff,

If you can create a private view, then create it.  Have the selection formula as Select @ALL.  Have only one column in the view.  Let that column have @docnumber as formula. Give a name to the view.  modify the script to have the new view name.

MAKE SURE THAT THE VIEW IS NOT CATEGORISED on first column.

Run the Agent !

Good Luck !  (ATLEAST NOW)

-Arun

Feel free to REJECT if not working
Avatar of jdg995

ASKER

Gives me an invalid formula error.
Hi jdg995,

You please try this code and let me know the error message and script line if you get any error. I have created an agent and  tested this code on Lotus (5.0) and it is working fine.

1. Create Private or shared agent and give any name.

2. The agent's , When should this agent run should be "Manually from action menu"

3.The agent's which document(s) should it act should be "Selected documents"

4. In the agents initialize event , write the following script.

 'Declaration Part  
      Dim se As New notessession
      Dim db As notesdatabase
      Set db = se.currentdatabase
      Dim doc As NotesDocument
      Dim view As notesview
      Dim coll As notesdocumentcollection
      Dim rtitem As Variant
      
      
'Collect the selected document in  a document collection
      Set coll = db.unprocesseddocuments
      
     'Loop to process all the documents in document collection
      For i = 1 To coll.count
            Set doc = coll.getnthdocument(i)
            Set rtitem = doc.GetFirstItem( "<Rich text field name" )
            
       ' Check for field type , if it is Rich Text and attachment exists , copy to samples directory and remove it.
            If ( rtitem.Type = RICHTEXT ) Then
                  Forall o In item.EmbeddedObjects
                  If ( o.Type = EMBED_ATTACHMENT ) Then
      Call o.ExtractFile( "<Give the file path here>" & o.Source )
      Call o.Remove
      Call doc.Save( False, True )
      End If
      End Forall
            End If
      Next

This script will run on the selected document in the view. Select some document in the view and run from the action menu.

Please change the richtext field name and file path.

Check if it is not working , reject this answer.


Good luck,

Antony.
Avatar of jdg995

ASKER

Antony,

That won't work, because i can't see the field names.  The tab is blank.

To all,

Please look at my comment from 11/16 3:16 PM, and follow that link, as the script at that URl, while it didn't succeed, is the only one to not give me the errer "Object variable not set," and perhaps we can understand what I'm failing to do in the other cases.

Thanks again,
Jeff
Hi Jeff,
Were you able to create a private view ?

OK.  Do it without any formula.  Accept all the default values.  Even the view name.

Change the view name as reqd in the script. (It will be "Untitled").  Make sure the view name is on Quotes.

-Arun

PS: Feel free to reject if not workin.

:( - I dont want to lose the points.
Avatar of jdg995

ASKER

I think we're getting closer.  When I ran that I got a type mismatch error.  I ran the debugger and it couldn't get out of the for loop that looked for the field name.
Wait !

We are pretty close.
Will get back to you soon.

:)
Arun
Hi Jeff,

I have simulated the type mismatch in my mac and arrived at a solution.

Try the following code. With view name and the folder name changed.

=====================================
Dim ss As New notessession
     Dim db As notesdatabase
     Dim view As notesview      
     Dim rndno As Double
     
     Dim doc As NotesDocument
     Dim rtitem As NotesRichTextItem
     
     Set db = ss.currentdatabase
     Set view = db.getview("Testing")
     
     Set doc = view.getfirstdocument
     
     Do While Not doc Is Nothing
         
          If doc.HasEmbedded Then
               
               Forall m In doc.Items              
                   
                    If m.Type = RICHTEXT Then
                         
                         FieldName = m.Name
                         
                         Set rtitem = doc.GetFirstItem( FieldName )
                         
                         ' Check wether the rtitem has embedded objects                        
                         If Isarray (rtitem.EmbeddedObjects) Then
                             
                              Forall obj In rtitem.EmbeddedObjects
                                   
                                   If ( obj.Type = EMBED_ATTACHMENT ) Then
                                       
                                        Randomize
                                        rndno = Int ( Rnd() * 10000 )
                                       
                                        tt = Instr(1, obj.source , "." )
                                        filename1 = Left(obj.source , tt - 1)
                                        filenameextn = Right(obj.source, Len(Cstr(obj.source)) - tt )
                                       
                                        Call obj.ExtractFile( "F:\AAA\" & filename1 & "(" & rndno &")" & "." & filenameextn )
                                       
                                   End If
                                   
                              End Forall
                             
                         End If    
                         
                         
                    End If                    
                   
               End Forall
               
          End If
         
          Set doc = view.getnextdocument(doc)          
         
     Loop

======================================

Hope this works.

I am out for lunch.

Catch you later.

:)
Arun
Avatar of jdg995

ASKER

This time I got the message Illegal Function Call on this line:

filename1 = Left(obj.source , tt - 1)

These will be the hardest earned 500 points ever.
Assuming the file names does not repeat.....

Lets try this one

Comment the following lines
=====================
tt = Instr(1, obj.source , "." )
                                        filename1 = Left(obj.source , tt - 1)
                                        filenameextn = Right(obj.source, Len(Cstr(obj.source)) - tt )
                                        Call obj.ExtractFile( "F:\AAA\" & filename1 & "(" & rndno &")" & "." & filenameextn )
========================

Add this one line

Call obj.ExtractFile( "F:\AAA\" & obj.source )

Inplace of all the four lines.

------------------

If this works then lets do it for recurring filenames.

Good Luck !

:)
Arun

PS: YOUVE GOT access to the attached files is the positive sign now !!!
Avatar of jdg995

ASKER

It worked!  More or less...

All were detached (not just selected) and most were detached as "Att0xxxx" making them more or less useless.  Which means I now have a folder of 5000 mystery documents.  But serious progress has been made.

Do you think this didn't work before because something about the view was private?
Can you give an example of the filenames that were detached ?

-Arun
Avatar of jdg995

ASKER

I did.  They are att then four random characters.  No extension.
Like "attf92k".  I think this is the random end you assigned them, right?
Yeah !

The random number is generated by me.

Since some of your file name does not have an extension there was an error raised.  

May be I can work on this issue and post a valid answer that works for files with/without extension SOON.

*Smile*

The code actually over writes the existing files with the same name. I have to maintain the random number to the filename.

SO PLEASE WAIT....

:)
Arun
My random characters are actually random numbers within braces.

Like FileName(8674).extn

Anyway will get back to you.

-Arun
The following modified code takes care of the files without extensions also.

Change the view name and the folder name as usual and try it out.


====================================
Dim ss As New notessession
     Dim db As notesdatabase
     Dim view As notesview      
     Dim rndno As Double
     
     Dim doc As NotesDocument
     Dim rtitem As NotesRichTextItem
     
     Set db = ss.currentdatabase
     Set view = db.getview("Testing")
     
     Set doc = view.getfirstdocument
     
     Do While Not doc Is Nothing
         
          If doc.HasEmbedded Then
               
               Forall m In doc.Items              
                   
                    If m.Type = RICHTEXT Then
                         
                         FieldName = m.Name
                         
                         Set rtitem = doc.GetFirstItem( FieldName )
                         
                         ' Check wether the rtitem has embedded objects                        
                         If Isarray (rtitem.EmbeddedObjects) Then
                             
                              Forall obj In rtitem.EmbeddedObjects
                                   
                                   If ( obj.Type = EMBED_ATTACHMENT ) Then
                                       
                                        Randomize
                                        rndno = Int ( Rnd() * 10000 )
                                       
                                       
                                        tt = Instr(1, obj.source , "." )
                                       
                                        If tt <> 0 Then
                                             
                                             filename1 = Left(obj.source , tt - 1)
                                             filenameextn = Right(obj.source, Len(Cstr(obj.source)) - tt )                                            
                                             Call obj.ExtractFile( "F:\AAA\" & filename1 & "(" & rndno &")" & "." & filenameextn )
                                             
                                        Else
                                             
                                             filename1 = obj.source                                            
                                             Call obj.ExtractFile( "F:\AAA\" & obj.source & "(" & rndno &")")
                                             
                                        End If
                                       
                                   End If
                                   
                              End Forall
                             
                         End If    
                         
                         
                    End If                    
                   
               End Forall
               
          End If
         
          Set doc = view.getnextdocument(doc)          
         
     Loop
====================================
Avatar of jdg995

ASKER

Still had weird filenames, but I'm less worried about that than about the fact that it doesn't detach only the selected files.
I've been using the following code for 6 months with no problems...

In your agent, choose manually from actions menu, and then selected documents.  Open the view that shows documents you need to get the files from and select them.  Manually run the agent.  I also tested the following code with attachments that do not have an extention after the name.

  On Error Goto errortrap
     
     Dim session As New NotesSession
     Dim db As NotesDatabase
     Dim collection As NotesDocumentCollection
     Dim doc As NotesDocument
     Dim rtitem As Variant
     Dim fileCount As Integer
     Dim FirstInitial As String
     Dim LastName As String
     Dim x As Integer
     
     Set db = session.CurrentDatabase
     Set collection = db.UnprocessedDocuments
     Set doc = collection.GetFirstDocument
     
     x=1
     
     Do While Not doc Is Nothing
         
           '...set value of doc...
          Set rtitem = doc.GetFirstItem( "IDFile" )
         
          Forall o In rtitem.EmbeddedObjects
               Call o.ExtractFile ( "c:\temp\" & o.Name )
          End Forall
                   
          Set doc = collection.GetNextDocument ( doc )          
         
          'make sure agent is still running by printing doc number it processed
          Print x
         
          x=x+1
         
     Loop
     
errortrap:
     
End Sub
I now see that the person cannot see the field names, so my answer probably won't fly
if the script runs on all the documents, wont changing the :

Set doc = view.getfirstdocument
and
Set doc = view.getnextdocument(doc)            

to

Set doc = collection.getfirstdocument

Set doc = collection.getnextdocument(doc)            

do only the selected docs ?
           
     
Avatar of jdg995

ASKER

No.  It gives me the Object Variable not set message.
use
Set collection = db.UnprocessedDocuments
Avatar of jdg995

ASKER

That's what I did.
Dim collection As NotesDocumentCollection

did you include that line ?
Avatar of jdg995

ASKER

Yes I did.  I think it has some problem where it needs to initialize the view or something.
I see a bunch of good code to solve your problem, but one thing that concerns me is the fact that you cannot see any fields in the document properties.  This tells me one of two things 1) the database is corrupt or,2) all the fields on the document are encrypted.

To see if the database is corrupt, I would check the Notes log to see if you're getting any kind of "wacky" errors. (to open the Notes log:  File-> Database -> Open, type in the server name, in the file name at the bottom of the dialog box type log.nsf and click Open.  Go to the miscellaneous events view and check out the most recent entries.

Next, in either case I would still run fixup, updall, and compact on the database (these are all server tasks that will fix any corrputed views/documents, reindex the views, and remove whitespace respectively)

You'll probably have to have the Notes administrator run these for you.  Just tell them the database path, server, and that you'd like to run those three tasks on the database.

After these are all done check the document properties again.  If you still don't see anything, those fields are all encrypted, so to see them you'll need the apropriate encryption keys.  For those, you'll have to talk to the developers of the application.

I hope this gets you on track!
Avatar of jdg995

ASKER

Thanks.  I'm pretty sure that the fields are encrypted, but the keys are not available.  Still, I've been able to detach files, but not the selected, and not in any view that allows me to maintain the categorization.
ASKER CERTIFIED SOLUTION
Avatar of Arunkumar
Arunkumar

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of jdg995

ASKER

I gave up and detached them by hand.  It took a few hours, but not as long as all this!  Thanks.