lotus notes 开发常用方法

类别:编程语言 点击:0 评论:0 推荐:

一、关于AppendItemValue

试试下面这个简单的例子:

Dim ws As New notesuiworkspace

Dim uidoc As notesuidocument

Dim doc As notesdocument

Set uidoc=ws.currentdocument

Set doc=uidoc.document

For i=1 To 10

Call doc.appenditemvalue("myitem",i)

Next

Call doc.save(True,True )

这个程序用以对当前文档增加10个ITEM,名字都叫myitem,但值从1到10不等。结果如何?用调试方式进行观察,发现:确实增加了10个ITEM,名字都叫myitem,但值却都是1!这与NOTES中的帮助不符。帮助里宣称:

If the document already has an item called itemName$, AppendItemVa

lue does not replace it.

Instead, it creates another item of the same name, and gives it th

e value you specify.

^^^^^^^^^^^^^^^^^^^^

从4.6到5.0结果都一样。

 

二、区分NOTES的前台类与后台类

由于两者的使用范围不一,在写程序时应注意这一点,尤其写代理时。如果在后台服务器运行的代理里加一句:

Dim ws As New notesuiworkspace

代理运行日志报错:Unkown Error.

 

三、关于NOTES与OLE的共享域

NOTES提供了一个很好的功能:共享域。NOTES用共享域来与OLE应用程序交换彼此信息。但除非确有必要与OLE应用程序共享信息,建议在设计表单时,选上:禁止共享域。 笔者曾在一个表单中创建了一个作者域AUTHOR,又在它的RTF域中嵌入MS-WORD文档:

CALL UIDOC.CREATOBJECT("MYDOC","WORD.DOCUMENT.8","")

似乎一切都正常。但当我变更了NOTES的作者域AUTHOR(因笔者试图通过作者域的改变来控制NOTES文档的修改进而达到流程控制的目的),因为流程的需要,我把它变成了两个值,在NOTES中显示为:

user1/co1/server1,user2/co1/server2

然后对RTF域中所嵌入的WORD文档进行了修改,然后退出,保存。结果问题出现了,NOTES报错:你不是文档的作者,不能保存! 什么原因?当时我明明是用user1/co1/server1进行修改的!后来,仔细调试,把AUTHOR的隐藏属性去掉,仔细观察,发现只要激活了RTF域中嵌入的WORD文档,在RTF域中退出来时AUTHOR的值竟变成了:

user1/co1/server1/co1/server2!

原来,WORD也有一个作者域,名字也叫AUTHOR(似乎是不能改变的)WORD的AUTHOR与NOTES的AUTHOR相互影响(怎么影响?我也不知道),于是变出了上面的这个怪东西!解决办法,当然,就是把NOTES表单“禁止域交换”了!(OLE应用程序有太多的域,想弄清这些域的名字,似乎不太可能。所以“禁止域交换”应是解决这类问题的最好办法了,窃以为)

 

四、使用NOTES整合OA应用、OFFICE弥补NOTES不足







Sub Entering(Source As Field)

Dim curws As New notesuiworkspace

Dim uidoc As notesuidocument

Set uidoc=curws.currentdocument

lnflag=uidoc.fieldgettext("docadd")

If lnflag=0 Then

Call uidoc.fieldsettext("docadd","1")

Call uidoc.createobject("worddoc","word.document.8","")

End If

Exit Sub

End Sub

当提交后,须记录并显示编辑者对WORD文档的所有修改,故而要将WORD文档改成修订状态。在提交按钮中,写如下程序:

Sub Click(Source As Button)

Dim ws As New notesuiworkspace

Dim uidoc As notesuidocument

Set uidoc=ws.currentdocument

Dim curdoc As notesdocument

Set curdoc=uidoc.document

Dim worddoc As notesembeddedobject

Dim wordapp As Variant

 

Call ws.editdocument(True)

lnflag=uidoc.fieldgettext("docadd")

If lnflag="1" Then

Set worddoc=curdoc.embeddedobjects(0)

Set wordapp=worddoc.activate(False)

Call worddoc.doverb("编辑(&E)")

wordapp.application.visible=False

wordapp.application.activedocument.trackrevisions=True

wordapp.application.activedocument.showrevisions=True

Call wordapp.application.activedocument.save

Call wordapp.application.exit

End If

Call uidoc.save

Call ws.editdocument(False)

End Sub

上述修改WORD文档为修订状态的那段程序,其实可以改为:

Set wordapp=uidoc.GetObject("worddoc")

wordapp.application.visible=False

wordapp.application.activedocument.trackrevisions=True

wordapp.application.activedocument.showrevisions=True

Call wordapp.application.activedocument.save

即通过UIDOC的GetObject方法进行访问。




但通过OLE对象访问时,应注意拼写的正确性,尤其是能过指明OLE对象名称(而不是文件名称)来创建时,更应注意OLE对象名称的拼写正确





性。否则,错误难以预料。例如,在RTF域的Entering事件中将创建对象语句按如下修改:

把: Call uidoc.createobject("worddoc","word.document.8","")

改为: Call uidoc.createobject("worddoc","word.document","")

OLE对象还是可以创建,一切似乎都很正常。但是当执行提交时,若通过EmbeddedObject的访问文档,则在Set wordapp=worddoc.activate



(False)时出错:不能储存对象。

若通过UIDOC的GetObject方法进行访问,则在

wordapp.application.activedocument.trackrevisions=True时出错:没有激活文档。

 

五、使用APPENDTOTEXTLIST

APPENDTOTEXTLIST增加文本列表项。使用方法如下:

Dim rtitem as notesitem

dim uidoc as notesuidocument

dim ws as notesuiworkspace

dim curdoc as notesdocument

set uidoc=ws.currentdocument

set curdoc=uidoc.document

set rtitem=curdoc.getfirstitem("authors")

lcreader=curdoc.getitemvalue("readers")

 

for i=0 to ubound(lcreader)

call rtitem.appendtotextlist(lcreader(i))

next

上例把多值域READERS的值逐个追加到另一个多值域AUTHORS中。要实现这种目的,还有一种办法,即:通过NOTESDOCUMENT的GETITEMVALUE方法




分别把两个域的值放到两个数组中,再合并两个数组到一个新的数组中,通过调用NOTESDOCUMENT的REPLACEITEMVALUE方法把新数组的值赋给





AUTHORS。但显然这种方法,编程量要大得多。 也许有人会说,为什么不用字符串的相加,再通NOTESUIDOCUMENT的FIELD SETTEXT把相加后的字




符串赋给相应的域?按NOTES的说明及其相应的帮助来说,这应该是可以的(当然,两个字符串之间的分隔符应用设计域时指定的分隔符分





开)。但实际上,这种方法极不可靠!尤其是两个域的值均为姓名时,实在无法保证这样运算产生的结果是怎样的。NOTES对姓名域有自己的处




理办法,但它怎样将前台显示的姓名转换成后台的姓名?只怕没人能搞得清楚。本人有试过这种方法。当只有一两个值时,这种运算一般不会







错;但当值多时(我试的时候有7个左右),有时一切正常,有时出现的错误不可思议:NOTES居然把整个字符串当做一个值!它竟然根本没有理




会域的多值分隔符!还要注意一点,不须通过NOTESDOCUMENT的SAVE方法,上例所做的变更依然有效。NOTESITEM的变量应是指向相应文档的指针








(我猜的)。

 

六、NOTES的ODBC支持缺陷

 

A NOTES无法支持后台数据库(如ORACLE)的预储程序Stored Procedure,即使新版的6.2也是如此。尽管帮助自称有提供运行后台数据库SP的函数(resultset.execprocedure),但其实并不起作用。

 

B 如果在一个odbc connection中有多句SQL的话,会出错:too many cursor。尽管你的sql语句根本不含cursor。Lotus自称在4.6及以后版本中,这个bug已解决,不过,答案也确是如此

 

七、NOTES的数组

A 定义数组

有两种方式:DIM和REDIM。

DIM定义的是固定个数、数据类型的数组;而REDIM则不同,它可以定义不同类型的数据,也可以定义个数并非固定的数据。比较下面几个例子。 都合法的例子:

Dim myarray(5,2) as string Redim myarray(5,2) as string

前者错误而后者合法的例子:

n=10 n=10

Dim myarray(n) as string Redim myarray(n,2) as string

另外REDIM还可以定义未定类型的数组,如:Redim myarray(10)

 

B 数组个数

在以DIM或REDIM定义数组时指定的下标,表示的是访问该数组时所容许的最大下标,却不是该数组的个数。实际上,一维数组个数总是等于(最




大下标+1),访问时是通过下标从0开始逐个访问的。

比如:Dim myarray(5) As String定义的数组元素有6个,分别是:myarray (0)、

myarray(1)、myarray(2)、myarray(3)、myarray(4)、myarray(5)。

再如:Redim thisarray(2,5) As String 实际上定义了一个(2+1)*(5+1)=1 8的二维数组。

既然如此,那么,可不可义定义一个只有一个元素的数组呢?答案是:不可以。

如前所说,Redim thisarray(1)定义的数组实际上有(1+1)个数组元素,但类似于: Redim thisarray(0)的语法,NOTES又认为是错误的。所以,





不能定义一个只有一个数组元素的数组。其实,以上说的只是其默认状况。其实,定义数组可以通过定义下标的起止从而达到定义数组的个数甚





至下标的起止编号的。比如:Redim thisarray(1980 to1990)就 定义了一个含有11个元素的数组,下标从1980到1990。

 

C 关于UBOUND函数

UBOUND返回的是一维数组的最大下标,而不是元素个数。比如:Dim Myarray(5) As Integer,那么UBOUND(Myarray)返回的值是5,而不是6。





UBOUND也可以应用于二维数组。应用于二维数组时,它返回的是第一个下标的最大值。

比如:Dim Myarray(6,3) As Integer,

那么UBOUND(Myarray)返回的值是6,而不是7,更不是18(6*3=18)。

若要返回第二个下标的最大值,则使用:UBOUND(Myarray,2)。

与UBOUND相对应的是另外一个函数:LBOUND,它返回数组的最小下标。与UBOUND类似,LBOUND(Myarray,2)则返回数组MYARRAY的第二个下标的最





小值。所以,准确地说,一维数组Myarray的元素个数为:UBOUND(Myarray)-LBOUND(Myarray)+1,而二维数组的元素个数则为:

(UBOUND(Myarray)-LBOUND(Myarray)+1)*(UBOUND(Myarray,2)-LBOUND(Myarray,2)+1)

多维数组依此类推。

 

D 返回数组的函数

可以定义一个函数,使其返回数组。宣告函数时只要宣告它返回Variant型即可

。如下例:

Function db_string(Byval fdname As String) As Variant

fdnum=Len(fdname)

Redim lcarray(fdnum,2) As String

lcarray(0,0)="thisstr"

lcarray(0,1)=","

lcarray(0,2)=","

......

db_string=lcarray '使函数返回数组lcarray的值

End Function

在调用函数时,以如下方式调用:

thisstring="AAAAAAAA"

Dim Thisarray As Variant

thisarray=Db_string(thisstring)

print thisarray(0,0)

 

 

八、

NOTES的ODBC:(LS:DO)

A 使用LotusScript编写ODBC程序时需要掌握的几个类:ODBCConnection、ODBCQ

uery、与

ODBCResultSet。通常做法为:

Set con = New ODBCConnection

Dim dbqry As New ODBCQuery

Dim dbresult As New ODBCResultSet

ret=con.ConnectTo(DBSOURCENAME,DBUSERNAME,DBPASS)

If con.isconnected=False Then

ret1=Msgbox("数据库无法连接,请洽系统管理员",48,"提示信息")

odbc_insert=-2

Exit Function

End If

 

dbqry.sql="select * from THISTABLE where THISTABLE.ID=THISID"

Set dbqry.Connection = con

Set dbresult.query=dbqry

dbresult.execute

%REM

通过dbresult访问关系数据库:取值、更新数据库

%END REM

status=dbresult.close(db_commit)

ret=con.disconnect

 

B 通过ODBCResultSet更新数据(插入、删除、修改),可以有两种方式。一种方式如上例,对ODBCQry.SQL赋为查询语句,然后能过





ODBCResultSet类的ADDROW、UPDATEROW、DELETEROW 及SETVALUE等方法更新关系型数据库。如下例,对THISTABLE增加一笔记录,并赋字符串型





字段field1的值为test:

Set con = New ODBCConnection

Dim dbqry As New ODBCQuery

Dim dbresult As New ODBCResultSet

ret=con.ConnectTo(DBSOURCENAME,DBUSERNAME,DBPASS)

If con.isconnected=False Then

ret1=Msgbox("数据库无法连接,请洽系统管理员",48,"提示信息")

odbc_insert=-2

Exit Function

End If

 

dbqry.sql="select * from THISTABLE where 1=0"

Set dbqry.Connection = con

Set dbresult.query=dbqry

dbresult.execute

Call dbresult.addrow

Call dbresult.setvalue("field1","test")

Call dbresult.updaterow

 

status=dbresult.close(db_commit)

ret=con.disconnect

由于updaterow方法只有对只含一笔记录的ODBCResultSet才有效(多笔时会报错),故而在SQL中的条件中只有一个永远不成立的条件:1=0,以




保证在执行addrow之后在updaterow 之前ODBCResultSet中只有一笔。 另外一种方式是直接用SQL语句更新数据库。它的好处在于一次可以更新





多笔,而且比较灵活,坏处则在于必须考虑DOMINO与后台关系数据库之间的数据类型的转换。如下例,可以达到与上例一样的效果。

Set con = New ODBCConnection

Dim dbqry As New ODBCQuery

Dim dbresult As New ODBCResultSet

ret=con.ConnectTo(DBSOURCENAME,DBUSERNAME,DBPASS)

If con.isconnected=False Then

ret1=Msgbox("数据库无法连接,请洽系统管理员",48,"提示信息")

odbc_insert=-2

Exit Function

End If

 

dbqry.sql="insert into THISTABLE (THISID) values ('test')"

Set dbqry.Connection = con

Set dbresult.query=dbqry

dbresult.execute

status=dbresult.close(db_commit)

ret=con.disconnect

 

C 关于类型转换

通过ODBCResultSet更新数据时通常要进行类型转换。通过上述的方式一中的方法更新数据 库可以不用类型转换即可更新数据库,条件是:




NOTES表单中的相应域值不能为空(因为在 NOTES中任何域值若为空,则其数据类型总是string,值为空字符串)。如何实现?将方式 一的例子




中的

Call dbresult.setvalue("field1","test")改造如下:

ltmp=Doc.GetItemValue("doc_field1")

Call dbresult.setvalue("field1",ltmp(0))

其中,doc_field1为关系数据库字段field1对应的NOTES域名。如此改造,即可通过域名更 改相应的后台关系数据库了。 通过上述方式二更新






数据库,则要进行类型转换。可以通过前台NOTES的域的 数据类型来 判断生成可以正确执行的SQL语句,例如:字符型,则在生成时在其值的前




后加单引号;数值型,则不必。但如何取得数据类型呢?通过NotesItem的Type属性访问可返回NotesDocument的条目的数据类型,例如:字符型





时,返回1280;数值型时,返回768;日期时间型,返回 1024,等等。但当相应的域值为空时NotesItem.Type永远返回1280(即字符型),而不管




实 际该域值类型为数值还是日期。 还有一种方法进行类型转换,通过后台关系数据库的数据类型生成可以正确执行的SQL语句。




ODBCResultSet.FieldNativeDataType方法返回后台数据类型的相应字段类型,如: SQL_CHAR,SQL_INTEGER,SQL_TIMESTAMP等等。

 

本文地址:http://com.8s8s.com/it/it25250.htm