11. @DbColumn和@DbLookUp的LotusScript版本

由于Notes数据库特殊的结构,@DbColumn和@DbLookUp相当于SQL中的Select语句,是最重要和有用的公式。在LotusScript里,@DbColumn有对等的方法NotesView.GetColumnValues(),虽然帮助文档中没有记录,但是在编辑LotusScript时,这个方法都会出现在视图对象的方法列表里,返回的是一个包含在Variant里的数组。精确实现@DbLookUp的功能的方法不存在。利用NotesView.GetAllDocumentsByKey()和NotesView.GetAllEntriesByKey()可以满足对应的查找需求,不过有时候还是直接获得像@DbLookUp返回的结果那样比较方便。当然,我们可以在LotusScript里嵌入公式,但是如果有一个LotusScript的函数,就不必在两种语言间切换,还可以利用编辑器的功能确保语法的正确。那么,我们就动手自己写一个吧。

%REM
	Function DbLookUp
	Description: return an array. Values from multiple documents matched with the key are
	put in one array. If no document matches, return EMPTY
%END REM
Function DbLookUp(viewName As String, keys As variant, field As variant, dbPath As string ) As Variant
	Dim s As New notessession
	Dim db As NotesDatabase
	Dim result As Variant, v(0) As Variant
	If (dbPath="") Then
		Set db=s.Currentdatabase
	Else
		Set db=s.Getdatabase(s.Currentdatabase.Server, dbPath)
	End If
	If Not db.Isopen Then
		DbLookUp=result
		Exit function
	End If
	Dim view As NotesView
	Set view=db.Getview(viewName)
	Dim dc As NotesDocumentCollection, vc As NotesViewEntryCollection
	dim doc As NotesDocument, entry As NotesViewEntry
	Select case TypeName(Field)
		Case "STRING"
			Set dc=view.Getalldocumentsbykey(keys, true)
			Set doc=dc.Getfirstdocument()
			If doc Is Nothing Then
				Exit Function
			Else
				'result is a dynamic array with string, integer etc. elements
				result=doc.Getitemvalue(field)
			End If
			Set doc=dc.Getnextdocument(doc)
			While Not doc Is Nothing
				'result is a dynamic array with variant elements
				result=ArrayAppend(result, doc.Getitemvalue(field))
				Set doc=dc.Getnextdocument(doc)
			Wend
		Case "INTEGER"
			Set vc=view.Getallentriesbykey(keys, true)
			'Check the entry collection to avoid a bug SPR# BKOH6LVHGJ
			'When keys is a empty string, a nothing is returned.
			'https://www-304.ibm.com/support/docview.wss?uid=swg21230708
			If vc Is Nothing Then
				Exit Function 
			End If
			
			Set entry=vc.Getfirstentry()
			If entry Is Nothing Then
				Exit Function
			Else
				'if the column contains multiple values, the result is an array
				'with string, integer etc. elements; otherwise it is a scalar value
				result=entry.Columnvalues(Field)
			End If
			If IsScalar(result) Then
				v(0)=result
				result=v
			End If
			Set entry=vc.Getnextentry(entry)
			While Not entry Is Nothing 
				result=ArrayAppend(result, entry.Columnvalues(Field))
				Set entry=vc.Getnextentry(entry)
			Wend
		Case Else
			'DbLookUp=result
			'Exit Function					
	End Select
	DbLookUp=result
	
End Function

代码本身不复杂,也有少量英文注释(在编辑器中切换语言很麻烦,而且注释中也包含很多LotusScript的术语)。另外还针对NotesView.GetAllEntriesByKey()的一个bug做了处理。
参数说明:
viewName是要从中查找数据的视图名;keys是用于查找的关键词,可以是标量,也可以是数组,直接传入NotesView.GetAllDocumentsByKey()和NotesView.GetAllEntriesByKey();field是要查找的值所在的域名或视图列,根据它分别使用上面的视图的不同方法; dbPath是数据库的路径名,通常查找当前数据库时,就只需提供一个空字符串。
返回说明:
返回的是包含在Variant里的数组,查找到的所有文档的对应列或域的值都存入其中。如果无法打开数据库或没有找到找到,则返回一个空的Variant(IsEmpty()为True)。使用时,须先检查是否为空,然后取其中的值。例如,下面这个只截取结果中第一个值的函数:

%REM
	Description: Use DBLookUp to get the first value mapping the key
%END REM
Public Function GetValueByKey(viewName As String, keys As Variant, field As Variant, dbPath As String ) As Variant
	Dim values
	values=DBLookUp(viewName, keys, Field, dbPath)
	If Not IsEmpty(values) Then
		GetValueByKey=values(0)
	End If
End Function

你可能感兴趣的:(公式,LotusScript,DbColumn,DbLookUp)