Link to home
Start Free TrialLog in
Avatar of lcuksch
lcuksch

asked on

Can I detach a bulk load of attachments from a Lotus Notes DB?

Lotus Notes Version 4.6.7.
I have a fairly simple database set-up, which contains various notes documents under a few different headings.
Most of the documents contain attachments, such as Word, PPT, Excel documents etc.

I need to review & migate these attachments to a new system, is there a way I can do a bulk unload of all the attachments to say a network drive?
(I'm trying to avoid going in to every dingle document & detaching the attachment)
(I don't care about the actual Notes documents, it's only the attachments I'm interested in)
Thanks!
Avatar of madheeswar
madheeswar
Flag of Singapore image

yes. It can be done. But u need to write an agent (Lotus Script) to do it.

Currently I don't have the code. Let me check if I can find some code or not.
Avatar of mcjann
mcjann

lcuksch,

I have done the very thing you are attempting. Run the code on selected documents, that could be all the documents if you like, from an action button .  It may work elsewhere but I have only used from an action button.

'Remove attachments from a file
'This is a 2 part action
'Part 1 determines if a document in the collection is present. If it is the part 2 is activated otherwise end of sub



Sub Click(Source As Button)
      Dim session As New NotesSession  
      Dim db As NotesDatabase  
      Dim collection As NotesDocumentCollection  
      Dim doc As NotesDocument  
      Set db = session.CurrentDatabase  
      Set collection = db.UnprocessedDocuments  
      For i = 1 To collection.Count    
            Set doc = collection.GetNthDocument( i )  
            If doc.HasEmbedded Then    
                  Call detachFiles( doc )    
            End If
      Next
End Sub

'This will through a type mismatch if the field that contains the item is not rich text or the field name is not correct

Sub detachFiles( doc As NotesDocument )
      Dim rtitem As Variant

      Set rtitem = doc.GetFirstItem( "your rt field name here" )
      Forall o In rtitem.EmbeddedObjects
            If o.Type = EMBED_ATTACHMENT Then  
              Call o.ExtractFile( "h:\your location\directory\" & o.Source )
              ' use Remove statement after testing and only when you want to delete the item as well as copy it.
                'Call o.Remove
                  Call doc.Save( False, False)  
            End If
      End Forall
End Sub


Avatar of lcuksch

ASKER

Thanks both of you for your answers.  I need to get some access rights sorted out & then I will try the suggestions.  I will come back & grade the answers after that. May be a few days!
lcuksch,

Tell me this, can you create a custom view in the database?
From the file menu can you access database, new copy?

If so I would suggest making a local copy and testing then running the action in that local database.
When creating the new copy selecte the database design and documents choice and deselect the "access control list." Then you should be able to create your view and place the action in the view.
Avatar of lcuksch

ASKER

You must have read my mind. I did create a new copy, thinking I would automatically have access priveledges, but found I had none.  (Can you tell I am no Notes expert?)
I will try what you say, sounds like that should work for me.
Yes, be sure to delselect the box to copy access control list. A new copy without acl should give your the access you need. Beside I prefer to test on something I can mess up.
Avatar of lcuksch

ASKER

I originally tried to run one of madheeswar's links but got a 'type mismatch.'
So I tried mcjann's code, I have an action button in a doc coded as :-

@Command([ToolsRunMacro];"Save attachments")

But that doesn't seem to do anything.  What am I doing wrong?  Assume I am 5 years old.
This will do it efficiently, and wil also sure each file anme is unique (since two documents coudl contain teh same attachment name).

Set it up as an agentto run against selected documents:

Const path = "C:\BULK\"
DIm s as new notesSession
Dim db as notesDatabase
Set db = s.currentDatabase
DIm docs as notesDocument
Set docs = db.unprocessedDocuments
Dim doc as notesDocument
Set doc = docs.getFitsDocument
Dim fileNames, fileObj as notesEmbeddedObject, dotPos as integer, lastDotPos as integer
Do Until doc is nothing
  if not doc.hasItem("$File") then goto skip
  fileNames = Evaluate("@AttachmentNames",doc)
  forall filename in fileNames
    set fileObj = doc.getAttachment(filename)
    lastDotPos = len(filename+1)
    dotPos = Instr(filename,".")
    do until dotPos = 0
      lastDotPos = dotPos
      dotPos = Instr(dotPos+1,filename,".")
    loop
    filename = left(filename,lastDotPos-1) & " (" & doc.noteID & ")" & mid(filename,lastDotPos)
    fileObj.extractFile path & filename
  End Forall
skip:
  Set doc = docs.getNextDocument(doc)
Loop

lcuksch,

that button should work as long as the code I sent previous is pasted into the initialize section of an agent titled "Save attachments."

Your agent should be a lotus script.
Click on the "initialize" section and paste this code directly between the sub and end sub. Save the agent as "Save attachments"

Dim session As New NotesSession  
      Dim db As NotesDatabase  
      Dim collection As NotesDocumentCollection  
      Dim doc As NotesDocument  
      Set db = session.CurrentDatabase  
      Set collection = db.UnprocessedDocuments  
      For i = 1 To collection.Count    
            Set doc = collection.GetNthDocument( i )  
            If doc.HasEmbedded Then    
                  Call detachFiles( doc )    
            End If
      Next
Sub detachFiles( doc As NotesDocument )
      Dim rtitem As Variant
      Set rtitem = doc.GetFirstItem( "Body" ) ' update rt field name here
      Forall o In rtitem.EmbeddedObjects
            If o.Type = EMBED_ATTACHMENT Then  
                  Call o.ExtractFile( "h:\data\RMs\" & o.Source ) ' update your directory here
                  'Call o.Remove ' use Remove statement only when you want to delete the item as well as copy it
                  Call doc.Save( False, False)  
            End If
      End Forall
End Sub

In the "detachFiles" event besure to update the field name and directory or you will get an object requred error.

Now your smart icon should call the agent. You'll get there!!!!
Avatar of lcuksch

ASKER

I tried your code, but the script gets a type mismatch on :-
Set docs = db.unprocessedDocuments  ??
the code line you specified in not in the code sent but a type mismatch will occur if the field that contains the item is not rich text or the field name is not correct check both of these.

See comments in the detachFiles event
Avatar of lcuksch

ASKER

OK mcjann, going back to your last bit of code, I've done that & it looks OK.  I pasted it all in initialise & it got split, so the first part remains in 'initialise' & there is also now a 'detachfiles' heading with the second bit of code.
I think the field I am looking for is called 'Body',(which is a 5318 length rich text field).  The docs are all free form things which allow for attachments to be placed anywhere within the text.

Maybe I am running the acton button from the wrong place.  Using Notes help, I created a document under a random heading in my database & created the hotspot button within the document.  I run it from there, is that right?  It still doesn't do anything.

(The type mismatch error wasfrom qwalitee's code)
It won't work from an action button, instead go to file>preferences>SmartIcon settings.
in the "Available Icons" list scroll to the bottom and pick a macro button. Drag the button to the end of your icons in use list.

Select that macro icon in your icons list and click edit icon. Here is where you will paste @Command([ToolsRunMacro];"Save attachments")
Then click "Done" and "OK". The new SmartIcon should appear on your toolbar.

Go to your database and view, don't open a document just select the documents you want to run the agent on then click the SmartIcon. This will execute the agent against selected documents in the database.

Sorry, I didn't see qwalitte's code  but he did raise a good point about attachments with the same name. Is that a possiblity in your database? Even if it isn't you may consider appending a document number or somthing to your copied file to enable quick identification of the host document. Just a thought
lcuksch,

> I tried your code, but the script gets a type mismatch on :-
> Set docs = db.unprocessedDocuments  ??
Oops:

Dim docs as notesDocumentCollection 'I didn't put in COLLECTION

- qwaletee
Another thing to watch out for is "V2 style attachmets," wherethe attachmen is not associated with a rich text field.  These appear as icons below a blak rule at the bottom of the document. My code does process these, mcjann's may not.
Avatar of lcuksch

ASKER

Here's where I'm at with this, it's driving me crazzeeeeee, but I do appreciate everyone's help.

I ran mcjann's code last night from a smarticon.  I selected one document with an attachment, & it didn't seem to work.  So I selected a few docs & got a memory referenced crash, had to reboot etc.  I suspect this is because I may be referencing the worng field.

So, this morning, I tried running qwalitee's code from a button within a document, & nothing happens there either.

Apart from turning my PC on,what else am I doing wrong?
lcuksch,

What version of notes and operating system are you on?
Did the code execute without errors?
If so, you may be looking in the wrong field for your attachment and when nothing is placed in your directory it appears that nothing happened. You are on the right track if your documents have mulitple rt fields then find another change your code and try that field.

Avatar of lcuksch

ASKER

Mcjann, It's notes 4.6.7.  Being decommissioned here, hence the reason for my little project.

The code seems OK, except when I run multiple docs, Notes just errors & chucks me out.

Just one question, at the bottom of the script input in the agent design screen, there is a button called 'fields & functions'.  Should the RT field I am looking for be present in the field list in there, or is it something I needto work out from theform design & manually type in the code?

Ta.
If it is listed there it will only list a field name.
To find the fields in a document select a document in a view and go to File>Document Properties. Click the second tab (Fields). On the left you can scroll through a list of fields in the document and when selected in this list the list on the right will display the field information. The first item is field name and second is data type. To hold an attachment a field's data type must be Rich Text. Find your document's rich text fields and copy the name directly from the field information and paste it into your code. Unless this help you identify you spot your field try each rt field. Also keep in mind that a database could hold documents based on multiple forms. For each form present you may need to modify and run the code because the rt field name may change.  A field $FILE indicates a file attachment is in the document.
Avatar of lcuksch

ASKER

OK, I have done what you said, there are three fields called 'Body' they are the only rich text fields in the document.
Could the duplication be causing the crash with code?
They have a duplicate ID Number of 0, 1 & 2.
ASKER CERTIFIED SOLUTION
Avatar of qwaletee
qwaletee

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 lcuksch

ASKER

Qwalitee, Many thanks, I finally got this working this morning.
We are moving to Outlook.

Just to clarify for anyone like me that isn't a Notes Expert who wants to reuse this code:-

Create an Agent called 'Save attachments'
Paste the code from the previous entry as is in the initialise script in your Agent.  No need to change anything, just create the directory 'C:\BULK'.
Crate a macro smarticon, that contains the following code:-
@Command([ToolsRunMacro];"Save attachments")

Select the documents from the database view, & then run your smarticon from the toolbar.
Works great.

Mcjann, thanks also for your efforts.
lcuksch,

> Paste the code from the previous entry as is in the initialise script in your Agent.  No need
> to change anything, just create the directory 'C:\BULK'.
> Crate a macro smarticon, that contains the following code:-

Yo don't need teh SmartIcon.  If the agent is set to run from actions menu, you can click on teh actions menu as you will see "Save attachments" is there.

- qwaletee
Hello all,

This code is a nice one for regular attachments, however there are cases when we have documents not as regular attachments, but as OLE documents. Can anybody provide a sample code which dumps to disk all OLE documents?

Thanks in advance
Dainius