%REM Description: Create a response for the given document. Use the given form name. Return the unsaved response. %END REM Public Function CreateResponse(doc As NotesDocument, form As String)As NotesDocument Dim response As NotesDocument Set response=doc.Parentdatabase.Createdocument() response.Form=form Call response.Makeresponse(doc) Set CreateResponse=response End Function %REM Description: Description: Replace the given items of the document collection with the given document's items of the same name. @param: itemNames is an array or a string conainting names separated by '^' other types provided, an error will occur %END REM Public Function StampCollection(dc As NotesDocumentCollection, doc As NotesDocument, itemNames As Variant) Dim v If Not IsArray(itemNames) Then v=Split(itemNames, "^") Else v=itemNames End If ForAll itemName In v Call dc.Stampall(itemName, doc.Getitemvalue(itemName)) End ForAll End Function %REM Description: Replace the given items of the reponses of the given document with its own items of the same name. @param: itemNames is an array or a string conainting names separated by '^' other types provided, an error will occur %END REM Public function StampResponses(doc As NotesDocument, itemNames As Variant) Dim dc As NotesDocumentCollection Set dc=doc.Responses Call StampCollection(dc, doc, itemNames) 'Call dc.StampAll(itemName,doc.GetItemValue(itemName)) End Function这样的函数创建多了,我们便可以发现进一步改进的可能。它们都与NotesDocument有关,按照面向对象语言的规范,应该将它们集中到一个对象里。这样,可以收到使用对象的诸多好处,比如可以省去参数中的NotesDocument,减少了函数名称冲突的可能性。本来根据面向对象的思想,可以考虑扩展NotesDocument成为一个新的具备更多功能的类。但是LotusScript中由产品本身提供的类是不能扩展的。继承不了,我们可以换一种方式。创建一个“包含”NotesDocument的类,在其构造函数中传入需要“增强”的NotesDocument,保存在内部变量中,然后为其增加任意需要的方法,从中引用该NotesDocument。在面向对象的架构里,要创建一个新类,利用已有的类,也不只有继承一径,还可以组合或包含。
%REM Class ExtDoc Description: Comments for Class %END REM Public Class ExtDoc Public mdoc As NotesDocument %REM Sub New Description: Comments for Sub %END REM Sub New(doc As NotesDocument) Set me.mdoc=doc End Sub %REM Function ReplaceItemValue Description: Replace the given item's value using the given "from" array to "to" array. %END REM Public Function ReplaceItemValue(itemName As String, compareArray As Variant, replaceArray As Variant) Dim v As Variant v=me.mdoc.Getitemvalue(itemName) Call me.mdoc.Replaceitemvalue(itemName, ArrayReplace(v, compareArray, replaceArray)) End Function %REM Function CopyAllTo Description: copy the document and all its descendents to another db. %END REM Public Function CopyAllTo(dest As NotesDatabase ) Call mdoc.Copytodatabase(dest) Dim dc As NotesDocumentCollection Dim rdoc As NotesDocument Dim rext As ExtDoc Set dc=mdoc.Responses Set rdoc=dc.Getfirstdocument() Do Until rdoc Is Nothing Set rext=New ExtDoc(rdoc) Call rext.CopyAllTo(dest) Set rdoc=dc.Getnextdocument(rdoc) Loop Call mdoc.Copytodatabase(dest) End Function %REM Function RemoveAll Description: Remove the document and all its descendents %END REM Public Function RemoveAll(force As Boolean) Dim dc As NotesDocumentCollection Dim docR As NotesDocument, docTmp As NotesDocument Dim ed As ExtDoc Set dc=mdoc.Responses Set docR=dc.Getfirstdocument() Do Until docR Is Nothing Set docTmp=dc.Getnextdocument(docR) Set ed=New ExtDoc(docR) Call ed.RemoveAll(force) Set docR=docTmp Loop Call mdoc.Remove(force) End Function %REM Function ComputeAndSave Description: Comments for Function %END REM Public Function ComputeAndSave() Call mdoc.Computewithform(False, False ) Call mdoc.save(True, False) End Function %REM Function CopyItemsFrom Description: Comments for Function %END REM Public Function CopyItemsFrom(source As NotesDocument, items As Variant) If IsArray(items) Then ForAll itemName In items Call mdoc.Replaceitemvalue(itemName, source.Getitemvalue(itemName)) End ForAll Else Call mdoc.Replaceitemvalue(items, source.Getitemvalue(items)) End If End Function %REM Function CreateResponse Description: Comments for Function %END REM Public Function CreateResponseDoc(form As String ) As NotesDocument Set me.CreateResponseDoc=CreateResponse(me.mdoc, form) End Function %REM Function StampResponses Description: Replace the given item of the reponses of the wrapped document with its own item of the same name. %END REM Public Function StampResponseDocs(itemName As Variant) Call StampResponses(me.mdoc, itemName) End Function %REM Function GetParentDoc Description: Comments for Function %END REM Public Function GetParentDoc() As NotesDocument Dim docResult As NotesDocument If me.mdoc.Isresponse Then Set docResult=mdoc.Parentdatabase.Getdocumentbyunid(mdoc.Parentdocumentunid) Else Set docResult=Nothing End If Set GetParentDoc=docResult End Function %REM Function IsUnique Description: Check if the wrapped document is unique in the given view. A document is unique if for the given number -- keyNum -- of sorted columns, there's no other document having the same values. That is, if a GetDocumentByKey is called with an array cotaining keyNum of keys, no other document is returned. %END REM Public Function IsUnique(viewName As String, keyNum As Integer) As Boolean Dim view As NotesView Set view=Me.mdoc.ParentDatabase.GetView(viewName) Dim doc As NotesDocument Dim keys As New NArray(-1) ForAll c In view.Columns If c.IsSorted Then keys.Add(mdoc.Getitemvalue(c.Itemname)(0)) keyNum=keyNum-1 If keyNum=0 Then Exit ForAll End If End If End ForAll Set doc=view.Getdocumentbykey(keys.Container, True) If doc Is Nothing Then IsUnique=True Else If doc.Universalid=mdoc.Universalid Then IsUnique=True Else IsUnique=False End If End If End Function %REM Function IsValueUnique Description: Check if the wrapped document is unique in the given column of the given view. %END REM Public Function IsValueUnique(value As Variant,viewName As String,columnNum As Integer) As Boolean Dim s As New NotesSession Dim view As NotesView Dim doc As NotesDocument Set view=s.CurrentDatabase.GetView(viewName) Set doc=view.GetFirstDocument Do Until doc Is Nothing If doc.ColumnValues(columnNum)=value And doc.Universalid><mdoc.Universalid Then Me.IsValueUnique=False Exit Function End If Set doc=view.GetNextDocument(doc) Loop Me.IsValueUnique=True End Function %REM Description: Check if the wrapped document is unique in the given field of the given document collection. %END REM Public Function IsValueUniqueInDC(Field As String, dc As NotesDocumentCollection) As Boolean Dim doc As NotesDocument Set doc=dc.Getfirstdocument() Do Until doc Is Nothing 'cannot compare the item value array, compare the first value instead If doc.GetItemValue(Field)(0)=mdoc.Getitemvalue(field)(0) And doc.Universalid><mdoc.Universalid Then Me.IsValueUniqueInDC=False Exit Function End If Set doc=dc.GetNextDocument(doc) Loop Me.IsValueUniqueInDC=True End Function %REM Function GetDuplicatedDoc Description: Return the first found document in the given view, which has the same value with the given document in the given column. %END REM Public Function GetDuplicatedDoc(value As Variant, viewName As String, columnNum As Integer) As NotesDocument Dim s As New NotesSession Dim view As NotesView Dim doc As NotesDocument Set view=s.CurrentDatabase.GetView(viewName) Set doc=view.GetFirstDocument Do Until doc Is Nothing If doc.ColumnValues(columnNum)=value And doc.Universalid><mdoc.Universalid Then Set Me.GetDuplicatedDoc=doc Exit Function End If Set doc=view.GetNextDocument(doc) Loop End Function %REM Obsolete Function ReplicateTo Description: Make sure the copied document has the same universal id. Direct copied documents will keep the response relations in 8.5. Modifying a document's universal id and saving it will generate another document with still a different OF part of the id. Public Function ReplicateTo(dest As NotesDatabase ) Dim doc As NotesDocument Set doc= mdoc.Copytodatabase(dest) doc.Universalid=mdoc.Universalid Call doc.Save(True, False) Set me.ReplicateTo=doc End Function %END REM %REM Obsolete Function ReplicateAllTo Description: Comments for Function Public Function ReplicateAllTo(dest As NotesDatabase) Call me.ReplicateTo(dest) Dim dc As NotesDocumentCollection Dim rdoc As NotesDocument Dim rext As ExtDoc Set dc=mdoc.Responses Set rdoc=dc.Getfirstdocument() Do Until rdoc Is Nothing Set rext=New ExtDoc(rdoc) Call rext.ReplicateAllTo(dest) Set rdoc=dc.Getnextdocument(rdoc) Loop End Function %END REM End Class
上面的CreateResponseDoc和StampResponseDocs方法分别调用了CreateResponse和StampResponses函数。当然也可以将这些函数本身包含进类中。大部分方法的作用都一看即知。稍微复杂一些的做了详细的注释,这里再略加说明。GetDuplicatedDoc,IsUnique, IsValueUnique,这些方法提到的Unique, Duplicated的含义都是针对某个视图的某个或某些列;IsUnique可以比较视图的前若干个排序列;IsValueUniqueInDC针对的是文档集合和某个字段。StampResponseDocs使用父文档的域更改子文档,参数中的域名可以是数组或由特殊字符^分隔开的字符串。CopyAllTo和RemoveAll里的All指的是连带所有子文档。ReplicateTo和ReplicateAllTo会修改目的文档的UniversalID,但是在8.5中似乎Notes会自动保持答复关系,故不再需要。
ExtDoc就像一把瑞士军刀,而且你还可以随时丰富它的功能。同样,对于其它Notes对象,你也可以制造你的瑞士军刀。