lotus notes 开发常用方法

一、关于 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(Myarr ay,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 等等。


相关文档

安装Lotus Notes方法和使用
Lotus Notes常用代码
浅析Lotus Notes开发
Lotus Notes设置方法1
lotus notes 开发经验
LOTUS NOTES常见问题的处理
lotus notes安装和使用常见问题的解决方法与技巧
开发人员眼中的lotus Domino/Notes
lotus_notes 安装和使用常见问题的解决方法与技巧
电脑版