lotus notes 开发常用方法

  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(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等等。
 

 

你可能感兴趣的:(Lotus,Notes/Domino)