Clear out "ghost" attachments
Jan 11, 2013

For a project, I had to provide a way for users to select certain images to delete out of an XPage. Displaying and giving a checkbox to delete was easy - but then I had to actually delete the images. There could be any number of attachments (all images, so I don't need to worry about type), and the user should be able to delete any of the images.
Here is where my problem came up. I could delete the embedded objects from the NotesDocument no problem - but this left "ghosts" in the rich text field. The deleted image still had an icon in the RTField, but with 0 bytes. Since the next step in the process is in classic Notes, the user there would see attachment icons that would not launch/contain anything. So I needed to get them out.
So I need to delete from the Rich Text field. But of course there could be mutliple copies of this field in the document. So if I want to delete something in the third RT Field, I have to delete the two before it, then delete - but if I save then, I have deleted the 2 fields that might have something I need to keep. So I created an agent for those documents flagged (and in my "Delete Images" view). As I check each attachment, I move it to a temporary document if it's to be kept. When I've deleted all the RTFields, I copy it back over from my temporary document (if there are any - it will fail if there is nothing there) and save it. So it also "cleans up" the document a bit, and no "ghosts".
Option Public
Option Declare

Sub Initialize
    Dim s As New NotesSession
    Dim db As NotesDatabase
    Dim doc As NotesDocument
    Dim rtItem As Variant
    Dim getIndex As Variant
    Dim item As NotesItem
    Dim tempDoc As NotesDocument
    Dim tempRTField As NotesRichTextItem
    Dim agent As NotesAgent
    Dim view As NotesView
    Const LOG_VERBOSE = True
    If LOG_VERBOSE Then Dim agentLog As New NotesLog (s.CurrentDatabase.Title & " - " & s.CurrentAgent.Name )
    If LOG_VERBOSE Then Call agentLog.OpenNotesLog ( "", "AgentLog.nsf" )
    If LOG_VERBOSE Then Call agentLog.LogAction ("Agent Started" )
    On Error GoTo ErrorHandler
    Set db = s.Currentdatabase
    Set view = db.getview("Delete Images")
    view.Autoupdate = False
    Set doc = view.Getfirstdocument()
    Do While Not doc Is Nothing
        'Set agent = s.Currentagent
        'Set doc = db.Getdocumentbyid(agent.Parameterdocid)
        If LOG_VERBOSE Then Call agentLog.LogAction("DocID: " + doc.Noteid)
        Set tempDoc = db.Createdocument()
        Call tempDoc.Replaceitemvalue("Form", "RTfieldHolder")
        Set tempRTField = tempDoc.Createrichtextitem("body")
        If doc.Hasitem("delImage") Then

            Set item = doc.getFirstItem("delImage")
            If LOG_VERBOSE Then Call agentLog.Logaction("I have the item " + doc.delImage(0))
            ForAll x In item.Values
                If LOG_VERBOSE Then Call agentLog.Logaction(x)
            End ForAll

            ForAll x In doc.Items
                If UCase(x.Name) = "BODY" Then
                    Set rtItem = doc.Getfirstitem("Body")
                    If rtItem.Type = RICHTEXT Then
                        ForAll o In rtitem.EmbeddedObjects
                            If ( o.Type = EMBED_ATTACHMENT ) Then
                                Print("checking on (" & o.Name & ")")
                                'see if it's one we need to delete
                                getIndex = ArrayGetIndex(item.Values, o.Name, 5)
                                If Not(IsNull(getIndex)) Then
                                    'Delete it
                                    Print("deleting (" & o.Name & ")")
                                    Call o.Remove
                                    Print("Keeping " & o.Name)
                                End If        
                            End If
                        End ForAll        
                    End If
                    If LOG_VERBOSE Then Call agentLog.Logaction("temp body size: " & tempRTField.Valuelength)
                    If tempRTField.valueLength < 2 Then
                        'do not add, nothing of any significant size
                        Call tempRTField.Appendrtitem(rtItem)
                    End If
                    Call x.Remove
                End If
            End ForAll
            Call doc.Removeitem("delImage")
            'Copy the items back to the original document
            Dim newItem As NotesItem
            Set newItem = tempRTField.CopyItemToDocument(doc, "body")
                'only copy over if there is something significant
            'Save the original doc, but not the temp doc
            Call doc.Save(True, False)
            If LOG_VERBOSE Then Call agentLog.Logaction("just saved doc")
            If LOG_VERBOSE Then Call agentLog.Logaction("no delImages recorded")
        End If
        Set doc = view.Getnextdocument(doc)
    view.Autoupdate = true
    GoTo TheEnd
    If LOG_VERBOSE Then Call agentLog.LogError ( Err, "Line " & Erl & ": " & Error$ )
    Resume TheEnd
    If LOG_VERBOSE Then Call agentLog.LogAction ( "Agent Finished" )
    If LOG_VERBOSE Then Call agentLog.Close
End Sub


Add a Comment 
More Actions 
Comments (2)

1 Theo Heselmans commented Jan 14 2013 Permalink Recommendations 0
Very nice solution, thanks for sharing. 
Could you elaborate a bit more on how you got those ghost attachments in the first place? I have those sometimes too, but don't know what part of my code causes them.

2 Brian M Moore commented Jan 14 2013 Permalink Recommendations 0
@Theo - I'm not sure, it happens if you remove the attachment via a NotesEmbeddedObject from a NotesDocument, the "ghost" (an icon in front of file of 0 bytes) will show in the RichTextField. If you remove it from the RichTextField, no "ghost".


I would surmise this is because the file isn't really in the RT Field, but in a $FILE field. Removing from the NotesDocument removes the $FILE, but doesn't touch the part of the Rich Text field that points to that $FILE, so that the attachment could be accessed from the RT Field.
This is an archive of my previous blog attachments are in the download control