Als Klasse mit zugegebenermassen zu wenig errorhandling
Public Class DocCopyFactory
Private db As NotesDatabase
Private fieldNames As Variant
Sub New (fieldNamesIn As String)
' first get the names of the fields which should be copied.
' if (fieldNamesIn == null) throw new ilegalArgumentException (no idea how to code that in LS)
' extracted as tokens separated by ~ (by convention)
fieldNames = Split(fieldNamesIn, "~")
Dim s As New NotesSession
Set db = s.CurrentDatabase
End Sub
Public Function copyDocument(docToCopy As NotesDocument, formCopyDocument As String) As NotesDocument
' document to return
Set copyDocument = db.createDocument ' return value
copyDocument.form=formCopyDocument
' copy the items
Dim itemDocToCopy As NotesItem
Forall fieldName In fieldNames
Set itemDocToCopy = docToCopy.GetFirstItem(fieldName)
If Not itemDocToCopy Is Nothing Then
Call itemDocToCopy.CopyItemToDocument(copyDocument, fieldName)
Else
' do some better errorhandling or logging than this.
Print "NO GOOD. The item " + fieldName + " does not exist in the document to be copied."
End If
End Forall
End Function
End Class
wird so angesprochen:
(Client code für Klasse)
Dim s As New NotesSession
Dim docOriginal As NotesDocument
Dim docNochneKopie As NotesDocument
Dim aDocCopyFactory As New DocCopyFactory("item1~item2~item3")
Set docOriginal = s.DocumentContext
Set docKopie = aDocCopyFactory.copyDocument(docOriginal, "Kopie von original")
docKopie.save True, False
Set docNochneKopie = aDocCopyFactory.copyDocument(docOriginal, "Kopie von original")
docNochneKopie.save True, False
In der Beispiel DB in Agenten DocCopyFactory.
In BeispielDB sich in der Ansicht "Alle" auf das einzige Dokument stellen und dann den einzigen button mit der Beschriftung "push the button" drücken. Der startet den Client code für die Klasse (im Agenten DocCopyFactory).
Man kann ja noch eine weitere Methode hinzufügen, die auch das mapping
original.feldname1 -> kopie.feldnameAnders
anbietet.
Ich weiss auch nicht ob klassische Funktionen in Scriptlibraries hier nicht die bessere Lösung darstellen.
Da ich seit gestern dynamic languages Programmierer bin (hab mein erstes Groovy script geschrieben), seh ich das sowieso nicht mehr so ideologisch. ;D . (What joker needs curly braced language. My tackle is much lighter than this crap)
Die Klasse führt da auf jedenfall eine gewisse Rigidität ein.
Vielleicht ist es besser das als Funktion zu programmieren:
public Function copyDocument(docToCopy As NotesDocument, formCopyDocument As String, fieldNamesIn As String) As NotesDocument
Dim fieldNames As Variant
Dim db as notesDabase
Set db = docToCopy.CurrentDatabase
fieldNames = Split(fieldNamesIn, "~")
' document to return
Set copyDocument = db.createDocument ' return value
copyDocument.form=formCopyDocument
' copy the items
Dim itemDocToCopy As NotesItem
Forall fieldName In fieldNames
Set itemDocToCopy = docToCopy.GetFirstItem(fieldName)
If Not itemDocToCopy Is Nothing Then
Call itemDocToCopy.CopyItemToDocument(copyDocument, fieldName)
Else
' do some better errorhandling or logging than this.
Print "NO GOOD. The item " + fieldName + " does not exist in the document to be copied."
End If
End Forall
End Function
Hier eine Variante meinerseits...
Public Class DocumentCopierFactory
Private source As NotesDocument
Private fieldMap List As String
Private form As String
Public Sub new(source As NotesDocument, formName As String, fields List As String)
If formName = "" Or source Is Nothing Or Isempty(fields)Then
Exit Sub
End If
Set Me.source = source
Me.form = formName
Forall entry In fields
Me.fieldMap(Listtag(entry)) = entry
End Forall
End Sub
Public Function copyDocument(targetDb As NotesDatabase) As NotesDocument
Dim session As New Notessession
Dim newDoc As Notesdocument
Dim db As NotesDatabase
If Not targetDb Is Nothing Then
Set db = targetDb
Else
Set db = session.CurrentDatabase
End If
Set newDoc = db.CreateDocument
newDoc.Form = form
Forall entry In Me.fieldMap
Call newDoc.ReplaceItemValue(entry, source.GetItemValue(Listtag(entry)))
End Forall
Set copyDocument = newDoc
End Function
End Class
Ich habe mich meiner Klasse nochmal angenommen und einen Hinweis von Norbert einzubauen:
Immer, wenn ich beim Kopieren irgendwo "GETFIRSTITEM" lese, denke ich mir, daß die Methode nicht umsonst so heißt - daß es also mehrere gleichnamige Feld(Teile) geben kann.
Und da sind wir mitten im Schlamassel. Die Klassenmethode muß also letztlich mehr leisten, z.B. das Dokument erst einmal in ein neues virtuelles Dokument kopieren und in dem die ITEMS durchorgeln. Bei einem Kopierkandidaten dann das gefundene GETFIRSTITEM removen und nach einem weiteren GETFIRSTITEM des gleichen Namens suchen usw.
Jedoch frage ich mich gerade, wann ein Item mehrmals vorhanden sein soll und woran man das erkennen kann. Intuitiv dachte ich zuerst, dass man das an den Dokumenteigenschaften erkennen kann (siehe Screenshot im Anhang), wenn ein Feldname mehrmals auftaucht. Scheinbar ist das aber so nicht korrekt, denn wenn ich meine modifizierte Klassse in der ich mit dem virtuellen Dokument arbeite auf diesem Dokument aufrufe, durchläuft er mir meine Schleife, die so lange Items entfernen und kopieren soll, nur ein einziges mal. Kurioserweise taucht das Item im Debugger aber auch nur ein einziges mal auf.
Hier die Schleife:
'iterate over the map of field names
Forall entry In Me.fieldMap
Dim item As NotesItem
'get item the first time
Set item = virtual.GetFirstItem(Listtag(entry))
Do
'copy item to new document, as long as there are items with the same name
Call item.CopyItemToDocument(newDoc,entry)
Call item.Remove()
'Set item = Nothing
Set item = virtual.GetFirstItem(Listtag(entry))
Loop Until item Is Nothing
End Forall
Ich frage mich gerade ob ich jetzt falsch denke oder ob LS vielleicht mehrere gleichnamige Items zu einem wieder zusammensetzt... ???