綜合使用JavaScript、LotusScript Agent和Formula的技巧

 一 概述
在使用 Designer開發B/S模式的應用時,JavaScript、LotusScript和Formula是我們主要用到的三種開發語言。它們在各自的位置都有着很強勁的優勢。
1. JavaScript因爲只能取得瀏覽器端的數據,不能訪問Notes DOM;所以,主要用在瀏覽器端的數據驗證、信息提示等對當前Brows窗口操作易的用性功能

2. LotusScript能訪問Notes DOM。在Notes客戶端可以取得當前文檔的數據,但是,因爲其無法直接在瀏覽器端工作;所以在B/S模式的應用中LotusScript只能在服務器端工作,我們通過編寫LotusScript代理來實現其強大的文檔處理能力。

3. Formula能訪問後臺數據,語言簡潔,數據處理能力較弱,不能在瀏覽器端工作。Formula主要使用在元素的顯示控制以及域值的計算公式及簡單的數據處理方面。
這三者使用的範圍和處理能力各不相同。在應用中將其三者綜合起來使用,會使應用的各方面功能大大增強。

二 由JavaScript向代理(LS\FL)通信

一般情況下JavaScript向代理的通信,使用url command。即如下格式http://Host/Database/AgentName?OpenAgent&參數。這類操作可以用來解決數據查詢、文檔刪除等任務。這類操作的特點是可以帶參數,但是取不到瀏覽器端的當前文檔,無法對瀏覽器端的文檔進行處理。
那麼,爲什麼要使用JavaScript向代理通信,並讓代理取得瀏覽器端的當前文檔呢?先看一個例子:
在某申請系統中,用戶創建新申請可以這樣做:打開新的申請單,填寫各項目後,點擊操作按鈕“提交申請”,就完成了操作。對設計者而言觸發“提交”操作必定運行一個代理或一段公式(此處我們先假定提交操作運行的是代理,後面將介紹提交操作運行公式的情況)。在真正運行代理的“提交”之前,系統一定要進行數據合法性的驗證。最簡單的做法是在每個域裏面寫入驗證公式,或者在代理裏寫入驗證數據合法性的代碼。但是,這類做法的共同的缺點是:即使數據不合法,服務器端和瀏覽器端也發生了交互,佔用帶寬、影響網絡速度。並且,出錯提示信息只能以網頁形式輸出在原窗口上。這樣,就會使原窗口中的信息丟失,不方便用戶修改原來的數據。
針對這種情況,我們想讓域的驗證工作在瀏覽器端執行。並且,出錯提示使用彈出窗口。JavaScript正能符合要求,但是難點就在:一旦驗證通過怎樣調用代理?
解決的辦法是:
1. 保持“提交申請”操作按鈕和提交代理不變。在瀏覽器端預覽表單,點擊右鍵查看源文件,找出“提交申請”操作按鈕的onclick事件中的代碼。

2. 新建一個同樣名爲“提交申請”操作按鈕,將原來的“提交申請”操作按鈕隱藏。在新建的操作按鈕中寫入域驗證信息JavaScript代碼,如果驗證通過則執行第一步的代碼。如果不通過則使用alert彈出窗口,提示出錯信息。
3. 注意:每增減一次操作按鈕,都會影響原“提交申請”操作按鈕的onclick事件代碼。所以,比較好的辦法是將原來的“提交申請”操作按鈕作成共享操作。

以上做法是我們在工作流模版裏使用的方法。現在,我們有一種改進方法:
1。不用原來的操作按鈕,把觸發提交代理的寫在一個按鈕(button)裏,給該按鈕命名(假設爲“b1”,在其屬性框中找到html選項卡“name”欄中填爲“b1”),用css將該按鈕隱藏。(同樣在tml選項卡中,在“style”欄填入“visibility: hidden”)

2。新建一個名爲“提交申請”的操作按鈕,在按鈕中寫入域驗證信息JavaScript代碼,如果驗證通過則執行“ document.forms[0].b1.onclick()”(此處的b1是上一步我們假設的按鈕name)。如果不通過則使用alert彈出窗口,提示出錯信息。

3。注意如果有多個這種操作在同一個表單裏,那麼按鈕的name必須不同。對按鈕的調用顯然也應該根據其name。

縱觀兩種用JavaScript調用代理的方法,各有特點。使用urlcommand比較方便易用,但缺點是取不到瀏覽器端的當前文檔,代理很多強大的功能無法展開。使用第二種方法,實際上是JavaScript通過調用操作按鈕,間接調用了代理。這種方法功能強大,但是,創建和維護都稍顯複雜。最後指出:所謂使用JavaScript調用Formula,也就是指用JavaScript調用操作按鈕,而操作按鈕則中執行的是各類對文檔進行操作的Formula。即用JavaScript間接調用了Formula。
三 由代理向JavaScript通信

使用代理向JavaScript通信,可以分爲用代理寫出JavaScript程序和用代理設置JavaScript參數。
[一]用代理寫出JavaScript程序。
我們可以使用代理中的print系統函數,在窗口打印信息。這些信息爲瀏覽器認做HTML語句來解釋。這樣我們就可以用print函數在代理中寫JavaScript程序。
例如以下代碼片段:
If dc.count=0 then
‘dc爲在前面程序裏使用database.search得到的DocumentCollection
Print "<SCRIPT LANGUAGE=JavaScript>"
Print "alert(""沒有找到相關文檔,請和管理員聯繫。"")"
Print "location.href = ""/Web+test.nsf/Main+View?OpenView"""
Print "</SCRIPT>"
End if
該段代碼執行如下功能,判斷如果當前搜索得到的文檔集爲空,就在瀏覽器端顯示出錯信息,然後將窗口路徑指向某視圖

再看一個代碼片段:

flag =curdoc.save(True,False)
If flag Then
Print "<OBJECT id=closes type=""application/x-oleobject""classid=""clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11"">"
Print " <param name=""Command"" value=""Close""> </object>"
Print "<script>"
Print "window.setTimeout('closes.Click()',1000)"
Print "</script>"
Print "<h4>個人選項保存成功。</h4>"
End If
該段代碼執行如下功能,判斷如果當前文檔保存成功,就在瀏覽器端顯示確認信息,隨即關閉窗口。

使用代理寫JavaScript程序我們可以做出許多有效、方便的功能來。比如動態的信息展播等。

[二]用代理設置JavaScript參數。
這裏JavaScript是表單中寫好的,但是JavaScript的某些參數可能使用表單中某些域的值。這樣用代理設置了該域的值也就設置了JavaScript參數。
例如:某系統用戶要求在申請單中的“編號”字段用戶能手動填寫,但是又要能保證:如有重複的號碼,系統要給與提醒。
解決辦法就是:
1. 使用webquaryopen事件運行代理,使其將所有已經編號文擋的編號值都以逗號隔開,放入文檔的某域中。
2. 而在表單內則寫入JavaScript代碼。將該域的值取出作參數,再將該參數以逗號隔開取得字符串數組。
3. 最後在域有效性驗證時,比較當前的編號是否存在於數組中,若是則返回出錯,否則成功。

比較以上介紹的兩種方法。第一種方法:因爲JS代碼都由代理寫出來,所以形式更靈活、功能更強大。但是,由於代碼是Print出來的,無法和文檔在窗口共存;所以,這種方法一般使用在信息展示方面。第二種方法:由於大部分代碼是在瀏覽器端寫好的,所以功能相對單一。因爲代理通過修改域值影響JavaScript代碼;所以,一般用在文檔處理方面。
四 由Formula向JavaScript通信

Formula調用JavaScript。與代理調用JavaScript的第2條十分相似。但是,因爲Formula能控制表單元素的顯示屬性。而Agent能訪問更多的數據,所以Formula與Agent各有千秋。
這裏介紹一個比較有趣的例子,就是怎樣使文擋按條件自動編輯。即某些情況下文擋打開時爲閱讀狀態。另一些情況,文檔打開時則爲編輯狀態。顯然,設置表單的自動編輯功能是無法完成功能的。
做法:
1. 在表單建立JavaScript函數autoedit。

2. 函數中寫入代碼取得當前窗口路徑,將路徑最後幾個字符opendocument替換成editdocument,然後存在變量mypath中。
3. 假設文檔是否自動編輯的判斷條件是當前用戶在公共通訊錄裏的個人文檔的“myauto”字段是否爲“yes”。那麼在JavaScript函數“autoedit”中寫JavaScript代碼:t=<此處爲計算文本>,計算文本的公式爲“@dblookup(""; "" : "names.nsf" ; "people"; @name([ cn ] ; @username) ; "myauto")”。
4. 在JavaScript函數“autoedit”中加入代碼,判斷t是否爲“yes”,若是則爲將window.location置爲mypath。然後將本段代碼設置爲在編輯狀態下隱藏。
5. form的onload事件中加入JavaScript代碼,調用autoload函數。

注:以上文檔是我在學校裏時寫的,現在看來有些觀點難免有點牽強,實例也不夠生動;貼上來權作拋磚引玉。
程序開發總結之二
  
如何頁面上建立一個熱點,讓它打開一個文檔?
答: 在頁面上寫一段文字,然後選上這段文字,然後點菜單”創建” –熱點--操作熱 點.然後選LotusScript ,舉個例子,比如打開ID 爲NT00000C62的文檔:
Sub Click(Source As Button)
Dim uiworkspace As New notesuiworkspace
Dim curdatabase As notesuidatabase
Dim database As notesdatabase
Dim doc As notesdocument
Set curdatabase = uiworkspace.currentdatabase
Set database = curdatabase.database
Set doc = database.getdocumentbyid("00000C62")
Call uiworkspace.EditDocument(True,doc,False )
End Sub
我如何實現歸檔,比如我如何把當前視圖中所有被選中的文檔歸入文件夾 fold 中?
答: 用Script象如下這樣實現:
Sub AddDocToFold(fold As String)
Dim uiworkspace As New notesuiworkspace
Dim uiview As notesuiview
Dim doc As NotesDocument
Dim docList As String
Set uiview = uiworkspace.currentview
For j = 1 To uiview.Documents.Count
Set doc = uiview.Documents.GetNthDocument(j)
Call doc.PutInFolder( fold )
Next
End Sub
我如何實現把某文件夾視圖中的被選擇的文檔從該文件夾中清除,但卻不能刪除他們?
答: 用Script 實現如下:
Sub RemoveDocFromFold( fold As String,all As Integer)
'功能:
' 把文檔從某個文件夾中移走,但並不刪除此文檔
'參數:
' fold: 文件夾
' all : 0表示僅移走當前選擇的文檔,1表示移走該文件夾中所有文檔
Dim uiworkspace As New notesuiworkspace
Dim uiview As notesuiview
Dim doc As NotesDocument
Dim view As notesview
Set uiview = uiworkspace.currentview
Set view = uiview.view
If all = 0 Then '移去所選文檔
For j = 1 To uiview.Documents.Count
Set doc = uiview.Documents.GetNthDocument(j)
Call doc.RemoveFromFolder( fold )
Next
Else
If all=1 Then '移去全部文檔
Set doc = view.GetFirstDocument
'遍列該視圖的所有文檔,獲取所有滿足條件的紀錄數
While Not(doc Is Nothing)
Call doc.RemoveFromFolder( fold )
Set doc = view.GetNextDocument(doc)
Wend
End If
End If
'Evaluate("@Command([ViewRefreshFields])")
End Sub
我如何把當前視圖中的所有的被選擇的文檔的某個域的值替換掉?
答: 用Script 實現如下:
Sub SelectedDocFieldReplace( Field As String,repval As String)
'功能:
' 把所選文檔中的每個 Field 域的值 改爲 repval
'參數:
' Field 要更改的域的名稱
' repval 修改後的域值
Dim uiworkspace As New notesuiworkspace
Dim uiview As notesuiview
Dim doc As NotesDocument
Dim order_num As String
'order_num = Inputbox$("請輸入批次")
Set uiview = uiworkspace.currentview
For j = 1 To uiview.Documents.Count
Set doc = uiview.Documents.GetNthDocument(j)
On Error Goto lable1
Call doc.replaceitemvalue(Field,repval)
Call doc.save(True,False)
Next
Exit Sub
lable1:
Msgbox("錯誤!,所選文檔沒有指定的域,這個錯誤發生在沒有給 selectedDocFieldReplace() 函數傳遞正確的參數")
Exit Sub
End Sub
我如何創建某個程序運行結果的日誌文檔?
答: 首先新建一個日誌文檔的表單,並把該表單設置成數據庫的默認表單,然後 就用Script創建文檔,並填寫該文檔中某些域的值,最後存盤,例子程序片段如下:
'寫傳真日誌
Dim faxerdoc as notesdocument
‘faxerr_receiver,faxerr_docnum,faxerr_content是表單form_faxerr的三個域名

Set faxerrdoc = New NotesDocument( db )
faxerrdoc.Form = "form_faxerr"
Call faxerrdoc.replaceitemvalue("faxerr_receiver",Cstr(peoplecount) )
Call faxerrdoc.replaceitemvalue("faxerr_docnum",strsucssnding )
Call faxerrdoc.replaceitemvalue("faxerr_content",faxerrmsg )
success = faxerrdoc.ComputeWithForm( False, False )
If success Then
Call faxerrdoc.Save( True, False )
Else
Msgbox("無法寫入傳真日誌....")
End If
'Msgbox(faxerrmsg)
Exit Sub
我要從當前視圖中選擇一批文檔,並讓程序從這些文檔中提取信息,在嵌入在表單中的OLE對象Word文檔中建立一張表,要求是選擇了幾篇文檔就在這張表中畫幾行,這張表的每個列的信息都中文檔中的域中提取,換句話說,就是要把被選文檔以Word文檔表格的形式表示出來,能否給我一個這方面的例子程序?
答: 可以,下面就是這樣的一個例子:
Sub inputgroupplan(source As notesuidocument,doccollection As notesdocumentcollection)
'功能: 自動生成出團計劃表。
' 詳細描述:
' 從 文檔集合 doccollection 中提取各個域值,並把提取的信息以一定
' 的表格形式送入當前文檔的 body 域中的 OLE 對象--Word 文檔中.
'參數:
' source: 當前文檔
' doccollection :文檔集(比如文檔的選擇集)

Dim session As New NotesSession '當前會話
Dim counter As Integer '計數器
Dim doccustom As NotesDocument 'notes 文檔對象
Dim thisdoc As Variant 'Word 文檔對象
Dim thisrange As Variant 'Word 開發中的 range 對象
Dim thispicture As Variant '嵌入Word 文檔的圖象對象
Dim thistable As Variant '嵌入Word 文檔的表格對象
Dim pagehead As String '嵌入Word 標題
'獲取嵌入文檔的句丙
If source.EditMode Then
Set thisdoc = source.getobject("oleobject")
'插入一幅圖
Set thispicture = thisdoc.shapes.Addpicture("c:\學習\cassiatb.jpg")
'設置圖像屬性
With thispicture.wrapformat '環繞方式
.type = wdwrappicture '類型爲picture
.side = wdwrapright '文字右環繞
End With
'設置該文檔的頁面設置的左邊距爲20個單位(象素)
With thisdoc.pagesetup
.leftmargin = 20
.rightmargin = 20
End With
counter=0
pagehead = Inputbox$("請輸入標題")
pagehead = Chr(10) & pagehead & Chr(10) & Chr(10) & Chr(10)
'Call source.FieldSetText ( "Namelist_Group_Num", group_num )
'groupstring = "Namelist" & " " & group_num & Chr(10)
Set thisrange = thisdoc.range(1,1)
thisrange.InsertBefore (pagehead)
Set thisrange = thisdoc.range(2,Len(pagehead))
With thisrange
.bold = True '加粗
.ParagraphFormat.Alignment = 1'wdAlignParagraphCenter 行居中
.font.size = 20 '字體大小爲20
End With
Set doccustom = doccollection.GetFirstDocument
'遍列文檔集的所有文檔,獲取所有滿足條件的紀錄數
While Not(doccustom Is Nothing)
counter=counter+1
Set doccustom = doccollection.GetNextDocument(doccustom)
Wend
'動態分配紀錄數組
'Redim record(counter,6) As String
'插入一張表
Set thisrange = thisdoc.range(Len(pagehead)+1,Len(pagehead)+1)
Set thistable = thisdoc.tables.Add(thisrange, counter+1, 8)
'thistable.autoformat(False)
'寫表頭
thistable.rows(1).cells(1).range.insertbefore("前往國家")
thistable.rows(1).cells(2).range.insertbefore("國家數")
thistable.rows(1).cells(3).range.insertbefore("天數")
thistable.rows(1).cells(4).range.insertbefore("出境城市")
thistable.rows(1).cells(5).range.insertbefore("入境城市")
thistable.rows(1).cells(6).range.insertbefore("出發日期")
thistable.rows(1).cells(7).range.insertbefore("同行價")
thistable.rows(1).cells(8).range.insertbefore("市場指導價")
'恢復計數器
counter = 0
'寫表內容
Set doccustom = doccollection.GetFirstDocument
While Not(doccustom Is Nothing)
counter = counter+1
thistable.rows(counter+1).cells(1).range.insertbefore(doccustom.plan_country(0))
thistable.rows(counter+1).cells(2).range.insertbefore(doccustom.plan_country_num(0))
thistable.rows(counter+1).cells(3).range.insertbefore(doccustom.plan_day(0))
thistable.rows(counter+1).cells(4).range.insertbefore(doccustom.plan_out_city(0))
thistable.rows(counter+1).cells(5).range.insertbefore(doccustom.plan_in_city(0))
thistable.rows(counter+1).cells(6).range.insertbefore(doccustom.plan_date(0))
thistable.rows(counter+1).cells(7).range.insertbefore(doccustom.plan_whole_price(0))
thistable.rows(counter+1).cells(8).range.insertbefore(doccustom.plan_mart_price(0))
Set doccustom = doccollection.GetNextDocument(doccustom)
Wend
End If
End Sub
如何實現表單上的內容根據用戶的輸入動態變化?
答: 一般可以用notes的隱藏屬性功能來控制,使用當公式爲真是隱藏,然後靠公式來控制具體怎樣隱藏.比如可以在對話筐上放一個對話筐列表,裏面放十個選項,當用戶選擇了其中的某幾個選項時,響應的在下面的表單部分顯示幾行.這可以畫一個表格,這個表格的屬性中設置邊框的線條粗細爲零.然後對應十個選項分爲十行,每行填入和選項響應的內容,然後選定某一行的所有文本,編輯其隱藏屬性,選當公式爲真時隱藏,這個公式您就可以寫成當選項的被選中條目中不包含本行文字時隱藏就可以了,這樣這一行就會在響應的選項被選中時纔會顯示.
notes沒有應用程序級的公共變量,那麼我如果要彈出一個對話筐,並從這個對話筐中返回很多用戶輸入,我該怎麼辦?
答: 你首先要確定你要在哪個表單上彈出這個對話筐,一般的的做法是利用notes 的域值傳遞功能,即如果對話筐中的表單上的域和彈出這個對話筐的母表單的域相同,則對話筐中的值會被自動傳到母表單的相應的域中的.你可以將放在對話筐中的表單作成子表單,同時把它放入對話筐中和母表單中,這樣你就可以接受到所有的用戶輸入了.
                                              在b/s下從通訊錄中選人一例在parentform母表單上建一個域reader(多值),另建一表單(childform),上建兩個對話框域rylb(通訊錄中人員的姓名),reader(用於添加或刪除人員),在母表單上建一按鈕,js代碼如下:window.open('/xxxy/xxx.nsf/childform?openform',null,'width=450,height=200,status=no,resizable=no,top=200,left=200,scrollbars=no');在childform表單的js head 中寫入以下代碼,var fieldfunction AddClick(field){var fieldEntryList=document.all["rylb"]if(fieldEntryList.selectedIndex != -1){for (var i=0; i < fieldEntryList.options.length; ++i){if (fieldEntryList.options.selected)field.options[field.options.length] = new Option(fieldEntryList.options.text);}}}function RemoveClick(field){if (field.length != 0){if (field.selectedIndex != -1){for(var i=0;i<field.options.length ; ++i){if (field.options.selected){field.options = null;--i;}}}}}在childform表單的onload中寫入以下代碼,(用於讀取原有的值)if(window.opener){readers=window.opener.document.forms[0].reader.value;var arr=readers.split(";");var field=document.all["reader"]for(i=0;i<arr.length;i++){field.options[field.options.length] = new Option(arr);}}在childform表單中的rylb域中的“爲選項使用公式”中寫入公式@Unique( @DbColumn("";"":"names.NSF";"people";1)),在HTML樣式中寫入“width=130;height=150”在childform表單中的reader域中HTML樣式中寫入“width=130;height=150”;在childform表單上建四個按鈕,“添加->”按鈕,代碼如下:AddClick(reader),“移除<-”按鈕,代碼如下:RemoveClick(reader),“確定”按鈕,代碼如下:var fieldEntryList=document.all["reader"]if (fieldEntryList.options.length=="0"){window.opener.document.forms[0].reader.value=""}else{window.opener.document.forms[0].reader.value="";for (var i=0; i < fieldEntryList.options.length; ++i){if(window.opener.document.forms[0].reader.value==""){window.opener.document.forms[0].reader.value=fieldEntryList.options.text}else{window.opener.document.forms[0].reader.value=window.opener.document.forms[0].reader.value+";"+fieldEntryList.options.text}}}alert("操作成功,請保存原文檔!")window.close()“取消”按鈕,代碼如下:window.close()這樣就可以對parentform母表單域中的值進行添加、移除等自如地操作。

  
 
Servlet在Cookie,Session和上傳文件上的應用
  
Servlet可以被認爲是服務端的applet,它被WEB服務器加載和執行,前端可以顯示頁面和獲得頁面數據,後臺可以操縱數據庫,能完成JavaBean的很多功能。在這裏我較爲詳細的說說Servlet在Cookie,Session和上傳文件上的應用,在說明時我給出一些能編繹運行的小例子,最後給出一個文件上傳例子以加深印象。
  我們先來看看SERVLET程序的基本構架:
式1:
  package test;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import java.io.*;
  import java.util.*;
  public class test extends HttpServlet {
  public void init(ServletConfig config) throws ServletException {
  super.init(config);
}
  public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  int f =1; switch(f){
  case 1:firstMothed(request,respponse);break;
}
}
  public void firstMothed(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  response.setContentType("text/html");
  OutputStreamWriter osw = new
  OutputStreamWriter(response.getOutputStream());
  PrintWriter out = new PrintWriter (response.getOutputStream());
  out.println("< html>");
  out.println("< head>< title>Servlet1< /title>< /head>");
  out.println("< body>你好!");
  out.println("< /body>< /html>");
  out.close();
}
}
式2:
  package test;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import java.io.*;
  import java.util.*;
  public class test extends HttpServlet {
  public void init(ServletConfig config) throws ServletException {
  super.init(config);
}
  public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  response.setContentType("text/html");
  OutputStreamWriter osw = new OutputStreamWriter(response.getOutputStream());
  PrintWriter out = new PrintWriter (response.getOutputStream());
  out.println("< html>");
  out.println("< head>< title>Servlet1< /title>< /head>");
  out.println("< body>你好!");
  out.println("< /body>< /html>");
  out.close();
}
  public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  response.setContentType("text/html");
  OutputStreamWriter osw = new OutputStreamWriter(response.getOutputStream());
  PrintWriter out = new PrintWriter (response.getOutputStream());
  out.println("< html>");
  out.println("< head>< title>Servlet1< /title>< /head>");
  out.println("< body>你好!");
  out.println("< /body>< /html>");
  out.close();
}
}
  式1適合於作總控模塊,此SERVLET作中間調度,根據不同的f值調用不同的SERVLET或方法。
式2適合於對html的get和post有不同要求的情況。
  但這並不是絕對的,式2就完全可以代替式1,只要在doGet()方法中寫上doPost就與式1完全一樣。
在init方法中執行的語句,只要這個servlet被啓動了就一直有效,比如,我們在init()中new了一個對象,那麼這個對象的內存空間就永遠存在,除非顯式地把這個對象賦爲null,或重啓服務。
  HttpServletRequest和HttpServletResponse兩個對象實現http請求,它們有很多有用的方法,在下面的cookie和session管理中會細加描述。
  1, cookie管理 cookie用於在客戶端保存個人所特有的信息,它採取在客戶機寫臨時文件的機制。
  package test;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import java.io.*;
  import java.util.*;
  public class test extends HttpServlet {
  public void init(ServletConfig config) throws ServletException {
  super.init(config);
}
  public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  //寫cookie
  String CookieName ="js79"; //若是漢字則需編碼
  String CookieValue = "yesky";//若是漢字則需編碼
  Cookie cookie = new Cookie(CookieName,CookieValue);
  cookie.setMaxAge(age); // age = Integer.MAX_VALUE 永不過期
  cookie.setPath("/");
  //讀cookie
  String value = null;
  Cookie[] cookies = request.getCookies();
  if (cookies != null) {
  for (int i=0; i< cookies.length; i++) {
  if (cookies.getName().equals(CookieName))
  value = cookies.getValue();
  break;
}
}
}
  response.setContentType("text/html");
  OutputStreamWriter osw = new OutputStreamWriter(response.getOutputStream());
  PrintWriter out = new PrintWriter (response.getOutputStream());
  out.println("< html>");
  out.println("< head>< title>test< /title>< /head>");
  out.println("cookie鍵:"+CookieName+"< br>");
  out.println("cookie值: "+value);
  out.println("< /body>< /html>");
  out.close();
}
}
  2,session管理
  Session在Servlet中是很有用的,它比cookie安全可靠靈活,但是管理起來有點麻煩,用得不好會造成服務器的開銷很大,浪費資源。下面是一個基於Session管理一個對象的簡單例子。
一個簡單的bean對象TestObject
  package test;
  public class TestObject extends Object {
  int id = 0; public String cur="";
}
  package test;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import java.io.*;
  import java.util.*;
  public class TestMan extends HttpServlet {
  public void init(ServletConfig config) throws ServletException {
  super.init(config);
}
  public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  int f = 1;
  if(request.getParameter("f")!=null)
  f =
  Integer.parseInt(request.getParameter("f"));
  switch(f){
  case 1: this.getResult(request,response);
  break;
  case 2:
  this.setSession(request,response);
  break;
}
}
  public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  doGet(request,response);
}
  public void getResult(HttpServletRequest request, HttpServletResponse response)   throws ServletException, IOException {
  TestObject testObject = null;
  testObject = getStatus(request,response);
  String html = testObject.id; doWrite( response,html);
}
  public void setSession(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {
  HttpSession session = request.getSession();
  TestObject testObject = null;
  testObject = getStatus(request,response);
  String tmp = null;
  tmp = request.getParameter("id");
  if(tmp != null) testObject.id = tmp;
  session.putValue("testObject ",article);
  getResult(request,response);
}
  private TestObject getStatus(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  HttpSession session = request.getSession();
  TestObject testObject = null;
  if(session!=null){
  if(session.getValue("testObject ")!=null){
  testObject = (TestObject)session.getValue("testObject ");
}
  else{
  testObject = new TestObject ();
}
}
  else{
  testObject = new TestObject ();
}
  return testObject;
}
  private void doWrite(HttpServletResponse response,String html) throws   ServletException, IOException {
  PrintWriter out = response.getWriter();
  out.println(html);
  out.close();
}
  /////////////////////////////////////////////////////////
}
  若能輕鬆搞定上面的例子,相信讀者對SERVLET已有了較爲深刻的理解。
下面再介紹一個上傳文件例子,其中汲及到了下載的免費JavaBean (如有感興趣的朋友,可來函索要免費JavaBean源代碼,Email:[email protected])
  上傳基本原理:由頁面發出一個http請求,服務端得到請求後,解析多媒體協議,讀出文件內容,寫文件內容到服務器,所有的這些功能都封裝到JavaBean中。
  上傳文件的必需條件:Browser端< form>表單的ENCTYPE屬性值必須爲 multipart/form-data,它告訴我們傳輸的數據要用到多媒體傳輸協議,由於多媒體傳輸的都是大量的數據,所以規定上傳文件必須是post方法,< input>的type屬性必須是file。
  package upload;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import java.io.*;
  import java.util.*;
  public class UpLoadServlet extends HttpServlet {
  public void init(ServletConfig config) throws ServletException{
  super.init(config);
}
  public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  PrintWriter out = response.getWriter();
  out.println("< HTML>< HEAD>< TITLE>UpLoad< /TITLE>"
  +"< meta http-equiv='Content-Type' content='text/html; charset=gb2312'>"
  +"< /HEAD>"
  +"< body>");
  out.println("< div align='center' valign='top'>"
  +"< span class='nava'>請你選擇上傳的文件(請注意文件大小只能在20K之內)< /span>< BR>"
  +"< form ENCTYPE='multipart/form-data' method=post action=''>"
  +"< input type='file' name='file'>"
  +"< input type='submit' value='發送'>"
  +"< /form>"
  +"< /div>");
  out.println("< /body>< /html>");
  out.close();
}
  ////////
  public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  PrintWriter out = response.getWriter();
  int tmpID = 1; try {
  MultipartRequest multi = new MultipartRequest(request,"/home/js79/html/", 5 * 1024 * 1024);
}
  catch(Exception e){
  tmpID = -1; System.out.println(e);
}
  if(tmpID == 1){
  out.println("< HTML>< HEAD>< TITLE>UpLoad< /TITLE>"
  +"< meta http-equiv='Content-Type' content='text/html; charset=gb2312'>"
  +"< /HEAD>"
  +"< body>");
  out.println("上傳成功!< /body>< /html>");
}
  else{
  out.println("< HTML>< HEAD>< TITLE>UpLoad< /TITLE>"
  +"< meta http-equiv='Content-Type' content='text/html; charset=gb2312'>"
  +"< /HEAD>"
  +"< body>");
  out.println("上傳不成功!< /body>< /html>");
}
  out.close();
}
}

討論notes在b/s模式下如何才能達到最佳效果!
  
  
1、要充分利用CSS樣式表,將你的域和文本儘可能放到表格單元格中,在樣式中可加入CSS,還有在HTML 首頁內容中加入Css
2、在B/S模式下,做到頁面的切換,要充分利用JavaScript;
3、在B/S下,要在表單中加入相應的html,也不是單純的加入,而且要結合notes的公式語言;
4、需要注意的,所有的Domino設計元素以及文檔都有自己的特定的ID號,當需要生成某些URL時,Domino就使用這些特定的ID號來代表該元素;
5、在B/S下,如果你的不同視圖具有一致的風格,那就需要採用$$ViewTemplate for “視圖的名字”的方式;
6、還有就是需要CGI變量。
  
在notes裏頭好多東西在http下實現不了,不知各位怎樣解決的?
                                     功程序員的七個祕密
作者 Merrion

7項使你成爲開發者社區出色成員的技巧
  
1.爲人的需求編碼
計算機界的一個最普遍的誤會是認爲原始碼是爲計算機服務。計算機是工作在低級的二進制代碼上,是在一系列的難以理解的1或0或者十六進制數字之上,而不是我們敲入的結構化高級計算機語言。
這些語言被開發出來的目的是爲了幫助我們程序員。
在實踐中,爲人的需求編碼通常意味着首先要有清楚透明的結構和思路,其次纔是效率和速度。
2.經常的好的註釋
註釋是爲人的需求編碼的一種極端的語言元素例子。大多數編譯器都會將註釋與可執行程序分離開來。
註釋的目的就是要告訴你(或者其他將來的開發着)程序的功能是什麼。
把這些寫進註釋 - 並且避免只是簡單重新敘述代碼。
好的註釋:
Disable button to prevent its activation
糟糕的註釋:
Set cmd = False
一個很好的檢驗註釋的標準是:如果只有註解沒有去掉,有人能夠知道你的程序的作用嗎?
3.良好代碼佈局增加易讀性
正如一位作家將一本書分成章和段落以幫助閱讀,因此開發者考慮代碼如何佈局如何能能增強代碼的易讀性也是非常重要的。
特別在任何語句結構塊中 (如
IF.
.
THEN.
.
.
ELSE語句快) 和任何循環結構(如
WHILE.
.
.
END WHILE)
代碼應該縮進以便於很容易分清楚哪裏是開始哪裏是結束。
4.預測並處理 那意想不到的事情
你打開一個文件之前,確定文件爲當前文件。你將焦點設定爲控件之前,確定控制是看得見的並且可用。設法找出在什麼條件下使你的代碼失效,並在你的程序崩潰之前測試它。
5.命名變量增強易讀性
有許多策略進行變量命名。首要原則是一致性和儘可能的能通過命名變量提供足夠的信息。如果你命名一個變量爲nMonth,你提供給程序員的信息是這個變量將被設計用來存儲什麼內容。
我自己傾向於使用匈牙利的命名風格 - 但是無論你使用哪一種風格,一致性是最主要的。
6.使你的方法和過程保持簡潔
一個方法或者過程理想狀況下應該只做一件事情。在我的經驗方面,最大的誤區是,一個過程通常被設計來完成許多的不同操作。
應該將他們按不同的操作拆分成各個不同方法處理各自的事情,這樣各個功能可以很容易被重用,而且各個方法內的代碼改變也很容易理解。
7.適當的方法和變量使用範圍
功能和變量如果只在一個組件中使用,則在那一個組件之外不應該是看得見的。如果變量只被設計用於一個方法或者過程,那麼在那一個方法或過程之外不應該是看得見的。
這可以避免任何一個變量或者方法在它沒有意義的地方使用。

有許多其他的提示和技巧能使你被成爲比較好的程序員, 將會使你更有效率而你寫的程序也更可維護, 但是這上面列出的七個祕密將會視爲一個好的基礎 - 然而使你高度地建構在他們之上。
  
公式祕籍
  
訪問用戶環境

用戶環境是包含數據庫的服務器或工作站,數據庫包括以下內容: 複製公式、由新郵件到達時或定時觸發的代理、選擇公式或列公式。否則,用戶環境是用戶運行公式的 Notes 工作站。
用戶名可以是專有名稱也可以是非專有名稱,專有名稱可以是規範或縮寫的,使用 @Name 可更改用戶名的格式。
以下函數返回或處理用戶環境的信息。
函數 描述
@UserName 返回用戶名或服務器名。
@Name([key]; name) 更改用戶名的格式。關鍵字包含 [CN] 以從一個專有名字中解析出公共名,[Abbreviate] 縮寫規範格式的專有名字,[Canonicalize] 與上述作用相反,[ToKeyword] 將名字各部分按相反順序排序,用反斜槓分開(用於分類視圖)。
@UserRoles 對於服務器上的數據庫,返回當前用戶的角色列表。
@MailDbName 返回用戶郵件數據庫的服務器名和路徑名。該 @function 計算出一個包含兩元素的列表。
@OptimizeMailAddress(address) 從地址中刪除無用的網絡域。
@Platform 返回用戶當前運行的平臺:Macintosh、 NetWare、 OS2V1、 OS2V2、 UNIX、 Windows/16 或 Windows/32。
@Version 返回正在運行的 Notes 版本(字符串)。
@Password(string) 對字符串加密。加密後別人無法從中得到最初的字符串。


訪問當前數據庫和視圖

可以直接訪問正在運行公式的數據庫(便捷圖標除外,因爲它沒有數據庫環境)。也可以在視圖環境中直接訪問正在運行公式的視圖。同樣,在文檔環境中可直接訪問打開文檔的視圖。
數據庫和視圖屬性
下表列出返回數據庫和視圖屬性的函數。
函數 描述
@DbManager 返回當前對數據庫有“管理者”權限的用戶、羣組和服務器。返回一個列表。
@DbName 返回當前 Notes 服務器和數據庫的名稱。返回二個元素的列表。
@ViewTitle 返回當前視圖的標題。
窗口標題和列公式 @function
許多 @function 提供了關於視圖的答覆層次和其他方面的信息。在視圖中,主文檔以 1、2、3 等編號。每組答覆文檔或答覆的答覆文檔則有第二個和第三個層次的從 1 開始的編號。缺省情況下,完整的答覆文檔的編號以小數形式出現。例如:第三個主文檔的第二個答覆文檔編號爲 3.2,而它下面的第一個答覆文檔編號爲 3.2.1。
這些函數僅工作於窗口標題和列公式中,有一些會被限制。返回值都是一個字符串。
函數 描述
@Responses 返回當前視圖中當前文檔的答覆文檔的編號(只限於窗口標題公式)。
@DocLevel 返回在當前視圖中當前文檔的級別。
@DocSiblings 返回與當前文檔同級的文檔編號(包含當前文檔)。
@DocNumber 返回當前視圖中的當前文檔或分類的編號。
@DocNumber(sep) 同上,只是用 sep,而不是句點來分隔編號。
@DocNumber("") 同上,只是僅返回編號的最右邊部分。
@DocParentNumber 返回當前視圖中當前文檔或分類的父文檔或父分類的編號。
@DocParentNumber(sep) 同上,只是用 sep,而不是句點分隔編號。
@DocParentNumber("") 同上,只是僅返回編號的最右部分。
@DocDescendants 返回後續文檔的編號。包含當前文檔的子文檔,子文檔的子文檔。
@DocDescendants(def) 同上,只是返回 def。在 def 中使用 % 以表示編號。
@DocDescendants(zero; def) 同上,只是如果沒有後續文檔的話則返回 zero。
@DocDescendants(one, zero; def) 同上,如果只有一個後續文檔的話,則返回 one。
@DocChildren 返回當前文檔的直接子文檔的編號。
@DocChildren(def) 同上,僅返回 def。在 def 中使用 % 以表示編號。
@DocChildren(zero; def) 同上,只是如果沒有後續文檔的話,則返回 zero。
@DocChildren(one, zero; def) 同上,如果只有一個後續文檔的話,則返回 one。
@IsCategory 如果當前行的當前域右邊任何域是一個分類,則返回一個星號。
@IsCategory(True) 同上,只是返回 Frue 代替星號。
@IsCategory(True; False) 同上,但是如果沒有分類域,則返回 False。
@IsExpandable 如果當前行是可展開的,則返回一個加號。
@IsExpandable(True) 同上,只是返回 True 代替加號。
@IsExpandable(True; False) 同上,但是如果當前行是不可展開的,則返回 False。

使用 @function 通過 LS:DO 訪問外部數據庫

以下 @function 通過 ODBC 訪問外部數據庫並返回一個值或值的列表:
@DbColumn 返回表的一列中的全部值,或者全部的不同的值。
@DbLookup 返回表的一列中通過關鍵字匹配選定的值。
@DbCommand 將一個命令傳遞給外部的數據庫管理系統(DBMS)並返回結果。
@DbColumn 與 @DbLookup 都只能提取數據。它們不能增加、刪除、修改數據或執行其他操作。@DbCommand 能提取數據或發送其他可以更改數據的 SQL 語句。LotusScript 提供了包括更新外部數據庫的更加強大的功能。
前四個參數對於三個函數是同樣的,通過 ODBC 建立訪問數據庫。這些參數是:
"ODBC" 是字符常量;或 "ODBC" : "NoCache"
定義在數據源表格中的數據源名稱(在 Windows 中的 ODBC.INI)
用戶標識符,兩個用戶標識符列表,或者一個空串,根據外部數據源而定
口令,兩個口令列表,或者一個空串,根據外部數據源而定
(@DbColumn 和 @DbLookup) 要訪問的表的名稱
(@DbCommand) 要執行的命令
(@DbColumn 和 @DbLookup) 要訪問的列的名稱
處理由數據源返回的空數據的選項
(@DbLookup) 包含關鍵字的列名
(@DbLookup) 適當的數據類型的關鍵字值,或者是一個列表
(@DbColumn 和 @DbLookup) 兩個元素的列表:“Distinct”作爲關鍵字或空串;“Ascending”或“Descending”作爲一個關鍵字
在需要用 IDS 和口令的地方,您可以指定空串並讓用戶在執行函數時提供它們。

使用 @function 通過 LS:DO 訪問外部數據庫

1. 該公式取得 MANUAL 表中的 PARTNO 列。
@DbColumn("ODBC";"Oracle";"";"";"MANUALS";"PARTNO";"":"Ascending")
2. 該公式從 MANUALS 表的行中取得 TITLE,在該行中 PARTNO 是 17-895A。
@DbLookup("ODBC";"Oracle";"";"";"MANUALS";"TITLE";"PARTNO";"17-895A")
3. 該公式從 MANUALS 表中的 ONHAND 列的數字值小於 100 的每行中取得 PARTNO 列值。
@DbCommand("ODBC";"Oracle";"";"";"SELECT PARTNO FROM MANUALS WHERE ONHAND <100")

轉換數據類型

在對數據操作時類型必須是正確的。以下的函數用來轉換數據和測試數據類型。
函數 描述
@Text(value) 將一個值轉換爲文本字符串。
@Text(value; format) 根據指定的格式將一個數字或時間-日期值轉換成文本字符串。
@TextToNumber(string) 將文本字符串轉換成一個數字。
@TextToTime(string) 將文本字符串轉換成一個日期-時間值。
@IsText(value) 如果值是文本字符串或文本字符串列表,則返回“真”值 (1)。
@IsNumber(value) 如果值是數字或數字列表,則返回“真”值 (1)。
@IsTime(value) 如果一個值是時間-日期或時間-日期列表,則返回“真”值 (1)。
@Char(number) 將一個 IBM 代碼頁 850 代碼轉換爲對應的字符。


連接、比較和判定長度


運算符 + 用來連接字符串。運算符 =、<>、!=、=!、><、<、>、<= 和 >= 用來比較字符串。以下的函數用來判定字符串的長度和比較字符串:
函數 描述和用法
@Length (string) 以字符爲單位返回字符串的長度。
@Length(stringlist) 以字符爲單位,返回字符串列表中每個元素的長度。
@Matches (string; pattern) 判定兩個字符串是否匹配。可以用通配符來擴展比較的範圍。
@Like (string; pattern) 判定兩個字符串是否匹配。遵循 ANSI SQL 標準。
@Like(string; pattern; esc) 與上面的一樣只是多了一個轉義字符。
@Matches @Matches 用“?”來匹配任意一個單獨的字符,用“*”來匹配任意的字符序列,@Matches 使用“\”作爲轉義字符。
@Like 按照 ANSI X3.135-1992 標準,使用“_”(下劃線)來匹配任意一個單獨的字符,用“%”(百分號)來匹配任意的字符序列。

查找並提取子串

樣例
以下函數查找並提取子串:
函數 描述
@Contains(string; sub) 判定一個字符串是否包含一個子串。
@Contains(string; list) 判定一個字符串是否包含一個列表中的子串。
@Begins(string; sub) 判定一個字符串是否以一個子串開始。
@Ends(string; sub) 判定一個字符串是否以一個子串結束。
@Left(string; n) 從一個字符串中提取最左邊的 n 個字符。
@Left(string; sub) 從一個字符串中提取最左邊的字符,直到一個子串爲止,從左到右搜索。
@LeftBack (string; n) 從一個字符串中提取最左邊的字符,直到從右邊開始的第 n 個字符爲止。
@LeftBack(string; sub) 從一個字符串中提取最左邊的字符,直到一個子串爲止,從右到左搜索。
@Right(string; n) 從一個字符串中提取最右邊的 n 個字符。
@Right(string; sub) 從一個字符串中提取最右邊的字符,直到一個子串爲止,從左到右搜索。
@RightBack (string; n) 從一個字符串中提取最右邊的字符,直到從左邊開始的第 n 個字符爲止。
@RightBack(string; sub) 從一個字符串中提取最右邊的字符,直到一個子串爲止,從左到右搜索。
@Middle(string; off; n) 從一個字符串中提取 n 個字符,從一個偏移量開始,從左到右搜索。
@Middle(string; sub; n) 從一個字符串中提取 n 個字符,從一個子串開始,從左到右搜索。
@Middle(string; off; sub) 從一個字符串中提取字符,從一個偏移量開始,到一個子串結束,從左到右搜索。
@Middle(string; sub; sub) 從一個字符串中提取字符,從一個子串開始,到另一個子串結束,從左到右搜索。
@MiddleBack(str; off; n) 從一個字符串中提取 n 個字符,從一個偏移量開始,從右到左搜索。
@MiddleBack(str; sub; n) 從一個字符串中提取 n 個字符,從一個子串開始,從右到左搜索。
@MiddleBack(str; off; sub) 從一個字符串中提取字符,從一個偏移量開始,到一個子串結束,從右到左搜索。
@MiddleBack(str; sub; sub) 從一個字符串中提取字符,從一個子串開始,到另一個子串結束,從右到左搜索。
@ReplaceSubstring(source; from; to) 在 source 中用 from 的內容替換 to 的內容。如果 from 和 to 都是列表,按次序替換對應的項目。
@Word(string; sep; n) 從 string 提取單詞 n,其中單詞是在指定的分隔符之間的文本。
@Word(list; sep; n) 從列表中的每個字符串中提取單詞 n,其中單詞是在指定的分隔符之間的文本。


修剪、重複、添加新行,並改變大小寫

樣例

以下函數修剪字符串、重複字符、添加新行(回車),並改變大小寫:
函數 描述
@Trim(string) 從字符串中刪除開頭、結尾和多餘的空格。
@Trim(list) 從字符串列表的每個元素中刪除開頭、結尾和多餘的空格,並從列表中刪除空白元素。
@Repeat(string , number) 將字符串重複若干次。
@NewLine 在文本字符串中插入一個新行(回車)。
@LowerCase(string) 將字符串中所有的大寫字符轉換成小寫。
@UpperCase(string) 將字符串中所有的小寫字符轉換成大寫。
@ProperCase 將字符串中每個單詞的第一個字符轉換成大寫,並將其餘的字符轉換爲小寫。


執行算術運算

乘、除、加、減運算符(*/+-)。乘法和除法運算符的優先級高於加法和減法;運算順序是從左到右。但可以使用括號更改運算順序。以下列出的是算術運算函數。
函數 描述
@Abs(number) 計算一個數的絕對(無符號)值。
@Sign (number) 對於正數返回 1,對於負數返回 -1,對於零則返回 0。
@Sum(num; num; ...) 計算數字和數字列表的和。
@Integer(number) 去掉數字的小數部分,使它成爲整數。
@Integer(numlist) 去掉數字列表所有元素的小數部分,使它們成爲整數。
@Round(number) 對一個數字進行四捨五入。
@Round(number; factor) 以一個指定的因子規整數字。
@Round(numlist) 對數字列表中的每個數字進行四捨五入。
@Round(numlist; factor) 以一個指定的因子規整數字列表中的每個元素。
@Max(number; number) 取兩個數中較大的一個。
@Max(numlist; numlist) 對兩個數字列表進行矩陣式操作時,取兩個數字中較大的一個
@Min(number; number) 取兩個數中較小的一個。
@Min(numlist; numlist) 對兩個數字列表進行矩陣式操作時,取兩個數字中較小的一個。
@Modulo(number; number) 計算一個數字被第二個數字除後得出的餘數。
@Modulo(numlist; numlist) 對兩個數字列表進行矩陣式操作時,計算一個數字被第二個數字除後得出的餘數。
@Power(base; exp) 指數計算。
@Sqrt (number) 計算平方根。
@Pi 取得圓周率。
@Log(number) 計算常用(以 10 爲底)對數。
@Ln(number) 計算自然(以 e 爲底)對數。
@Exp(number) 計算以 e 爲底的指數。
@Random 返回一個 0 到 1 之間的隨機數。
@Sin(angle) 計算角度的正弦(弧度)。
@Cos(angle) 計算角度的餘弦(弧度)。
@Tan(angle) 計算角度的正切(弧度)。
@Asin(sine) 反正弦函數。
@Acos(cosine) 反餘弦函數。
@Atan(tangent) 反正切函數。
@Atan2(x; y) 計算以 y/x 作爲正切值的反正切函數。

答覆列的公式

僅用於答覆的列需要公式來生成總結答覆文檔的文本。
包含作者的信息
討論數據庫可以使用如下答覆列的公式來顯示答覆文檔的作者、日期和主題:
From + " added this comment: " + Subject + " (" + @Text(@Created) + ")"
按以下方式顯示答覆:
Stephanie Mahar added this comment: Great job! (10/10/97 04:43:15 PM)
跟蹤文檔狀態
在僱員信息數據庫中,答覆列可以顯示新僱員以及離職僱員的調查信息,作爲“按僱員姓名”視圖中常規的“僱員記錄”的答覆文檔。下面公式根據答覆文檔使用的表單的不同,顯示不同的消息,並且顯示文檔的郵遞狀態。
@If(Form = "Exit"; "Exit Form, "; "New Hire Information, ") + @If(Mailed = "Yes"; "mailed to employee " + @Text(@Date(PostedDate)); "not yet mailed")
如果答覆文檔使用 Exit 表單,那麼答覆行顯示也許如下:
Exit Form, mailed to employee 08/26/97
如果答覆文檔使用 New Hire Information 表單,那麼答覆行顯示也許如下:
New Hire Information, not yet mailed
跟蹤答覆的數目
可以使用 @DocDescendants 跟蹤答覆文檔的數目,以便作者迅速知道收到多少答覆文檔。下面的主文檔列(不是答覆列)公式對於答覆樣式的視圖非常有用。
Subject + " (" + @Name([CN]; From) + @DocDescendants(")"; ", % response)"; ", % responses)")
如果是主文檔,那麼列顯示 Subject 域的內容、作者名稱、答覆以及答覆的答覆文檔的數目。如果文檔有一個答覆,那麼列顯示“response”;否則顯示“responses”。主文檔行可作如下顯示:
Need Help with Trade Show (Indy Montoya, 1 response)
Changing the Product Name (Sandy Braun, 2 responses)



視圖小程序編程
通過使用一些 @commands 命令可以對視圖小程序編程。有以下命令:
@command 描述
ViewCollapse 摺疊所選文檔
ViewExpand 展開所選文檔
ViewCollapseAll 摺疊所有文檔
ViewExpandAll 展開所有文檔
ViewRefreshFields 刷新視圖。
刷新時,視圖小程序不刪除標記爲已刪除的文檔
MoveToTrash 使當前所選文檔標記爲已刪除
EmptyTrash 永久刪除標記爲已刪除的文檔
Folder 將所選文檔移動或拷貝到文件夾
RemoveFromFolder 從當前文件夾刪除所選文檔。


用新建表單增強Notes打印功能中央財經大學 鄒龍泉
02-1-31 下午 01:56:09

Lotus公司推出的Lotus Domino/Notes作爲辦公自動化系統的平臺近年來在國內得到了廣泛的應用,許多的政府主管部門、金融單位、企事業單位都使用了Notes以及在Notes上開發的各種辦公系統,工作效率得到了極大的提高。
在實際的應用中,爲了存檔以及供沒安裝Notes系統的部門傳閱,許多在Notes系統中流轉的電子文檔需要打印出來。不幸的是,Notes提供的打印功能很弱,一個文檔只能按照給定表單的版式進行打印。但在實際的使用中,如政府部門,內容相同的一個文檔,其上行公文和下行公文的版式是不一樣的,這就需要將同一文檔用多種樣式打印。最直接的想法當然是在Designer中修改表單的版式,但由於應用系統一般是隱藏設計的,表單無法修改。還有就是最終用戶的計算機水平有限,直接修改表單從技術上講也行不通。
這時一個可行的做法就是:用VC++給用戶提供一個“所見即所得”的編輯界面,並列出Notes文檔中各部分的內容,讓用戶以拖放的方式將相關內容放到適當的位置上,同時還可以加入文字、圖片等修飾內容,然後按照最終的版式在Notes外部直接生成一個Notes表單,並用此表單進行打印。這種方法既繞過了隱藏設計的障礙,又降低了對最終用戶的技術要求。當然這一切都得益於Notes提供的API函數。
由於只需一個NSFItemScan函數就能收集到Notes文檔中所有的域,而又有多種靈活的方式實現“所見即所得”的排版功能,因此在提出上述的思路後,本文將主要介紹如何構造Notes表單。

一、Notes表單結構簡介
一個表單中有三個必需的域:$TITLE、$INFO和$BODY,輔助性的還有$FIELDS域及屬性爲placeholder的各域。
1.$TITLE域
$TITLE域的類型爲TYPE_TEXT,其中保存表單的名稱,Notes客戶端窗口中“創建”菜單下列出的各表單名即爲各表單note中$TITLE域的值。在Notes提供的C API頭文件“stdnames.h”中有預定義的常量ITEM_NAME_TEMPLATE_NAME代表表單note的名稱域,爲保證程序的向後兼容,建議使用常量而避免直接使用$TITLE。
2.$INFO域
由於表單和文檔的創建有關,$INFO域定義了通過此表單創建的文檔的一些屬性。實際上$INFO域中存儲的是一個名爲CDDOCUMENT的結構體,對生成文檔屬性的設定就是通過對該結構體中各分量的不同賦值實現的。結構體CDDOCUMENT 的定義及說明見Lotus C API 的參考文檔。
$INFO域的類型爲TYPE_COMPOSITE,對應的預定義常量爲ITEM_NAME_DOCUMENT。
3. $BODY域
$BODY域是表單note中的核心域,整個表單顯示和打印時的格式,還有通過此表單生成的文檔所包含的域及其類型,都是在本域中定義的。由於$BODY域的結構非常複雜,本文將在第二部分專門介紹。$BODY域也是TYPE_COMPOSITE類型的,名稱預定義常量爲ITEM_NAME_TEMPLATE。
4. $FIELDS域
$FIELDS域是一個TYPE_TEXT_LIST類型的域,其中包含了用此表單生成的文檔包含的所有域。但專爲打印生成的表單中可以沒有此域。
5. "placeholder"域
對$BODY域中定義的將來文檔中要含有的每一個域,在表單中都對應一個類型爲TYPE_INVALID_OR_UNKNOWN而標誌爲ITEM_PLACEHOLDER的域,域名和$BODY域中定義的一樣,而其值爲NULL。
標誌爲ITEM_PLACEHOLDER的域將被加入到“域名錶”中,這樣當用戶選擇了客戶端中的“設計”菜單中的“視圖”子菜單後,在彈出的對話框中選擇“添加域”時,該域名纔會被顯示出來。
同樣,這些域在打印的表單中不是必需的。

二、$BODY域詳解
$BODY域中可以包含各種Notes對象,如文本、域、圖像、熱點、鏈接等,還有一些輔助性對象,如段定義、段引用等。爲方便管理,所有這些對象的定義都是通過不同的結構體實現的。Notes中定義對象的結構體都以“CD”開頭,如CDTEXT定義靜態文本、CDFIELD定義域等,其他對象的具體定義請查閱Lotus C API 的參考文檔。
通常,一個$BODY域的整體結構是這樣的:
CDPABDEFINITION
CDPABDEFINITION
...
CDPARAGRAPH
CDPABREFERENCE
CDTEXT
text
...
CDPARAGRAPH
CDPABREFERENCE
CDBEGINRECORD
CDFIELD
CDBEGINRECORD
...
下面對其中的各部分分別予以說明。
1.段落預定義部分
CDPABDEFINITION定義頁面上一個段落的屬性,在這個結構體中我們可以定義段落的對齊方式、頁邊距、段間距、行間距等。在後面的某個具體段落中,如果定義了到此段定義的引用,則該段落就具有了此處定義的各屬性。
段落的定義可以放在$BODY域的開頭,也可以放在中間,只要保證序號PABID不重複就可以了。
2.靜態文本的定義
上述總體結構的中間部分定義了一段文本:CDPARAGRAPH定義一段的開始,類似文本串中的一個回車換行符;CDPABREFERENCE定義一個到段定義的引用,從而本段就具有了前面定義的各種屬性;CDTEXT是文本的頭部,包含有文本的長度、字體、顏色等信息;text是實際的文本。
3.域的定義
對域的定義也是以CDPARAGRAPH和CDPABREFERENCE開始,但與文本不同的是,像域、圖像等對象的定義,除了有作爲頭部的結構體外,還要有一對界定結構體CDBEGINRECORD和CDENDRECORD放在對象定義的前後兩端。
有時在域的前面還要有一些提示性文字,如一個用於接收姓名的域name,通常在其前面要有“姓名”兩個字,以便具體操作者知道此處要輸入姓名。具體創建域時,這部分內容以文本形式放在CDBEGINRECORD之前,格式如上一步中所述。
在貨幣型或數值型的域中,爲了對數據的格式進行更進一步的控制,在CDBEGINRECORD和CDFIELD中間還要插入一個CDEXT2FIELD結構,該結構提供了附加的格式定義。
域中的其他元素,如默認值計算公式、輸入變換公式、域名、描述字串等放在CDFIELD後面,排列順序和其長度值在CDFIELD結構體中的位置順序一致。當然除域名外,其他元素如不是必要可以省略。
在本部分中,以文本和域爲例,介紹了$BODY域中各對象的具體定義方式,其他對象與此類似。

三、創建Notes表單
在瞭解了Notes表單結構的基礎上,通過API函數建立表單就很容易了。
首先打開一個數據庫,然後在其中新建一個空白note,接下來就可以向其中添加各域了。像$TITLE這樣的單一類型的域,可以直接調用NSFItemSetText函數創建。而像$INFO和$BODY這樣的複合類型的域,就比較麻煩一些。通常的做法是,先申請一塊足夠大的內存,然後順序寫入各部分內容,最後調用NSFItemAppend函數創建域。
在向複合域中寫入數據時,文本、域名等一般字符串可以直接寫入,而各種結構體需調用ODSWriteMemory函數以Domino規範的形式寫入,另外就是域定義中用到的各種公式,在寫入前要經過NSFFormulaCompile變換。

四、例程
下面的程序段定義了一個帶有默認值公式的名爲“TextField”的域:

char TextFieldName[] = "TextField";
char TextDescription[] = "This is a Simple Text Field";
char TextDefValFormula[] = "\"Default\"";
char far *pBufferStart, far *pBuffer;
HANDLE hMem;
CDPABREFERENCE CDPabRef;
CDPARAGRAPH CDPara;
CDBEGINRECORD CDBegin;
CDENDRECORD CDEnd;
CDEXT2FIELD CDExt2Field;
CDFIELD CDField;
FONTIDFIELDS *pFontFields;

// 申請內存並鎖定內存,獲得指向該塊內存的指針
OSMemAlloc (0, wCDBufferLength, &hMem);
pBufferStart = (char far *)OSLockObject(hMem);
memset( pBufferStart, 0, (size_t) wCDBufferLength );
pBuffer = pBufferStart;

// 填寫 PARAGRAPH 結構
// 結構體的長度
CDPara.Header.Length = (BYTE) ODSLength(_CDPARAGRAPH);
// 結構體的類型
CDPara.Header.Signature = (BYTE)SIG_CD_PARAGRAPH;
// 轉換爲Domino規範的形式寫入申請的內存
ODSWriteMemory( (void far * far *)&pBuffer, _CDPARAGRAPH, &CDPara, 1 );

// 填寫 PABREF 結構
CDPabRef.Header.Signature = (BYTE)SIG_CD_PABREFERENCE;
CDPabRef.Header.Length = (BYTE) ODSLength(_CDPABREFERENCE);
// 要引用的段定義的序號
CDPabRef.PABID = wPabDefNumber;
ODSWriteMemory( (void far * far *)&pBuffer, _CDPABREFERENCE, &CDPabRef, 1 );

// 填寫CDBEGINRECORD 結構
CDBegin.Header.Length = (BYTE)ODSLength(_CDBEGINRECORD);
CDBegin.Header.Signature = SIG_CD_BEGIN;
CDBegin.Version = 0;
CDBegin.Signature = SIG_CD_FIELD;
ODSWriteMemory( (void far * far *)&pBuffer, _CDBEGINRECORD,(void far *) &CDBegin, 1 );

// 填寫CDEXT2FIELD 結構
memset(&CDExt2Field, 0, sizeof(CDEXT2FIELD));
CDExt2Field.Header.Length = (WORD)ODSLength(_CDEXT2FIELD);
CDExt2Field.Header.Signature = SIG_CD_EXT2_FIELD;
ODSWriteMemory( (void far * far *)&pBuffer, _CDEXT2FIELD, (void far *) &CDExt2Field, 1 );

// 填寫CDFIELD 結構,定義文本域
CDField.Header.Signature = SIG_CD_FIELD;
CDField.Flags = FEDITABLE;
CDField.DataType = TYPE_TEXT;
CDField.ListDelim = LDDELIM_SEMICOLON;

// 本域中不用數值格式參數,全部清零
CDField.NumberFormat.Digits = 0;
CDField.NumberFormat.Format = 0;
CDField.NumberFormat.Attributes = 0;
CDField.NumberFormat.Unused = 0;

//本域中不用時間格式參數,全部清零
CDField.TimeFormat.Date = 0;
CDField.TimeFormat.Time = 0;
CDField.TimeFormat.Zone = 0;
CDField.TimeFormat.Structure = 0;

// 設定FontID
pFontFields = (FONTIDFIELDS *)&CDField.FontID;
pFontFields->Face = FONT_FACE_ROMAN;
pFontFields->Attrib = 0;
pFontFields->Color = NOTES_COLOR_BLACK;
pFontFields->PointSize = 14;

// 編譯默認值公式
NSFFormulaCompile(NULL, 0, TextDefValFormula, (WORD) strlen(TextDefValFormula), &hTextDefValFormula, &wTextDefValFormulaLen, &wdc, &wdc, &wdc, &wdc, &wdc))

// 填寫CDFIELD 結構的其餘部分,因爲DVLength值只有公式編譯後才知道
CDField.DVLength = wTextDefValFormulaLen;
CDField.ITLength = 0;
CDField.TabOrder = 0;
CDField.IVLength = 0;
CDField.NameLength = strlen(TextFieldName);
CDField.DescLength = strlen(TextDescription);
CDField.TextValueLength = 0;
CDField.Header.Length = ODSLength(_CDFIELD) +CDField.DVLength +CDField.ITLength +CDField.IVLength +CDField.NameLength +CDField.DescLength +CDField.TextValueLength;

// 保證CDFIELD域長度爲偶數
if (CDField.Header.Length % 2)
CDField.Header.Length++;
ODSWriteMemory( (void far * far *)&pBuffer, _CDFIELD, (void far *)&CDField, 1 );

// 獲取指向編譯後公式的指針
pTextDefValFormula = OSLock( char, hTextDefValFormula );
// 寫入公式內容到內存
memcpy( pBuffer, pTextDefValFormula, wTextDefValFormulaLen );
pBuffer += CDField.DVLength;
// 解鎖並釋放公式佔用的空間
OSUnlockObject(hTextDefValFormula);
OSMemFree(hTextDefValFormula);

// 域名部分,直接寫入
memcpy( pBuffer, TextFieldName, CDField.NameLength );
pBuffer += CDField.NameLength;

// 域描述部分,直接寫入
memcpy( pBuffer, TextDescription, CDField.DescLength );
pBuffer += CDField.DescLength;

// 保證整個域定義的長度爲偶數
if ((pBuffer-pBufferStart) %2)
pBuffer++;

// 填寫CDENDRECORD結構
CDEnd.Header.Length = (BYTE)ODSLength(_CDENDRECORD);
CDEnd.Header.Signature = SIG_CD_END;
CDEnd.Version = 0;
CDEnd.Signature = SIG_CD_FIELD;
ODSWriteMemory( (void far * far *)&pBuffer, _CDENDRECORD, (void far *) &CDEnd, 1 );



在web上顯示視圖的時候,總是不喜歡notes的默認界面,想換成表格的。用表格顯示很容易,別讓notes生成HTML,全部由你自己定製就成了。但如何交替用顏色顯示不同行呢?就是說當view行數是寄數時顯示一種顏色,偶數時顯示另一種顏色。
原先想用@docnumber去做,但@docnumber產生的值時一個特殊值,無法轉換成數字來判斷。在www.lotus.com的開發者原地有一篇類似介紹,用的方法是把docnumber直接打印到html裏,然後再用javascript來判斷,這樣雖然可以,但非常的麻煩。
下面有一種比較簡便的方法:還是用javascript:
function transformView() {
var tableElements = document.getElementsByTagName('table') ;
var table = tableElements[tableElements.length - 1] ;
//上面是你的表格再頁面中倒數第幾個表格,如果你是倒數第2個,就-2
table.width = '100%' ;
table.cellSpacing = '0' ;
headers = table.getElementsByTagName("th") ;
for( i = 0; i < headers.length; i++) {
headers.bgColor = '#cccccc' ;
}
rows = table.getElementsByTagName("tr") ;
var counter = 0
for( i = 0; i < rows.length; i++) {
rows.bgColor = (i % 2 ? '#efefef' : '') ;
}
}
怎麼樣,是不是很cool?

如何將Domino服務器配置爲Internet郵件服務器?
在學習配置之前,我們需要先簡單瞭解一下協議的概念。
在進行Internet郵件收發的時候,我們需要使用到下面兩個協議:
SMTP(簡單消息傳輸協議)管理Internet郵件發送
POP3(郵局協議)管理Internet郵件接收
實際上兩者的功能劃分並不是如此清楚,也就是說兩者間關係是相輔相成的,獨立任何一方都不可能完成任務。
好了,協議就瞭解到這裏,我們來看看最具體的東西,配置步驟:
1、配置——服務器配置文檔——基本中,打開SMTP郵件郵遞和SMTP偵聽任務選項
2、在服務器配置文檔——基本中,定義全限定的Internet主機名,也就是說用戶的郵件地址會是:用戶名@全限定Internet主機域名,比如用戶admin,全限定的Internet主機名爲www.flycat.net,那麼該用戶的郵件地址就是[email protected]
3、將POP3加入NOTES.INI的ServerTasks參數中
4、配置——消息處理——網絡域——添加網絡域
5、確定網絡域類型爲全球網絡域
6、確定網絡域名稱,任意都可以
7、確定網絡域角色爲R5 Internet網絡域
8、確定爲缺省全球網絡域
9、在網絡域文檔中定義郵件地址轉換規則
10、配置——消息處理——配置——添加配置
11、啓動配置文檔中的“在本地INTERNET網絡域以外發送消息所用SMTP”
12、作好域名解析工作
13、重新啓動服務器
14、用E-Mail客戶端試試好了

LotusDomino環境下編寫Web瀏覽器多數據庫檢索程序  
   隨着計算機技術的日益普及,Internet/Intranet技術得到了更加廣泛的應用,在世 界範圍的大量Web網點上以及公司內部的Web服務器上,都存放着大量的信息。爲使這些信 息得到的合理使用,Web服務器管理員應該爲用戶提供方便的信息檢索方法。作爲羣件代 表的Lotus Domino 4.5集成了郵件處理、羣件應用和Internet出版等功能,是Notes技術向Internet/ Intranet融合開放的里程碑式的產品。在繼承以往產品全部優點與功能的基礎上,Domino 將原先的Notes服務器提升爲用途更廣泛、使用更方便的Internet/Intranet服務器。在 Domino的幫助下用戶能夠快速 構建安全可靠的Web網點,開發出管理和控制Internet/Intranet的應用程序,並通過Web 瀏覽器實現對各類數據和服務器的交互式訪問。Domino還爲用戶提供了多種檢索信息的方 法,而且用戶甚至不必編程。本文所要討論的是通過簡單編程實現在Web瀏覽器上對任意 多個數據庫同時進行檢 索的一種方法。   下面給出具體的實現方法:   1、創建數據庫SiteSearch.NSF。   2、在數據庫SiteSearch.NSF上創建Form名稱爲 SearchForm。   3、在SearchForm上創建Field,內容如下:   (1)DatabaseNames:類型爲關鍵字,可編輯,允許多值,範圍爲:每行輸入一個關 鍵字。關鍵字列表框內輸入允許搜索的數據庫列表。   假設有五個數據庫允許用戶檢索,它們分別是:討論板(Discuss.NSF)、規章制度 (Institution.NSF)、技術論文(TechDocuments.NSF)、公司最新動態( CompanyNews.NSF)、簡報及公告(Bulletin.NSF),則在DatabaseNames關鍵字列表框內 可輸入:   討論板 | Discuss.NSF   規章制度| Institution.NSF   技術論文| TechDocuments.NSF   公司最新動態 | CompanyNews.NSF   簡報及公告 | Bulletin.NSF   (2)SearchString:類型爲文本,可編輯。   (3)$$QuerySaveAgent :類型爲文本,顯示時計算,數值爲textSearchQuerySaveA gent,隱藏。   (4)SaveOptions:類型爲文本,可編輯,默認值爲“0”,隱藏。   4、創建代理TextSearchQuerySaveAgent。運行代理時間指定爲:從“操作”菜單中 選擇執行。指定代理操作的文檔爲:運行一次(可能使用@命令)。   代理程序的內容如下:   Sub Initialize    Dim ArrNsf As Variant    Dim item As NotesItem    '獲得文檔 context,因爲此代理是一個$$QuerySaveAgent,所以$$QuerySaveAgent 可以訪問 Context文檔上的項目。    Dim sess As New NotesSession    Dim doc As NotesDocument    Set doc = sess.DocumentContext    '輸出HTML頁面的頭部和標題:    Print {<html>}    Print { <head>}    Print {<meta http-equiv="Content-Type" content="text/html; charset=gb2312">}    Print {<title>}    Print "多數據庫搜索"    Print {</title>}    Print {</head>}    '設置HTML頁面的背景顏色:    Print {<body text="000000" bgcolor="f7f7f7">}    '獲得欲檢索的數據庫,存放在數組ArrNsf內:    ArrNsf= doc.DatabaseName    '如果沒有輸入檢索條件,則輸出提示信息:    If Trim(Cstr(doc.Query(0)))="" Then    Goto EmptyQuery    End If    Dim MatchDoc As NotesDocument    Dim db As NotesDatabase,    Dim collection As NotesDocumentCollection    '下列循環從數組ArrNsf中取得欲檢索的數據庫進行處理:    For nsfCount=0 To Ubound( ArrNsf )    SearchDB=ArrNsf(nsfCount)    Set db = sess.GetDatabase("",SearchDB)    '出現錯誤則轉向:    On Error Goto BadQuery    '獲得滿足查詢條件的記錄集:    Set collection = db.FTSearch(doc.Query(0),0)    On Error Goto 0    '輸出數據庫標題:    Print "<Hr>"    Print db.title    Print "<Hr>"    '輸出該數據庫中滿足條件的記錄個數:    Print "<font size=5><b>There are " & Str$(collection.Count) & " matching documents</b></font><br>"    '下列循環從滿足條件的記錄集中讀取記錄並輸出:    For i% = 1 To collection.Count    Set MatchDoc = collection.GetNthDocument(i%)    Print {<br><a href="/} &SearchDB &{/AllDocument/} & MatchDoc.UniversalID &{?OpenDocument">}    Print "<b>"    '如果文檔包含Subject或Title,則輸出Subject或Title:    Set item =MatchDoc.GetFirstItem( "Subject" )    If ( item Is Nothing ) Then    Set item = MatchDoc.GetFirstItem( "Title" )    End If    If Not (item Is Nothing) Then    Print " <b>" & item.Name & "</b>: " & item.Text    End If    '如果文檔包含Categories,則輸出Categories:    Set item = MatchDoc.GetFirstItem( "Categories" )    If Not (item Is Nothing) Then    Print item.Name & "</b>: " & item.Text    End If    '輸出文檔產生日期和作者:    createDate = MatchDoc.Created    Print "Document create date:" &createDate    Print " Authors: "    Forall aAuthor In MatchDoc.Authors    Print aAuthor    End Forall    Print "</a><br>"    Next    Next   Out:    Print {</body></html>}    Exit Sub   EmptyQuery:    Print {<b>Search query can not be empty </b>}    Resume Out   BadQuery:    Print {<b>Query is not understandable: </b>"} & doc.Query(0) & {"}    Resume Out   End Sub   在本例中使用的FTSearch搜索查詢內容是一個符合 Notes 全文檢索規則的字符串, 搜索內容可以是一個字詞或多個字詞。搜索內容可以包括 ? 和 * 通配符,並且可以由 ! (not)、& (and)、|(or) 操作符混合。所檢索的數據庫可以有全文索引,也可以沒有全文索引。如果沒有全文索引 ,則搜索速度會慢一些。運行本程序時,應先從瀏覽器中輸入URL:http://homeURL/Site Search.NSF/SearchForm?OpenForm,然後選擇欲檢索的數據庫並輸入檢索條件,單擊 Submit按鈕,則將列出所有 符合檢索條件的文檔。
版權所有2001

首頁-->LOTUS文章-->LOTUS Scrpit編碼指南
    編寫公式的方法一個公式中含有一條或多條按順序執行的語句。根據與公式相關聯的對象和其他標準的不同,公式可以在所選的文檔上運行一次或多次(每個文檔運行一次)。除了從公式返回以外,公式中沒有循環和控制跳轉的語句。公式中對條件執行路徑也有限制。代理公式將在選定的文檔上多次地、有條件地執行。您可以:編寫可得出計算結果的公式以下公式都應該有最後結果:複製公式 必須得出結果爲真 (1) 或假 (0),並且可以應用到數據庫的每個文檔上。表單公式 必須得出表單名稱。選擇公式 必須得出結果爲真 (1) 或假 (0),並且可以應用到視圖中的每個文檔上。列公式 必須得出一個可以轉換成文本字符串的值。顯示操作公式 必須得出真 (1) 或假 (0)。彈出式公式 必須得出一個文本串。窗口標題公式 必須得出一個文本或數字值,除非公式由一個任意類型的單獨的域組成。區段存取公式 必須得出一個姓名或姓名列表。插入子表單公式 必須得出一個子表單的名稱的文本值。區段標題公式 必須得出一個文本或數字值,除非公式由一個任意類型的單獨的域組成。段落隱藏公式 必須得出真 (1) 或者假 (0)。缺省值公式 必須得出一個可以存放在當前域中的值。輸入轉換公式 必須得出一個可以存放在當前域中的值。缺省校驗公式 必須得出是成功 (1) 還是失敗 (0)。計算域公式 必須得出一個可以存放在當前域中的值。關鍵字公式 必須得出一個可以存放在當前域中的值或值的列表。這些公式可以簡單到只有一個域、常量或者函數,也可以包含很多語句、使用臨時變量、更改域的內容或者產生一些附加效果。但不論如何,其最後一個語句必須是一個合適的值。如果關鍵字 SELECT 沒有顯式指定的話,它會加在一個邏輯語句之前,這個邏輯語句用來終止複製或選擇公式。這些公式運行於數據庫(複製公式)或視圖(選擇公式)的每一個文檔上,以確定複製和查看過程中包括或不包括哪些文檔。函數 @All 返回一個真值因此公式“SELECT @All”將包括所有文檔。樣例:編寫得出結果的公式1. 此樣例是標準討論數據庫中“From”域的缺省值公式。它只包含一個返回用戶姓名的函數。@UserName2. 此樣例是一個標準討論數據庫中“Subject”域的輸入校驗公式。它含有一個 @If 函數,如果“Subject”是空的(用戶未輸入任何值),它將返回一個失敗的值,反之則返回成功值。失敗時還將顯示一個消息。@If(Subject = ""; @Failure("You must enter a subject for your document."); @Success)3. 該樣例是標準討論數據庫的“Memo”表單的窗口標題公式。它只有一個語句,但包含有嵌套的 @If 命令。如果當前文檔是新的,則窗口標題是“New Memo”。如果當前文檔已經存在,並有一個“Subject”域,而且該域非空,則窗口標題將取“Subject”域中的內容(如果文檔帶有附件,則標題前還會出現“>>”)。如果不存在“Subject”域或該域爲空,則窗口標題爲創建日期。@If(@IsNewDoc; "New Memo"; @If(@IsAvailable(Subject) & Subject != ""; @If(@Attachments; "* "; "") + Subject; @Text(@Created)))編寫執行操作的公式下列公式不產生一個最後的可用結果,但可以改變域值和產生附加動作:便捷圖標公式 觸發時執行一次。代理公式 觸發時在一個數據庫上執行。一個代理公式運行在數據庫中所選的每個文檔上,這些文檔由 UI 中指定的條件和公式中的 SELECT 關鍵字所決定。SELECT 關鍵字缺省是 SELECT @All。操作公式 觸發時在一個視圖或表單中執行。按鈕公式 觸發時在一個表單、導航器或 RTF 域中執行。操作熱點 觸發時在一個表單、導航器或 RTF 域中執行。樣例:編寫執行操作的公式該代理樣例將一個基於“Main”表單的文檔中的“Address”域的“Wayside Street”替換成“Wayside Drive”。有效的操作是 FIELD Address 賦值語句。如果 Address 中含有“Wayside Street”,則新的 Address 的內容是將字符串“Wayside Street”左邊的字符,加上字符串“Wayside Drive”,然後再加上 Address 中“Wayside Street”右邊的字符。否則,Address 將被重置爲它的當前值。SELECT Form = "Main Form";ws := "Wayside Street";wd := "Wayside Drive";FIELD Address := @If(@Contains(Address; ws); @Left(Address; ws) + wd +@Right(Address; ws); Address)處理列表列表就是一個可以包含多個同類型值的命名實體。列表出現在以下幾種情況:允許多值的域可能包含一個列表而非一個單值。某些函數返回一個列表。常量可以被指定爲一個列表或者是單值。語法是多個單值用冒號分開;例如,"London":"New York":"Tokyo" 就是一個由三個元素構成的字符串列表常量。由於列表的連接運算具有最高的優先級,所以如果列表元素中的表達式是一個僅用於其自身的表達式的話,它就必須用括號括起來。例如,如果 3 爲負數而 4 不是負數的話就應該寫成 1:2-3):4,而不是 1:2:-3:4 。並列運算或交叉運算時的列表組合。列表限制了操作的範圍,因爲列表操作僅限於每一個列表元素。就象在一個循環中處理數組一樣。以下函數是列表所特有的。函數 描述@Elements(list) 確定列表元素的數量。@Explode(string) 將文本字符串轉換成一個文本列表。空格、逗號和分號用於分隔字符串的元素。@Explode(string; separator) 與上面的函數一樣,但第二個參數指定了字符串中的元素的分隔符。@Explode(string; separator; empties) 與上面的函數一樣,但是返回值爲 @True ,因爲第三個參數包含空的列表元素,其中出現了連續的分隔符。@Explode(date-range) 將一個日期範圍轉換成一個日期列表。參數必須是一個時間-日期值;返回值是文本列表。@Implode(list) 將文本列表轉換成文本字符串,用空格分隔各個元素。@Implode(list; separator) 與上面的函數一樣,但是第二個參數指定了字符串中每個元素之間的分隔符。@IsMember(string; list) 確定一個字符串是否爲一個列表的成員。返回真 (1) 或假 (0)。@IsMember(list1; list2) 確定一個列表是否被包含在另一個列表中。返回真 (1) 或假 (0)。@IsNotMember(string; list) 確定一個字符串是否不是一個列表的成員。返回真 (1) 或假 (0)。@IsNotMember(list1; list2) 確定一個列表是否不被包含在另一個列表中。返回真 (1) 或假 (0)。@Keywords(list1; list2) 在 list1 中找到與 list2 中的單詞相匹配的單詞。單詞分隔符有 " , ? ! ; : [ ] { } < >。@Keywords(list1; list2; separator) 與上面的函數一樣,但第二個參數指定了單詞的分隔符。@Member(value; list) 確定一個值在字符串列表中的位置。@Replace(list1; list2; list3) 將 list1 中與 list2 相匹配的值用 list3 中對應的值替換。@Subset(list; n) 從列表中提取出 n 個值。用 -n 表示從右到左提取。@Unique(list) 從字符串列表中刪除重複的值。@Unique 返回一個隨機的,唯一的文本值。樣例:使用列表1 (並列運算)該樣例用並列算法把兩個數字列表相加。結果列表中有四個值 11、22、27 和 44。list1 := 10 : 20 : 30 : 40;list2 := 1 : 2 : (-3) : 4;list3 := list1 + list2;result := @Text(list1) + " + " + @Text(list2) + " = " + @Text(list3);@Prompt([OKCANCELLIST]; "Result"; ""; ""; result)2 (交叉運算)該樣例用交叉算法將兩個列表連接起來。結果列表中有 12 個值:Blue Sedan、Blue Coupe、Blue Van、Blue Truck、Red Sedan 等等最後是 Yellow Truck。cars := "Sedan" : "Coupe" : "Van" : "Truck";colors := "Blue" : "Red" : "Yellow";result := colors + " " *+ cars;@Prompt([OKCANCELLIST]; "Result"; ""; ""; result)3 (@Elements) 如果“Categories”域中沒有元素,此例將顯示一條消息,如果有的話則顯示列表。@If(@Elements(Categories) = 0; @Prompt([OK]; "Categories"; "No categories");@Prompt([OKCANCELLIST]; "Categories"; ""; ""; Categories))4 (@Explode) 該樣例使用缺省的分隔符空格、逗號和分號,把一個字符串分離成一個列表。結果列表中的值是:Paris、London、Chicago 和 Seoul。cityList := @Explode("aris London,Chicago;Seoul");@Prompt([OKCANCELLIST]; "List of cities"; ""; ""; cityList)5 (@Explode) 該樣例使用分隔符逗號和分號將一個字符串常量分離成一個列表。結果列表中的值爲:Paris、London、New York 和 Hong Kong。New York 和 Hong Kong 沒有分離成 New、York、Hong 和 Kong,這是因爲沒有將空格作爲分隔符。cityList := @Explode("aris,London,New York;Hong Kong"; ",;");@Prompt([OKCANCELLIST]; "List of cities"; ""; ""; cityList)6 (@Explode) 該樣例在 London 和 New York 之間有一個空條目。如果第三個參數是 @False 或者被忽略,那麼多個連續的分隔符將被看作一個。請確信逗號是連續的,沒有被空格分隔。cityList := @Explode("aris,London,,New York;Hong Kong"; ",;"; @True);@Prompt([OKCANCELLIST]; "List of cities"; ""; ""; cityList)7 (@Implode) 該樣例將一個列表常量組合到一個字符串變量中,用空格(缺省)作爲分隔符。結果字符串中的值爲:Minneapolis Detroit Chicago。city := "Minneapolis" : "Detroit" : "Chicago";cityString := @Implode(city);@Prompt([OK]; "Imploded string"; cityString)8 (@Implode) 該樣例將一個列表常量組合到一個字符串列表中,用逗號和空格作爲分隔符。結果字符串中的值爲:Minneapolis, Detroit, Chicago。city := "Minneapolis" : "Detroit" : "Chicago";cityString := @Implode(city; ", ");@Prompt([OK]; "Imploded string"; cityString)9 (@Implode) 該樣例使用冒號作爲分隔符將一個列表域分離成一個字符串。如果 Categories 域中的輸入是 Minneapolis, Detroit, Chicago 則結果爲:Minneapolisetroit:Chicago 。@Prompt([OK]; "Categories"; @Implode(Categories; ":"))10 (IsMember) 該代理樣例檢查所選的文檔,看 Categories 列表中是否有 Adjusted,如果有,Categories 將不變化。如果沒有,Adjusted 將被添加到 Categories 列表中。FIELD Categories := @If(@IsMember("Adjusted"; Categories); Categories; @Explode(@Implode(Categories; ";") + ";Adjusted"; ";"));SELECT @All11 (@IsNotMember) 該樣例檢查所選文檔,看 Categories 列表中是否有 Adjusted 和 Signed off。如果沒有,則兩者都被加入到 Categories 列表中。如果兩者都已存在,則 Categories 維持原狀。FIELD Categories := @If(@IsNotMember("Adjusted" : "Signed off"; Categories); @Explode(@Implode(Categories; ";") + ";Adjusted;Signed off"; ";"); Categories);SELECT @All12 (@Keywords) 該樣例查找在 Cities 域中用到了哪個關鍵字。keywords := @Keywords(Cities ; "Paris" : "Moscow" : "Tokyo" : "Boston");@Prompt([OK]; "Keywords"; keywords)13 (@Member) 該樣例讓用戶從一個列表中選擇一個值,並顯示該值在列表中的編號。cars := "Sedan" : "Coupe" : "Van" : "Truck";car := @Prompt([OKCANCELLIST] : [NOSORT]; "Cars"; "Pick one"; "Sedan"; cars);n := @Member(car; cars);@Prompt([OK]; "Your selection is ..."; "Number " + @Text(n))14 (@Replace) 該樣例將 colors 列表中的“red”替換成“scarlet”並將“blue”替換成“turquoise”。colors := "red" : "blue" : "yellow" : "blue" : "black" : "red";from := "red" : "blue";to := "scarlet" : "turquoise";result := @Replace(colors; from; to);@Prompt([OKCANCELLIST] : [NoSort]; "Replacement list"; ""; ""; result)15 (@Subset) 該樣例將 New Orleans, London 和 Frankfurt 放到 first3 中,並將 Singapore 和 Sydney 放到 last2 中。cities := "New Orleans" : "London" : "Frankfurt" : "Singapore" :"Sydney";first3 := @Subset(cities; 3);last2 := @Subset(cities; -2);@Prompt([OKCANCELLIST] : [NoSort]; "First three"; ""; ""; first3);@Prompt([OKCANCELLIST] : [NoSort]; "Last two"; ""; ""; last2)16 (@Unique) 該樣例返回一個有四個元素的列表:red, blue, yellow 和 black。colors := "red" : "blue" : "yellow" : "blue" : "black" : "red";result := @Unique(colors);@Prompt([OKCANCELLIST] : [NoSort]; "Unique list"; ""; ""; result)使用條件語句@If 可以使您根據條件的真假執行不同的語句。這個條件通常是值和值的比較,但也可以是一個常量、一個變量或者一個函數的結果。例如:如果當前視圖是“By Author”,則 @ViewTitle = "By Author" 爲真。如果 Categories 至少有一個元素,@Elements(Categories) > 0 爲真。1 用在條件中時表示真。@True 和 @Yes 都返回 1。如果條件爲真,則比較運算和判斷條件的函數返回 1 。0 用在條件中時表示假。@False 和 @No 都返回 0。如果條件爲假,則比較運算和判斷條件的函數返回 0 。@If 語句有奇數個參數,必須至少有三個,例如:條件爲第一個參數,如果 @If 有多個條件的話,此後每隔一個參數就是一個條件。條件爲真時,執行的是第二個參數中的語句,如果 @If 有多個條件,則第二個參數以後的每隔一個參數都是一個可執行的語句。條件爲假時執行最後一個參數中的語句。最簡單的 @If 語句有如下的形式:@If(condition; true statement; false statement)三個條件的 @If 語句有如下形式:@If(condition1; true1; condition2; true2; condition3; true3; false)@If 函數從左到右依次計算,遇到第一個爲真的條件就執行對應的語句(也就是接下來的那個參數中的語句)。此後就不再執行任何 @If 中的語句了。如果沒有一個條件爲真,則執行最後一個參數中的語句。真值語句和假值語句的形式根據其前後關係的不同而有些變化:如果 @If 語句是公式中最後一條需要得出結果的語句,則真值和假值語句必須得出一個計算結果。如果 @If 語句是賦值語句右邊的部分,則真值和假值語句必須能得出一個可以存放在左邊的域或臨時變量中的值。否則,真值和假值語句必須產生一個操作。@If 中的真值和假值語句不能包含一個賦值語句。賦值語句左邊的部分只能出現在一個公式的最外層。以下語法形式是錯誤的:@If(condition; variable := value1; variable := value2)必須寫成:variable := @If(condition; value1; value2)@If 語句是可以嵌套的。嵌套的 @If 語句對於解決公式語言有限的邏輯結構問題是很有幫助的,但它會導致複雜的語法表達。@Do 函數可以使您在一個條件下執行多條語句。樣例:使用條件語句1. 該代理的例子將 Categories 中元素的數量與 0 比較。如果域中有元素,則不作任何改變(設置成自己的值)。如果域中沒有元素,則設置成一個常量字符串。FIELD Categories := @If(@Elements(Categories) > 0; Categories; "To be supplied ...");SELECT @All2. 此窗口標題的樣例首先檢查 @IsNewDoc 的返回值。如果文檔是新的,則窗口標題設置成文本常量“New Topic”。如果文檔已經存在,並且當前視圖是“AuthorView”的話,窗口標題設置爲“Subject”域中的內容。否則,窗口標題就是“Subject”域的內容加上一個表示答覆文檔數目的字符串。StandardTitle := Subject + @DocDescendants(" (No Responses)"; " (1 Response)"; " (% Responses)");@If(@IsNewDoc; "New Topic"; @ViewTitle = "AuthorView"; Subject; StandardTitle) 編寫消息和取得用戶輸入的方法您可以通過以下技術與用戶進行交互:使用 @Prompt 編寫消息用以下形式的 @Prompt 編寫消息,與用戶交流。@Prompt([OK]; title; prompt) 顯示一個信息對話框,標題文本在對話框的頂部,提示文本在對話框的主體部分。@Prompt([OKCANCELLIST] : [NOSORT]; title; prompt; default; choices) 將顯示一個對話框,標題文本在對話框的頂部,提示文本在對話框的主體部分,選擇文本列表在提示文本的下面。這種形式的 @Prompt 主要用於取得輸入信息,但也可以用於顯示。最後一個參數必須是一個文本列表。prompt 和 default 可以爲空。然而,如果該語句不是公式的最後一條語句,而且用戶單擊了“Cancel”的話,則接下來的公式便不再執行了。如果您想將列表排序的話就不要指定 [NOSORT] 。非文本值必須用 @Text 轉換成文本才能用作 @Prompt 的參數。文本值可以是常量、臨時變量、域或者表達式。樣例:使用 @Prompt 編寫消息1. 該樣例在對話框中編寫一個作爲標題的文本常量和一個文本表達式。表達式是文本常量和已轉換成文本的日期-時間值的組合。@Prompt([OK]; "Current time and date"; "The date is " + @Text(@Now; "D0S0") + ". " + "The time is " + @Text(@Now; "T0S1") + ".")2. 該樣例編寫一個文本常量作爲標題。而對話框的內容是一個文本常量,後面跟一個多值域中的值。@Prompt([OKCANCELLIST] : [NoSort]; "Field offices"; "Current field offices are located in the following cities:"; ""; Field_offices)使用 @Prompt 和 @PickList 取得用戶的輸入用以下形式的 @Prompt 和 @PickList 交互的取得用戶輸入:@Prompt([YesNo]; title; prompt) 顯示一個對話框,其中有標題文字、提示文本以及“是”和“否”按鈕。如果用戶單擊“是”,則 @Prompt 返回真 (1),如果用戶單擊“否”,則返回假 (0)。@Prompt([YesNoCancel]; title; prompt) 顯示一個對話框,其中有標題文字、提示文本以及“是”、“否”和“取消”按鈕。如果用戶單擊“是”,則 @Prompt 返回真 (1),如果用戶單擊“否”,則返回假 (0),如果用戶單擊“取消”,則返回 -1 。@Prompt([OkCancelEdit]; title; prompt, default) 顯示一個對話框,其中有標題文字、提示文本和一個用戶可以鍵入信息的方框。@Prompt 將以文本值的形式返回用戶的鍵入信息。如果用戶單擊“取消”,公式將立即終止。@Prompt([Password]; title; prompt) 與上面的公式作用一樣,只是在用戶鍵入時方框中顯示 X ,而不是用戶所輸入的內容,這是出於保密的考慮。@Prompt([OkCancelList] : [NoSort]; title; prompt; default; choices) 將顯示一個方框,標題文字在框的頂部,提示文本在框的主體部分,文字列表選項在提示文本的下面,並且突出顯示缺省選項。最後一個參數必須是文本列表。@Prompt 將返回用戶選擇的列表元素。如果用戶單擊了“取消”,該公式將立即終止。如果您想讓列表排序的話,請不要指定 [NoSort] 。@DbColumn 可以根據指定數據庫中的當前視圖的內容來生成一個列表。@Prompt([OkCancelCombo]; title; prompt; default; choices) 與上面的公式作用一樣,但使用的是一個下拉式列表,框中缺省項目位於列表最頂部。@Prompt([OkCancelEditCombo]; title; prompt; default; choices) 與上面的公式作用一樣,但是允許用戶在列表上的方框中輸入值或者從列表中選取一個值。@Prompt([OkCancelListMult]; title; prompt; default; choices) 與 OkCancelList 一樣,但是允許用戶選擇多個列表元素並返回一個列表。@Prompt[(LocalBrowse]; title; filetype) 顯示一個對話框,允許用戶從本地文件系統中選擇名稱。標題文本位於對話框的頂部,在對話框主體部分的左邊顯示一個選擇文件的列表框,在它下面是一個文件類型的列表框,在右邊是一個選擇目錄的列表框。對話框中包含“選擇”、“取消”和“網絡”或“幫助”按鈕。filetype 參數是一個文本值,從數字 1 到 3,指定初始化顯示的文件類型:"1" 表示 .nsf 文件,"2" 表示 .ntf 文件;"3" 表示全部文件。@PickList([Custom]:[Single]; server : file; view; title; prompt; column) 顯示一個對話框,其中包含標題文本、提示文本以及選項列表。列表中是指定數據庫的視圖。用戶可以選擇一個(如果指定了 [Single])或任意數量的元素(如果未指定 [Single])。@PickList 返回所選列表元素的指定列中的值。這有點象用 @DbColumn 來生成一個列表給 @Prompt 的過程。@PickList([Name]:[Single]) 與上面公式的作用類似,只是數據庫是一個通訊錄,而視圖是“個人”視圖。用戶可以在 @PickList 對話框中選擇通訊錄。當把非文本值用作 @Prompt 和 @PickList 的參數時,必須先通過 @Text 轉換成文本。文本值可以是常量、臨時變量、域或者表達式。如果返回值要用作非文本值的話,它還必須再加以轉換。樣例:使用 @Prompt 和 @PickList 取得用戶的輸入1 (YesNo) 這個輸入校驗公式向用戶查詢的 TotalAmount 域。如果用戶單擊“否”,則出現一個錯誤消息。@If(@Prompt([YesNo]; "Is this total within budget?"; @Text(TotalAmount; "C")); @Success; @Failure("Total not within budget"))2 (OkCancelEdit) 此按鈕公式要求用戶指定一個服務器和數據庫,並打開此數據庫。如果用戶沒有向編輯框中輸入信息而直接單擊“是”,則返回值是一個空字符串。server := @Prompt([OkCancelEdit]; "Server"; "Enter the name of a server"; "");database0 := @Prompt([OkCancelEdit]; "Database"; "Enter the name of a database on " + @If(server = ""; "your workstation"; server); "");database := @If(@Contains(database0; "."); database0; database0 + ".nsf");@Command([FileOpenDatabase]; server : database)3 (Password) 這個域輸入校驗公式從用戶那裏取得一個口令。並將此口令與文檔中“Password”域的內容相比較。pass := @Prompt([Password]; "Password"; "What is the password?");@If(pass = Password; @Success; @Failure("Password incorrect"))4 (OkCancelList) 此便捷圖標公式向用戶展示數據庫目錄中的數據庫列表,並打開用戶所選的數據庫。第一個 @DbColumn 將 Databases by _Replica ID 視圖的第 4 列的值的列表放入臨時變量 titles 中。第二個 @DbColumn 將 Databases by _Replica ID 視圖的第 2 列的值的列表放入臨時變量 servers 中。第三個 @DbColumn 將 Databases by _Replica ID 視圖的第 3 列的值的列表放入臨時變量 databases 中。臨時變量 list 將 titles,servers 和 databases 組合起來在 @Prompt 中呈現給用戶。然後,該公式將 @Prompt 的返回值分解成服務器和數據庫的名稱以用在 FileOpenDatabase 命令中。titles := @DbColumn(""; "doc":"catalog.nsf"; "Databases by _Replica ID"; 4);servers := @DbColumn(""; "doc":"catalog.nsf"; "Databases by _Replica ID"; 2);databases := @DbColumn(""; "doc":"catalog.nsf"; "Databases by _Replica ID"; 3);list := titles + " *-* " + servers + " *:* " + databases;member := @Prompt([OkCancelList]; "Open Database"; "Select a database"; ""; list);server := @Left(@Right(member; " *-* "); " *:* ");database := @Right(member; " *:* ");@Command([FileOpenDatabase]; server:database)5 (OkCancelListMult) 此按鈕公式向用戶展示了一個部門名稱及銷售總額的列表。用戶可以從列表中選擇任意數量的元素,公式計算其總和。departments := @DbColumn(""; "" : "sales.nsf"; "Main View"; 1);totalSales := @DbColumn(""; "" : "sales.nsf"; "Main View"; 2);totalsList := @Text(totalSales; "C") + " " + departments;sumList := @Prompt([OkCancelListMult]; "Total sales by department"; "Select the ones you want to sum"; ""; totalsList);sum := @Sum(@TextToNumber(sumList)); @Prompt([OK]; "Sum"; @Text(sum))6 (Custom) 此按鈕公式向用戶展示 DOC 服務器上的 CATALOG.NSF 中的 Databases by Replica ID 視圖。用戶從列表(視圖)中選擇一個元素(行),此公式將打開該行中第 3 列所指定的數據庫。name := @PickList([Custom]; "doc" : "catalog"; "Databases by Replica ID"; "Open database"; "Select a database that is on server Doc"; 3);@Command([FileOpenDatabase]; "doc" : name)使用 @DialogBox 填寫表單@DialogBox 將在一個對話框中顯示一個設計的表單,其中有“確定”和“取消”按鈕。當用戶單擊“確定”時,對話框中的某個域的內容將被傳遞到當前文檔同名的域中。@DialogBox 不傳遞 RTF 文本。在設計時要注意不能包含 RTF 文本。出現在對話框中的表單最好使用一個區域佈局來創建,而且 @DialogBox 應該使用[AutoVertFit] 和 [AutoHorzFit] 選項。樣例:使用 @DialogBox 填寫表單假如您有一個包含很多域的表單,但用戶通常在創建文檔時只填寫其中很少的幾個域。這時您可以創建另一個叫做“Dialog”的隱藏表單,在這個表單中包含一個區域佈局,其中有用戶通常填寫的域。在主表單的最上面,您可以創建一個包含下列公式的按鈕。當用戶單擊此按鈕時,此公式將使用“Dialog”表單顯示一個對話框。用戶可以在對話框中填寫域然後單擊“確定”,於是填寫的內容便被傳遞到主表單中。@DialogBox("Dialog"; [AutoVertFit] : [AutoHorzFit])取得和設置環境變量您可以從 NOTES.INI 文件中設置和提取環境變量(Windows,OS/2 和 UNIX 都適用)。@SetEnvironment(variable; value) 將一個已命名的變量設置成指定的值。您也可以用 ENVIRONMENT 關鍵字和雙參數形式的 @Environment。@Environment(variable) 提取一個已命名變量的值。環境變量的值是文本。非文本值必須在設置值之前和提取值之後轉換成文本。用戶環境變量是以 $ 字符開頭的。如果您用編輯器或者 LotusScript 添加一個環境變量,此後您還想用 @Environment 提取的話,那麼它的第一個字符必須是 $。請了確信您已經清楚了您的公式將會影響到哪個 NOTES.INI 文件。如果公式在一個服務器數據庫中,則以下幾種情況下公式是運行在服務器上的:複製公式、由“當一個新郵件到來時執行”和定時執行觸發的代理、選擇公式或者列公式。否則,公式將運行於用戶的工作站上。複本拷貝將根據其所在的服務器或工作站決定訪問不同的 NOTES.INI 文件。服務器訪問服從於管理限制(請參閱在“Notes 管理幫助”中的“限制服務器上的代理” 或者“管理員指南”)。環境變量的作用有:在不同的公式和數據庫之間傳遞臨時數據。爲一個用戶生成連續的數字。樣例:取得和設置環境變量1. 該樣例將一個數字轉換成文本並將其保存在一個環境變量中。ENVIRONMENT OrderNumber := @Text(NewOrderNumber);以下公式是等效的。@Environment("OrderNumber"; @Text(NewOrderNumber);@SetEnvironment("OrderNumber"; @Text(NewOrderNumber);2. 該樣例提取一個環境變量的值,並將其轉換成一個數字並存放在局部變量中。OldOrderNumber := @TextToNumber(@Environment("OrderNumber");3. 該樣例適用於“創建時計算”域。該公式保留有一個叫“OrderNumber”的環境變量。每當創建了一個新文檔時,此公式從環境變量中取得該值然後加一。這種計算法對於一個要進行復制的數據庫是不適用的,數據庫必須存在於單個服務器或工作站上,而且公式必須運行在相同的機器上。OldOrderNumber := @Environment("OrderNumber");NewOrderNumber := @TextToNumber(@If(OldOrderNumber = ""; "0"; OldOrderNumber)) + 1;ENVIRONMENT OrderNumber := @Text(NewOrderNumber);NewOrderNumber;4. 第一個公式被每個銷售人員運行一次。該公式提示用戶輸入銷售地區,並將其存放在一個叫“SalesArea”的環境變量中。在銷售文檔的表單中,您將第二個公式用作 SalesArea 域的缺省值公式。該公式從環境變量中取得值。這樣銷售人員便不再需要爲每個新文檔輸入銷售地區的信息了,而且也避免了在缺省值公式中硬性規定一個銷售區域。ENVIRONMENT SalesArea := @Prompt([OKCANCELLIST]; "Sales Area"; "What is your sales area?"; "Central"; "East" : "Central" : "West");@Environment("SalesArea");處理錯誤的方法錯誤有兩種類型:語法錯誤當您確認或退出正在編寫的公式時可能會出現語法錯誤的提示。您將接到一條指定錯誤的消息,有錯誤的行被突出顯示出來。必須查出錯誤並改正它。通常,語法錯誤包括:函數名稱或關鍵字拼寫錯誤缺少括號或括號多餘字符串常量兩邊缺引號語句之間沒有分號您最好在寫公式時隨時檢查。多重嵌套可能會使公式的語法非常複雜。運行錯誤運行錯誤在公式運行的時候發生。這種錯誤可分爲以下幾類:無法預料的錯誤 — 這是在開發時出現的錯誤,您的用戶是看不見的。例如,如果遺漏了函數的某個參數,則在運行時將出現以下消息:“函數的參數不夠”。應該測試公式儘量修正所有無法預料的錯誤。不予彙報的錯誤 — 這些是錯誤的結果,但是並不當作錯誤彙報。例如,如果試圖用 @Prompt 來顯示一個數字值,@Prompt 可以運行,但顯示爲空白。您的用戶永遠也看不見這些錯誤。應該測試公式,確保所有結果都是正確的。可以預料的錯誤 — 這些錯誤可能是用戶在運行公式時造成的。例如,在提示輸入一個數據庫的名稱時,用戶輸入了一個並不存在的數據庫名稱。無法阻止這些錯誤的發生但可以預計得到,或者可以有意測試一下,然後給出適當的解決辦法。以下函數可以幫助您處理運行錯誤:@IsError(value),當它發現一個域、臨時變量或者表達式中包含錯誤時就返回 1 。@Error 生成一個錯誤。@Failure(message),在輸入校驗公式中用來顯示消息。@Success 總是返回 1。@Return(value) 終止公式的運行並返回一個值。當一個域內嵌的校驗檢查失敗時,Notes 將產生一個錯誤。例如,如果將一個域指定爲數字型的,而用戶輸入的是一個非數字型的值,Notes 將把該域的值設置爲錯誤。您也可以設置一個域值爲 @Error 來生成錯誤。Notes 在用戶試圖保存文檔時彙報域中的錯誤。例如,如果一個數字域包含一個非數字的值,那麼當用戶試圖保存文檔時,Notes 將產生一條消息“不能將文本轉換爲數字”。爲了在錯誤發生時改變消息或執行另一個操作,請在域的校驗公式中使用 @IsError 來檢查域中的錯誤。可以用 @Failure 生成您自己的消息,但僅僅只是在域校驗公式中可以這樣做。爲了在一個域中使用您自己的出錯條件,請在域轉換公式中測試域的值,並在檢測出一個錯誤條件時返回一個 @Error。除了域公式以外,例如在代理、按鈕或者熱點中,可以檢查域的內容並對錯誤條件立即作出反應。例如,如果您用一個按鈕來檢查域,就可以在用戶保存文檔之前修改域值或者報告錯誤。在檢查錯誤時,值得注意的是,內嵌的校驗機制在用戶輸入值時馬上就可以彙報錯誤,而使用 @Error 的轉換公式直到用戶保存文檔時才報告錯誤。樣例:運行錯誤1.如果 Price 域中有錯誤的話,這個校驗公式將使該文檔保存失敗,並顯示一條指定的錯誤信息。@If(@IsError(Price); @Failure("The Price field must be numeric"); @Success)2. 此樣例包含輸入轉換和校驗公式。如果 Price 域的值大於 14.99 的話,輸入轉換公式將在 Price 域中放置一個錯誤。如果發現此錯誤,輸入校驗公式它就會使文檔的保存操作失敗,並顯示一條指定的錯誤信息。REM "Input translation formula for Price field";@If(Price > 14.99; @ERROR; Price)REM "Input validation formula for Price field";@If(@IsError(Price); @Failure("The Price field must be numeric and 14.99 or less"); @Success)3. 此按鈕公式在對 Price 打折扣之前先檢查它是否有錯誤。如果該域有錯誤,則該公式返回一個錯誤信息。FIELD Price := @If(!@IsError(Price) & @IsNumber(Price) & Price < 15; Price * 0.85; @Return(@Prompt([OK]; "Error in price field"; "Must be numeric and less than 15.00"; "")));@All4. 該按鈕公式檢測 Price 域中是否有錯誤。如果該域含有錯誤,則此公式將該域設置成一個通過 @Prompt 從用戶那裏得到的值。FIELD Price := @If(!@IsError(Price) & @IsNumber(Price) & Price < 15; Price; @TextToNumber(@Prompt([OKCANCELEDIT]; "Error in price field"; "Enter a number under $15.00"; "")));@All使用函數所有函數都能計算出一個值,並且可以放在公式中任何允許此類型值的地方。當公式執行的時候,公式的值代替了公式的位置。有些公式也有附加效果。例如,@Prompt 會產生一個消息框。大多數函數可以用於任意 Notes 對象的公式中,但有一些函數卻被限制在適當的範圍內。以下表格列舉了受限的函數,並列舉了它們可以用在哪些對象中。此外,您必須進入相應的上下文中才能使函數返回有關當前數據庫、視圖、文檔或者域的信息,也就是說,那些對象必須是當前的。受限函數 函數只應用於這些 Notes 對象@All 複製公式、代理、視圖選擇公式@AllChildren 複製公式、視圖選擇公式@AllDescendants 複製公式、視圖選擇公式@Command 便捷圖標公式、手動代理、按鈕、操作熱點@DbColumn (Notes 數據庫) 便捷圖標公式、操作、按鈕、熱點、域設計、代理(除郵件以外)@DbLookup (Notes 數據庫) 便捷圖標公式、操作、按鈕、熱點、域設計、代理(除郵件以外)@DeleteDocument 代理@DeleteField 代理@DocChildren 列公式、窗口標題公式@DocDescendants 列公式、窗口標題公式@DocLevel 列公式、窗口標題公式@DocMark 代理@DocNumber 列公式、窗口標題公式@DocParentNumber 列公式、窗口標題公式@DocSiblings 列公式、窗口標題公式@Failure 域校驗公式ENVIRONMENT 除彈出式熱點公式以外的所有場合@Environment 除了正在編寫的彈出式熱點公式以外的場合FIELD 便捷圖標公式、代理、按鈕、操作熱點、域設計@IsCategory 列公式@IsDocBeingLoaded 表單設計、域設計@IsDocBeingMailed 按鈕、熱點、域設計@IsDocBeingRecalculated 按鈕、熱點、域設計@IsDocBeingSaved 按鈕、熱點、域設計@IsExpandable 列公式@IsNewDoc 便捷圖標公式、按鈕、窗口標題公式、表單設計、域設計@MailSend 便捷圖標公式、代理、按鈕、操作熱點@PickList 便捷圖標公式、手動執行的代理、按鈕、操作熱點、域設計@Platform 便捷圖標公式、手動執行的代理、按鈕、熱點、除選擇公式和列公式以外的視圖設計、表單設計、域設計@Prompt 便捷圖標公式、手動執行的代理、按鈕、操作熱點、域設計@Responses 窗口標題公式、域設計@Return 便捷圖標公式、代理、按鈕、熱點、域設計SELECT 複製公式、代理、視圖選擇公式@SetDocField 便捷圖標公式、代理、按鈕、操作熱點、域設計@SetEnvironment 除了彈出式熱點公式以外的所有場合@SetField 便捷圖標公式、代理、按鈕、操作熱點、域設計@Success 校驗公式@Unavailable 代理@ViewTitle 代理使用命令命令就是一些可以用戶界面中執行即時操作的特殊函數。大多數命令是模仿與菜單命令的。例如以下公式,如果從按鈕執行,就是將當前文檔置於編輯模式並將插入點下移兩次:@Command([EditDocument]; "1");@Command([EditDown]; "2")命令的語法表示如下:@Command([command-name]; arg1; arg2; ... argn)@PostedCommand([command-name]; arg1; arg2; ... argn)函數名稱是 @Command 或者 @PostedCommand。第一個參數是用方括號括起來的命令名稱。在幫助導航器中選擇“Scripts & formulas”,然後選擇“Notes 公式語言命令 A-Z”即可得到一個命令的列表,或者請參閱“程序員指南”的第八章。其他則是命令所帶的參數。您不能在一個不與用戶交互的公式中使用命令,如定時代理、域公式或一個後臺宏。您不能在 Web 應用程序中使用大多數的命令,因爲它們是基於 Notes 工作站用戶界面的。在 Web 應用程序中只能夠使用以下命令(在各個命令的描述中分別註明了它的限制):[CalendarFormat]、[CalendarGoTo]、[Compose]、[EditClear]、[EditDocument]、[EditInsertFileAttachment]、[FileCloseWindow]、[FileOpenDatabase]、[OpenDocument]、[FileSave]、[NavigateNext]、[NaviagtePrev]、[NavigateNextMain]、[NavigatePrevMain]、[OpenNavigator]、[OpenView]、[ToolsRunMacro]、[ViewChange]、 [ViewExpandAll]、ViewCollapseAll] 和 [ViewShowSearchBar]、[ViewRefreshFields] 和 [FileOpenDBRepID]。@Command 函數按順序和其他函數一起執行,但有一些例外。例如,以下公式就是先執行命令:@Command([EditDocument]; "1");@Prompt([OK]; "Edit mode"; "The document is now in edit mode.")@PostedCommand 函數將在所有其他函數執行完畢後才按順序執行。這是爲了模仿 Notes R3 中的 @Command。例如,以下公式將在最後才執行命令:@PostedCommand([EditDocument]; "1");@Prompt([OK]; "Edit mode"; "The document will go into edit mode.")您可以檢查 @Command 的返回值(但 @PostedCommand 不行),並對其作出響應。如果命令執行正確返回值爲 @True ,否則返回值爲 @False 。以下便捷圖標的公式樣例在命令 FileOpenDatabase 執行失敗時返回。@If(@Command([FileOpenDatabase]; "NEWSUBJ"); ""; @Return(""));@Command([Compose]; ""; "Main Topic");@Command([EditGotoField]; "Subject");@Command([EditInsertText]; "New subject");@Command([EditGotoField]; "Body")執行字符串操作的方法公式語言函數支持數據類型轉換、字符串長度、字符串比較、子串、大小寫和修剪等操作。您可以:轉換數據類型在對數據操作時類型必須是正確的。以下的函數用來轉換數據和測試數據類型。函數 描述@Text(value) 將一個值轉換爲文本字符串。@Text(value; format) 根據指定的格式將一個數字或時間-日期值轉換成文本字符串。@TextToNumber(string) 將文本字符串轉換成一個數字。@TextToTime(string) 將文本字符串轉換成一個日期-時間值。@IsText(value) 如果值是文本字符串或文本字符串列表,則返回真值 (1) 。@IsNumber(value) 如果值是數字或數字列表,則返回真值 (1) 。@IsTime(value) 如果一個值是時間-日期或時間-日期列表,則返回真值 (1)。@Char(number) 將一個 IBM 代碼頁 850 代碼轉換爲對應的字符。樣例:轉換數據類型1 (@TextToNumber, @Text)。該樣例使用 @Prompt 交互的讀取一個數字,計算其對數,並用 @Prompt 交互的顯示答案。由於 @Prompt 只能處理文本值,所以輸入的值 i 在進行對數計算之前必須轉換成數字,答案 n 必須在顯示之前必須轉換成文本字符串。i := @Prompt([OKCANCELEDIT]; "@Log Test"; "Enter a number"; "");n := @Log(@TextToNumber(i));@If(@IsError(n); @Return(@Prompt([OK]; "@Log Test"; i + " is not a number")); ""); @Prompt([OK]; "@Log Test"; "The logarithm of " + i + " is " + @Text(n))2 (@Text)。該樣例根據日期-時間格式 T1S1 將 @Now 返回的日期-時間值轉換成文本。T1 僅指時間,S1 僅指小時和分鐘。在晚上六點時,用戶可以看到一個信息框,其中的文字以“The time is ...”開頭,後面是“06:00 PM”。@Prompt([OK]; "The time is ..."; @Text(@Now; "T1S1"))3 (@Text)。該樣例根據數字格式 C,2 將數字 800 轉換成文本並予以顯示。C 表示貨幣格式(以美元符開頭),2 表示保留兩位小數。用戶看到的信息框中的文字以“800 dollars”打頭,後面是“$800.00”。@Prompt([OK]; "800 dollars"; @Text(800; "C,2"))4 (@Text, @TextToTime)。此樣例將文本字符串“Today”轉換成當天的日期,然後將此日期轉換成文本供 @Prompt 使用。例如,如果今天是 1995 年 7 月 8 日,用戶將看到一個信息框,其中的文字以“Today's Date”開頭,後面跟着“07/08/95”。@Prompt([OK]; "Today's Date"; @Text(@TextToTime("Today")))5 (@IsNumber)。此樣例將域 A 和 B 相加。如果某一個域不是數字型的話,它將被轉換成數值 0。因爲用戶無法在一個數字域中輸入非數字的值,所以如果一個數字域是空的,並且沒有缺省值公式的話,它的缺省值就是一個空的文本字符串。此公式中的 @IsNumber 函數就避免了這個情況。@If(@IsNumber(A); A; 0) + @If(@IsNumber(B); B; 0)6 (@Char)。此樣例將整數 65 轉換成大寫字符 A。@Prompt([OK]; "IBM Code Page 850 code 65"; @Char(65))連接、比較和判定長度+ 運算符用來連接字符串。=、<>、!=、=!、><、<、>、<= 和 >= 運算符用來比較字符串。以下的函數用來判定字符串的長度和比較字符串:函數 描述@Length (string) 返回字符串的長度,以字符爲單位。@Length(stringlist) 返回字符串列表中每個元素的長度,以字符爲單位。@Matches (string; pattern) 判定兩個字符串是否匹配。可以用通配符來擴展比較的範圍。@Like (string; pattern) 判定兩個字符串是否匹配。遵循 ANSI SQL 標準。@Like(string; pattern; esc) 與上面的一樣只是多了一個轉義字符。@Matches 用 ? 來匹配任意一個單獨的字符,用 * 來匹配任意的字符序列,此序列中也可以包括其他的通配符。@Like 使用 _(下劃線)來匹配任意一個單獨的字符,用 %(百分號)來匹配任意的字符序列,符合 ANSI X3.135-1992 標準。@Matches 使用 作爲轉義字符。樣例:連接、比較和判定長度1 (+)。該樣例連接兩個字符串以形成 ABCDEF。@Prompt([OK]; "Concatenation"; "ABC" + "DEF")2 (+)。該樣例連接兩個輸入的字符串。Input1 := @Prompt([OKCANCELEDIT]; "Concatenation - first element"; "Enter any text in the box"; "ABC");Input2 := @Prompt([OKCANCELEDIT]; "Concatenation - second element"; "Enter any text in the box"; "DEF"); @Prompt([OK]; "Concatenation - result"; Input1 + Input2)3 (=)。如果兩個輸入字符串相等,該樣例爲 YesNo 返回 True,如果不等的話則爲 YesNo 返回 False。Input1 := @Prompt([OKCANCELEDIT]; "Comparison - first element"; "Enter any text in the box"; "ABC");Input2 := @Prompt([OKCANCELEDIT]; "Comparison - second element"; "Enter any text in the box"; "DEF");YesNO := @If(Input1 = Input2; "The strings are equal"; "The strings are not equal"); @Prompt([OK]; "Comparison - result"; YesNo)4 (@Length)。該樣例顯示 9,即字符串 abcdefghi 的長度。@Prompt([OK]; "Length of abcdefghi"; @Text(@Length("abcdefghi")))5 (@Length)。該樣例創建一個數字列表。該列表中的每個元素包含 TextList 中相應元素的長度。@Length(TextList)6 (@Matches)。如果輸入 abc,則該樣例在 YesNo 中返回 True。Input := @Prompt([OKCANCELLIST]; "@Matches Input"; "Choose one"; "abc"; "abc" : "bcd" : "cde" : "xyz" : "123");YesNo := @If(@Matches(Input; "abc"); " matches abc"; " does not match abc"); @Prompt([OK]; "@Matches Result"; Input + YesNo)7 (@Matches). 該樣例爲 YesNo 返回 True,如果輸入的每個字符都是字母的話,也就是說,從 a 到 z 的範圍內。集合 {a-z} 指定字母的範圍,前面的 + 表示任意多個字母。Input := @Prompt([OKCANCELLIST]; "@Matches Input"; "Choose one"; "abc"; "abc" : "bcd" : "cde" : "xyz" : "123");YesNo := @If(@Matches(Input; "+{a-z}"); " matches +{a-z}"; " does not match +{a-z}"); @Prompt([OK]; "@Matches Result"; Input + YesNo)8 (@Matches)。如果每個輸入的字符都不是字母,也就是說,在集合 {a-z} 之外,則該樣例爲 YesNo 返回 True。{!a-z} 表示不在集合 a 到 z 中。前面的 + 表示任意多個字母。Input := @Prompt([OKCANCELLIST]; "@Matches Input"; "Choose one"; "abc"; "abc" : "bcd" : "cde" : "xyz" : "123");YesNo := @If(@Matches(Input; "+{!a-z}"); " matches +{!a-z}"; " does not match +{!a-z}"); @Prompt([OK]; "@Matches Result"; Input + YesNo)9 (@Matches)。如果輸入包含由任意數目字符包圍的連續的 bc 字符,則該樣例爲 YesNo 返回 True。Input := @Prompt([OKCANCELLIST]; "@Matches Input"; "Choose one"; "abc"; "abc" : "bcd" : "cde" : "xyz" : "123");YesNo := @If(@Matches(Input; "*bc*"); " matches*bc*"; " does not match *bc*"); @Prompt([OK]; "@Matches Result"; Input + YesNo)10 (@Matches)。如果輸入是以 a 開始並且有三個字符長,或者輸入以 1 開始並且有三個字符長,則該樣例爲 YesNo 返回 True。Input := @Prompt([OKCANCELLIST]; "@Matches Input"; "Choose one"; "abc"; "abc" : "bcd" : "cde" : "xyz" : "123");YesNo := @If(@Matches(Input; "a??|1??"); " matches a??|1??"; " does not match a??|1??"); @Prompt([OK]; "@Matches Result"; Input + YesNo)11 (@Like)。該代理檢查每個文檔中 textBody 域內的兩個字符串集合。第一個字符串是順序包含“acquisition”和“Acme”的任何文本。第二個字符串是順序包含“Acme”和“51%”的任何文本。第二個 @Like 語句使用斜槓 (/) 作爲轉義字符,因而可以指定百分號 (%)。不要使用反斜槓 () 作爲轉義字符。@If(@Like(textBody; "%acquisition%Acme%"); @Prompt([OK]; "Found reference to "acquisition""; Subject); "");@If(@Like(textBody; "%Acme%51/%%"; "/"); @Prompt([OK]; "Found reference to "51%""; Subject); "");SELECT @All查找並提取子串以下函數查找並提取子串:函數 描述@Contains(string; sub) 判定一個字符串是否包含一個子串。@Contains(string; list) 判定一個字符串是否包含一個列表中的子串。@Begins(string; sub) 判定一個字符串是否以一個子串開始。@Ends(string; sub) 判定一個字符串是否以一個子串結束。@Left(string; n) 從一個字符串中提取最左邊的 n 個字符。@Left(string; sub) 從一個字符串中提取最左邊的字符,直到一個子串爲止,從左到右搜索。@LeftBack(string; n) 從一個字符串中提取最左邊的字符,直到從右邊開始的第 n 個字符爲止。@LeftBack(string; sub) 從一個字符串中提取最左邊的字符,直到一個子串爲止,從右到左搜索。@Right(string; n) 從一個字符串中提取最右邊的 n 個字符。@Right(string; sub) 從一個字符串中提取最右邊的字符,直到一個子串爲止,從左到右搜索@RightBack(string; n) 從一個字符串中提取最右邊的字符,直到從右邊開始的第 n 個字符爲止。@RightBack(string; sub) 從一個字符串中提取最右邊的字符,直到一個子串爲止,從右到左搜索。@Middle(string; off; n) 從一個字符串中提取 n 個字符,從一個偏移量開始,從左到右搜索。@Middle(string; sub; n) 從一個字符串中提取 n 個字符,從一個子串開始,從左到右搜索。@Middle(string; off; sub) 從一個字符串中提取字符,從一個偏移量開始,到一個子串結束,從左到右搜索。@Middle(string; sub; sub) 從一個字符串中提取字符,從一個子串開始,到另一個子串結束,從左到右搜索。@MiddleBack(str; off; n) 從一個字符串中提取 n 個字符,從一個偏移量開始,從右到左搜索。@MiddleBack(str; sub; n) 從一個字符串中提取 n 個字符,從一個子串開始,從右到左搜索。@MiddleBack(str; off; sub) 從一個字符串中提取字符,從一個偏移量開始,到一個子串結束,從右到左搜索。@MiddleBack(str; sub; sub) 從一個字符串中提取字符,從一個子串開始,到另一個子串結束,從右到左搜索。@ReplaceSubstring(source; from; to) 在 source 中用 from 的內容替換 to 的內容。如果 from 和 to 都是列表,按次序替換對應的項目。@Word(string; sep; n) 從 string 提取單詞 n,其中單詞是在指定的分隔符之間的文本。@Word(list; sep; n) 從列表中的每個字符串中提取單詞 n,其中單詞是在指定的分隔符之間的文本。樣例:查找並提取子串1 (@Contains)。如果 Substring 在 String 中的某個地方出現,則該樣例爲 R 返回 True。該搜索是區分大小寫的。String := @Prompt([OKCANCELEDIT]; "String"; "Enter a string"; "");Substring := @Prompt([OKCANCELEDIT]; "Substring"; "Enter a beginning substring"; "");Yes := Substring + " is in " + String;No := Substring + " is not in " + String;R := @Contains(String; Substring);@If(R; @Prompt([OK]; "Yes"; Yes); @Prompt([OK]; "No"; No))2 (@Contains)。如果 Substring1 或 Substring2 在 String 的某個地方出現,則該樣例爲 R 返回 True。該搜索是區分大小寫的。String := @Prompt([OKCANCELEDIT]; "String"; "Enter a string"; "");Substring1 := @Prompt([OKCANCELEDIT]; "Substring"; "Enter substring 1"; "");Substring2 := @Prompt([OKCANCELEDIT]; "Substring"; "Enter substring 2"; "");Yes := Substring1 + " or " + Substring2 + " is in " + String;No := Substring1 + " and " + Substring2 + " are not in " + String;R := @Contains(String; Substring1 : Substring2);@If(R; @Prompt([OK]; "Yes"; Yes); @Prompt([OK]; "No"; No))3 (@Left)。該樣例爲 R 返回 String 中最左邊的 N 個字符。String := @Prompt([OKCANCELEDIT]; "String"; "Enter a string"; "");Number := @Prompt([OKCANCELEDIT]; "Number of characters"; "Enter a number of characters"; "");N := @TextToNumber(Number);R := @Left(String; N); @Prompt([OK]; "Leftmost characters"; R)4 (@Left)。該樣例爲 R 返回 String 中的 Substring 左邊的字符。String := @Prompt([OKCANCELEDIT]; "String"; "Enter a string"; "");Substring := @Prompt([OKCANCELEDIT]; "Substring"; "Enter a substring"; "");R := @Left(String; Substring); @Prompt([OK]; "Characters left of " + Substring; R)5 (@RightBack, @Left)。如果在 ComposedBy 域中的公共名是“Judith Woo”,本公式計算出“Woo, Judith”。@RightBack 返回姓,@Left 返回名。@RightBack(@Name([CN]; ComposedBy); " ") + ", " + @Left(@Name([CN]; ComposedBy); " ")6 (@Middle)。該樣例爲 R 返回 String 中從 Substring 以後開始的 N 個字符。String := @Prompt([OKCANCELEDIT]; "String"; "Enter a string"; "");Substring := @Prompt([OKCANCELEDIT]; "Substring"; "Enter a substring"; "");Number := @Prompt([OKCANCELEDIT]; "Number of Characters"; "Enter the number of characters"; "");N := @TextToNumber(Number);R := @Middle(String; Substring; N); @Prompt([OK]; Number + " characters starting after " + Substring; R)7 (@ReplaceSubstring)。此代理樣例對所選文檔的 textBody 域作了三個替換。第三個替換是爲了避免句子結尾連續出現兩個句號。FIELD textBody := @ReplaceSubstring(textBody; "Acme" : "mousetrap" : ".." ; "Acme, Inc." : "mouse detention device" : ".");SELECT @All8 (@Word)。該樣例從字符串 s 中提取單詞 n ,用空格作爲單詞分隔符。s := @Prompt([OKCANCELEDIT]; "String"; "Enter a string of words"; "");n := @Prompt([OKCANCELEDIT]; "Word"; "Enter the number of the word to extract"; "");ss := @Word(s; " "; @TextToNumber(n)); @Prompt([OK]; "Substring"; "Word " + n + " is "" + ss + """)修剪、重複、添加新行,並改變大小寫以下函數修剪字符串、重複字符、添加新行(回車),並改變大小寫:函數 描述@Trim(string) 從字符串中刪除開頭、結尾和多餘的空格。@Trim(list) 從字符串列表的每個元素中刪除開頭、結尾和多餘的空格,並從列表中刪除空白元素。@Repeat(string, number) 將字符串 string 重複 number 次。@NewLine 在字符串中插入一個新行(回車)。@LowerCase(string) 將字符串中所有的大寫字符轉換成小寫。@UpperCase(string) 將字符串中所有的小寫字符轉換成大寫。@ProperCase 將字符串中每個單詞的第一個字符轉換成大寫,並將其餘的字符轉換爲小寫。樣例:修剪、重複、添加新行,並改變大小寫1 (@Trim)。該樣例返回 [Now is the time],刪除全部多餘的空格。Untrimmed := " Now is the time ";Trimmed := @Trim(Untrimmed);@Prompt([OK]; "Untrimmed"; "[" + Untrimmed + "]");@Prompt([OK]; "Trimmed"; "[" + Trimmed + "]")2 (@Trim, @ProperCase)。該樣例將 Name 中的單詞轉換成首字母大寫的單詞,並刪除開頭、結尾和多餘的空格。如果爲 Name 輸入“ jane j smith”,該公式將它轉換爲“Jane J Smith”。@Trim(@ProperCase(Name))3 (@Repeat)。如果 Sales 域大於或等於 100,000,則本樣例在 Comments 域中返回“Great Month! Great Month! Great Month!”FIELD Comments := @If(Sales >= 100000; @Repeat("Great Month! "; 3); Sales >= 50000; "Good Month"; "I want to see you in my office");SELECT @All4 (@NewLine)。本樣例返回由一個新行分隔開的用戶名和日期。@UserName + @NewLine + @Text(@Now)5 (@LowerCase)。本樣例返回小寫的用戶名。@LowerCase(@UserName)6 (@UpperCase)。本樣例返回大寫的用戶名。@UpperCase(@UserName)執行算術運算乘、除、加、減運算符 (* / + -)。乘法和除法運算符的優先級高於加法和減法;運算的順序是從左到右。以下列出的是一些算術運算函數。函數 描述@Abs(number) 計算一個數的絕對值。@Sign (number) 對於正數返回 1,對於負數則返回 -1,對於零則返回 0。@Sum(num; num; ...) 計算數字和數字列表的和。@Integer(number) 去掉數字的小數部分。@Integer(numberlist) 去掉數字列表元素的小數部分。@Round(number) 對一個數字進行四捨五入。@Round(number; factor) 以一個指定的因子規整數字。@Round(numberlist) 將列表中的每個數字都進行四捨五入。@Round(numlist; factor) 以一個指定的因子規整數字列表中的每個元素。@Max(number; number) 取兩個數中最大的一個。@Max(numlist; numlist) 用矩陣式的列表操作計算最大值。@Min(number; number) 取得兩個數中最小的一個。@Min(numlist; numlist) 用矩陣式的列表操作計算最小值。@Modulo(number; number) 計算第一個數被第二個數除之後得出的餘數。@Modulo(numlist; numlist) 用矩陣式列表操作計算餘數。@Power(base; exp) 指數運算。@Sqrt (number) 計算平方根。@Pi 圓周率值。@Log(number) 計算常用對數。@Ln(number) 計算自然對數。@Exp(number) 計算以 e 爲底的指數。@Random 返回一個 0 到 1 之間的隨機數。@Sin(angle) 計算角度的正弦(弧度)。@Cos(angle) 計算角度的餘弦(弧度)。@Tan(angle) 計算角度的正切(弧度)@Asin(sine) 反正弦函數。@Acos(cosine) 反餘弦函數@Atan(tangent) 反正切函數@Atan2(x; y) y/x 正切值的反正切函數樣例:執行算術運算1 (*, 優先級)。對於第一個 @Prompt,該例樣打印 15,因爲先執行乘法 4 * 3。對於第二個 @Prompt 該樣例打印 21,因爲括號強制先運算 3 + 4。@Prompt([OK]; "3 + 4 * 3"; @Text(3 + 4 * 3)); @Prompt([OK]; "(3 + 4) * 3"; @Text((3 + 4) * 3))2 (/ *)。該樣例對於第一個 @Prompt 打印 0.333333333333333,先執行除法再將結果四捨五入精確到小數點後 15 位。對於第二個 @Prompt,該樣例打印 1.2635268885E+17,顯示結果的 11 位小數作爲乘以 1017 的係數。@Prompt([OK]; "1 / 3"; @Text(1 / 3)); @Prompt([OK]; "123456789 * 1023456789"; @Text(123456789 * 1023456789))3 (@Abs)。該樣例計算 Score1 與 Score2 之差的絕對值。@Abs(Score1 - Score2)4 (@Abs)。該樣例計算 Sales 和 CostOfSales 之差的絕對值,在文本域中將它格式化,並用括號括在負數結果兩邊。GP := @Abs(Sales - CostOfSales); @If(Sales >= CostOfSales; @Text(GP); "(" + @Text(GP) + ")")5 (@Sign)。該代理樣例顯示 Total 域。如果域值是負數,則在括號中放置的是它的絕對值;如果域值是0,則顯示“Zero”。sign := @Sign(Total);display := @If(sign = 1; @Text(Total); sign = -1; "(" + @Text(@Abs(Total)) + ")"; "Zero");@Prompt([OK]; "Total"; display);SELECT @All6 (@Sum)。該樣例打印 15,列表 One23、變量 Four 和常量 5 的總和。One23 := 1 : 2 : 3; Four := 4;S := @Sum(One23; Four; 5); @Prompt([OK]; "Sum of 1-5"; @Text(S))7 (@Integer)。該樣例將 3.12 截爲 3 而將 6.735 截爲 6。@Prompt([OK]; "@Integer(3.12)"; @Text(@Integer(3.12))); @Prompt([OK]; "@Integer(6.735)"; @Text(@Integer(6.735)))8 (@Integer)。該樣例在列表中將 Sales 和 Commission 截爲整數。@Integer(Sales : Commission)9 (@Round)。該樣例將 3.12 四捨五入爲 3,將 6.735 取爲 7,7.5 取爲 8;753 以 10 爲因子歸整爲 750; 列表元素中的 3.12、 6.735 和 7.5 分別歸整爲 3、 6 和 7(把它們轉換爲文本字符串以顯示)。@Prompt([OK]; "@Round(3.12)"; @Text(@Round(3.12))); @Prompt([OK]; "@Round(6.735)"; @Text(@Round(6.735))); @Prompt([OK]; "@Round(7.5)"; @Text(@Round(7.5))); @Prompt([OK]; "@Round(753; 10)"; @Text(@Round(753; 10))); @Prompt([OK]; "@Round(3.12 : 6.735 : 7.5)"; @Implode(@Text(@Round(3.12 : 6.735 : 7.5))))10 (@Max)。該樣例打印 3,即 1 和 3 中的最大值,第二個樣例打印 99 6 7 8,即分別是兩個列表中平行元素的最大值。@Prompt([OK]; "@Max(1; 3)"; @Text(@Max(1; 3))); @Prompt([OK]; "@Max(99 : 2 : 3; 5 : 6 : 7 : 8)"; @Implode(@Text(@Max(99 : 2 : 3; 5 : 6 : 7 : 8))))11 (@Min)。該樣例打印 1,即 1 和 3 中的最小值,第二個樣例打印 5 2 3 3,即分別是兩個列表中平行元素的最小值。@Prompt([OK]; "@Min(1; 3)"; @Text(@Min(1; 3))); @Prompt([OK]; "@Min(99 : 2 : 3; 5 : 6 : 7 : 8)"; @Implode(@Text(@Min(99 : 2 : 3; 5 : 6 : 7 : 8))))12 (@Modulo)。該樣例打印 4/3 的餘數 1;-14/3 的餘數 -2,(當被除數是負數時,餘數是負數);還有 1 2 3 3,這分別是第一個列表中的被除數除以對應的第二個列表中的除數的餘數。@Prompt([OK]; "@Modulo(4; 3)"; @Text(@Modulo(4; 3))); @Prompt([OK]; "@Modulo(-14; 3)"; @Text(@Modulo(-14; 3))); @Prompt([OK]; "@Modulo(4 : 6 : 8 : 9; 3 : 4 : 5 : 6)"; @Implode(@Text(@Modulo(4 : 6 : 8 : 9; 3 : 4 : 5 : 6))))13 (@Modulo)。該樣例確定輸入的數字是奇數還是偶數(被 2 除其餘數爲 0)。n := @TextToNumber(@Prompt([OKCANCELEDIT]; "Input Number"; "Type a number"; "")); @Prompt([OK]; "The number is ..."; @If(@Modulo(n; 2) = 0; "Even"; "Odd"))14 (@Power)。該樣例打印 2 的 3 次冪即 8,和 -2 的 3 次冪即 -8,和 2 的 -3次冪即 0.125。@Prompt([OK]; "@Power(2; 3)"; @Text(@Power(2; 3))); @Prompt([OK]; "@Power(-2; 3)"; @Text(@Power(-2; 3))); @Prompt([OK]; "@Power(2; -3)"; @Text(@Power(2; -3)))15 (@Sqrt, @Power)。該樣例是用於一個計算域的值公式,計算矩形的斜邊,該矩形的邊在 Length 和 Width 域中指定。@If(Length = "" | Width = ""; ""; @Sqrt(@Power(Length; 2) + @Power(Width; 2)))16 (@Pi, @Power)。該樣例是用於一個計算域的值公式,計算一個圓形的面積,該圓形的半徑在 Radius 域中指定。@If(Radius = ""; ""; @Pi * @Power(Radius; 2))17 (@Log)。該樣例打印 0.602059991327962 和 14,它們分別是 4 和 1014 的常用對數。@Prompt([OK]; "Common log of 4"; @Text(@Log(4))); @Prompt([OK]; "Common log of 1.0E+14"; @Text(@Log(1.0E+14)))18 (@Ln)。該樣例打印 0.693147180559945,即 2 的自然對數。@Prompt([OK]; "Natural log of 2"; @Text(@Ln(2)))19 (@Exp)。該樣例計算出第一個 @Exp 函數值爲 2.71828182845904 (e 的值),第二個 @Exp 函數值爲 3.49034295746184 (e 的 1.25 次冪),第三個 @Exp 函數值爲 0.28650479686019 (e 的 -1.25 次冪)。@Prompt([OK]; "e to 1"; @Text(@Exp(1))); @Prompt([OK]; "e to 1.25"; @Text(@Exp(1.25))); @Prompt([OK]; "e to -1.25"; @Text(@Exp(-1.25)))20 (@Random)。
該視圖操作樣例從用戶那裏取得一個數字,並將它和 1 到 99 之間的隨機數比較,包含 1 和 99 。userNumber := @Prompt([OKCANCELEDIT]; "Number"; "Must be 1-99"; "");winningNumber := @Text(@Integer(98 * @Random + 1));@Prompt([OK]; "Result"; @If(userNumber = winningNumber; "YOU WIN"; "Sorry - winning number is " + winningNumber))21 (@Sin, @Cos)。該樣例顯示兩個計算域的公式。第一個公式計算矩形的長,第二個公式計算矩形的寬。Diagonal * @Sin(Angle * @Pi / 180)Diagonal * @Cos(Angle * @Pi / 180)執行時間/日期運算時間-日期值包含年、月、日、小時、分鐘和秒。您可以象在時間-日期域中那樣使用一個時間-日期值,但是必須用 @Text 把它們轉換爲字符串。您可以用 @TextToTime 將一個字符串轉換成時間-日期值。時間-日期常量可以是日期、時間或者兩者的結合,它們被括在方括號中。日期的格式是年、月、日(年份可選。缺省爲當前年;兩位數的年如果年數大於或等於 50 表示是在 20 世紀,如果年數小於 50 表示是在 21 世紀),由斜槓 (/) 或連字符 (-)(對於 OS/2)分開。時間的格式是小時、分鐘、秒(可選。缺省爲 0),由冒號分開。您可以使用 24 小時的時間形式或用“PM”表示下午時間。您可以增加時區以指示一個時區。將這些部分用空格分開。以下是幾個時間/日期常量的例子:[6/30/97]、[5:30:00 PM]、[17:30:00]、[17:30 EST]、[6/30 5:30 PM]。日期可以進行比較或做減法。減法操作的結果是以秒爲單位的數字。以下的函數用來確定並操作時間-日期值。函數 描述@Created 返回文檔創建的時間-日期。@Accessed 返回最後一次訪問文檔的時間-日期。@Modified 返回最後一次編輯並保存文檔的時間-日期。@Now 返回當前的時間-日期。@Today 返回當天的日期。@Tomorrow 返回明天的日期。@Yesterday 返回昨天的日期。@Weekday(time-date) 返回星期幾如 1-7(星期日到星期六)。@Day(time-date) 從時間-日期中提取月曆中的日期。@Month(time-date) 從時間-日期中提取月份值,從 1 到12。@Year(time-date) 從時間-日期中提取年值。@Hour(time-date) 從時間-日期中提取小時值。@Minute(time-date) 從時間-日期中提取分鐘值。@Second(time-date) 從時間-日期中提取秒值。@Date(y; m; d) 返回年,月,日中的日期部分。@Date(y; m; d; h; m; s) 返回年,月,日,小時,分鐘,秒中的日期部分。@Date(time-date) 返回時間-日期中的日期部分。@Time(y; m; d) 返回年,月,日中的時間部分。@Time(y; m; d; h; m; s) 返回年,月,日,小時,分鐘,秒中的時間部分。@Time(time-date) 返回時間-日期的時間部分。@Adjust(time-date; y; m; d; h; m; s) 通過加減某一數值以調整時間-日期。@Zone 返回當前計算機的時區設置。@Zone 返回當前時間-日期的時區設置。樣例:執行時間-日期運算1 (@Created)。如果當前文檔是在 1995 年以前創建,則該樣例將“Archive”寫入 Status 域,否則寫入“Current”。SELECT @All;FIELD Status := @If(@Created < [01/01/95 12:00:00 AM]; "Archive"; "Current");2 (@Modified, @Date, @Today, @Yesterday)。根據當前文檔最後一次修改的日期,該代理樣例將“Today”,“Yesterday”,或“Old”寫入到 ViewStatus 域中。FIELD ViewStatus := @If(@Date(@Modified) = @Today; "Today"; @Date(@Modified) = @Yesterday; "Yesterday"; "Old");SELECT @All3 (@Modified, @Date, @Weekday, @Today, @Adjust, @Yesterday)。該樣例在上例的基礎上做些修改,在指定“Yesterday”時要跳過星期六。如果今天是星期一,則 y 被設置爲今天的日期再減去 3 天;否則設置爲昨天的日期。用 y 代替 @Yesterday 用於測試 @Modified date。d := @Date(@Modified);y := @If(@Weekday(@Today) = 2; @Adjust(@Today; 0; 0; -3; 0; 0; 0); @Yesterday);FIELD ViewStatus := @If(d = @Today; "Today"; d = y; "Yesterday"; "Old");SELECT @All4 (@Now, @Month, @Year, @Day)。該計算文本域的樣例在 letterhead 表單的開頭顯示當天的日期。例如,6/30/95 顯示爲“June 30, 1995”。months := "January" : "February" : "March" : "April" : "May" : "June" : "July" : "August" : "September" : "October" : "November" : "December";month := @Subset(@Subset(months; @Month(@Now)); -1);year := @Year(@Now);day := @Day (@Now);month + " " + @Text(day) + ", " + @Text(year)5 (@Adjust, @Weekday, @Created)。這個計算時間域的樣例顯示距文檔創建日期兩天的日期。如果創建日期是星期五,則該樣例增加 4 天以跳過週末。increment := @If(@Weekday(@Created) = 6; 4; 2);@Date(@Adjust(@Created; 0; 0; increment; 0; 0; 0))訪問用戶環境用戶環境是包含公式的數據庫所在的服務器或工作站,公式包括以下情況: 複製公式、由新郵件到達時或定時觸發的代理、選擇公式或列公式。否則,用戶環境是用戶運行公式的 Notes 工作站。用戶名可以是專有名稱也可以是非專有名稱,專有名稱可以是規範或縮寫的,使用 @Name 以改變用戶名的格式。以下是在用戶環境中返回或處理信息的函數。函數 描述@UserName 返回用戶名或服務器名.@Name([key]; name) 改變用戶名的結構。關鍵字包含 [CN] 以從一個專有名字中解析出公共名,[Abbreviate] 縮寫規範格式的專有名字,[Canonicalize] 與上述作用相反,[ToKeyword] 將名字各部分按相反順序排序,用反斜槓分開(用於分類視圖)。@UserRoles 對於服務器上的數據庫,返回當前用戶的角色列表。@MailDbName 返回用戶郵件數據庫的服務器名和路徑名。該函數判定兩個元素的列表。@OptimizeMailAddress(address) 從地址中刪除無用的網絡域。@Platform 返回用戶當前運行的平臺:Macintosh、NetWare、OS2V1、OS2V2、UNIX、Windows/16 或 Windows/32。@Version 返回正在運行的 Notes 版本(字符串)。@Password(string) 對一個字符串編碼。您無法從編碼結果中確定原始字符串。樣例:訪問用戶環境1. 該視圖選擇公式限制視圖中只能有這樣一些文檔,這些文檔的 From_1 域與當前用戶名相匹配。From_1 和 @UserName 都被縮簡至層次名稱的公共名部分,以更好地確保匹配。SELECT @Name([CN]; @UserName) = @Name([CN]; From_1)2. 該列公式中,@Name 函數從“From”域中提取公共名部分。Subject + " (" + @Name([CN]; From) + @DocDescendants(")"; ", % response)"; ", % responses)")3. 該公式顯示有關用戶環境的信息。@MailDbName 的返回值被組合,因爲這是一個包含服務器名和路徑名的二元素列表。@Prompt([OK]; "User name"; @Name([CN]; @UserName));@Prompt([OK]; "Mail database"; @Implode(@MailDbName));@Prompt([OK]; "Platform"; @Platform);@Prompt([OK]; "Notes version"; @Version)4. 這是“By Author”視圖中第一列的公式。它轉換 From 域,該域包含了一個典型的專有名字,將其轉換爲姓、逗號、名的格式。AuthorName := @If(!@IsAvailable(From);"Anonymous";@Name([CN]; From));Name := @Trim(@Word(AuthorName; "("; 1));LastName := @RightBack(Name; " ");FirstName := @LeftBack(Name; " ");CombinedName := LastName + ", " + FirstName;@If(CombinedName = ", "; Name; CombinedName)5. 這是一個對於某表單的“Password”域的輸入校驗公式。作者可在口令被鍵入的時候看到口令,但是文檔被保存後,口令被編碼而且不可讀。@Password(Password)訪問當前數據庫和視圖您對運行公式的數據庫有直接的訪問權(便捷圖標公式除外,它沒有數據庫環境)。如果您在視圖的上下文中,則您對運行公式的視圖有直接的訪問權。在文檔的上下文中,您對文檔所在視圖有直接的訪問權。數據庫和視圖屬性下表列出返回數據庫和視圖屬性的函數。函數 描述@DbManager 返回當前對數據庫有“管理者”權限的用戶、羣組和服務器。 返回一個列表。@DbName 返回當前 Notes 服務器和數據庫的名字。返回二元素列表。@ViewTitle 返回當前視圖的標題。窗口標題和列公式函數許多函數提供了有關視圖的答覆層次和其他方面的信息。文檔在視圖中以 1, 2, 3 編號,這是對主文檔而言。每組答覆文檔或答覆的答覆文檔則有第二個和第三個層次的編號(從 1 開始)。缺省的情況下,完整的答覆文檔的編號以小數形式出現。例如,第三個主文檔的第二個答覆文檔編號爲 3.2,而它下面的第一個答覆文檔編號爲 3.2.1。這些函數僅工作於窗口標題和列公式中,有一些會被限制。返回值都是一個字符串。函數 描述@Responses 返回在當前視圖中當前文檔的答覆編號。只限於窗口標題公式。@DocLevel 返回在當前視圖中當前文檔的級別。@DocSiblings 返回與當前文檔同級的文檔編號,包含當前文檔。@DocNumber 返回在當前視圖中的當前文檔或分類的編號。@@DocNumber(sep) 與上相同,只是用 sep 分隔編號,替換了句點。@DocNumber("") 與上相同,只是僅返回編號的最右邊部分。@DocParentNumber 返回在當前視圖中當前文檔或分類的父文檔或父分類的編號。@@DocParentNumber(sep) 與上相同,只是用 sep 分隔編號,替換了句點。@DocParentNumber("") 與上相同,只是僅返回編號的最右邊部分。@DocDescendants 返回後續文檔的編號,包含當前文檔的子文檔,子文檔的子文檔。@DocDescendants(def) 與上相同,只是返回 def。在 def 中使用 % 以表示編號。@DocDescendants(zero; def) 與上相同,只是如果沒有後續文檔的話則返回 zero。@DocDescendants(one, zero; def) 與上相同,只是如果有一個後續文檔的話則返回 one 。@DocChildren 返回當前文檔的直接子文檔的編號。@DocChildren(def) 與上相同,只是返回 def。在 def 中使用 % 以表示編號。@DocChildren(zero; def) 與上相同,只是如果沒有後續文檔的話則返回 zero。@DocChildren(one, zero; def) 與上相同,只是如果有一個後續文檔的話則返回 one 。@IsCategory 如果當前行的當前域右邊任何域是一個分類的話,則返回一個星號。@IsCategory(true) 與上相同,只是返回 true 代替星號。@IsCategory(true; false) 與上相同,只是如果沒有域是分類的話則返回 false 。@IsExpandable 如果當前行是可展開的話則返回一個加號。@IsExpandable(true) 與上相同,只是返回 true 代替加號。@IsExpandable(true; false) 與上相同,只是如果當前行是不可展開的話則返回 false 。樣例:訪問當前數據庫和視圖1. 該樣例顯示數據庫標題、它的服務器和數據庫名和對它具有“管理者”權限的用戶名。@Prompt([OK]; "Title"; @DbTitle);@Prompt([OK]; "Server and database"; @Trim(@Implode(@DbName)));@Prompt([OK]; "Managers"; @Implode(@DbManager; ", "))2. 如果視圖標題公式爲新文檔顯示“New Title”。如果視圖標題爲“AuthorView”則顯示 Subject 域;否則顯示 Subject 域加上答覆文檔的數目。StandardTitle := Subject + @DocDescendants(" (No Responses)"; " (1 Response)"; " (% Responses)");@If(@IsNewDoc; "New Topic"; @ViewTitle = "AuthorView"; Subject; StandardTitle)3. 該列公式顯示 Subject 域、用戶名和答覆文檔的數目。Subject + " (" + @Name([CN]; From) + @DocDescendants(")"; ", % response)"; ", % responses)")在公式語言中訪問當前文檔對於表單操作、按鈕、熱點和域公式,當前文檔被是打開的那個。對於視圖操作,當前文檔是突出顯示的那個(不是複選的文檔)。對於代理,當前文檔是根據代理構造器選擇以及 SELECT 關鍵字標準激活的那個文檔。要閱讀當前文檔中的域,命名該域。命名不區分大小寫,但是名字必須準確。要編寫當前文檔中的域,您必須使用 FIELD 關鍵字或者 @SetField 函數。不能簡單的命名該域。關鍵字 FIELD 用於賦值語句並有以下格式。如果省略關鍵字 FIELD,則指定的變量將被認爲是臨時變量。FIELD field-name := expression@SetField 寫入域,它與使用關鍵字 FIELD 的賦值語句效果相同。@SetField 可以嵌套到另一個語句;對於關鍵字 FIELD 則不能這樣做。域名被表達成一個文本值,所以它可以是一個括號中的準確名字。有一個限制是 @SetField 只工作於已存在的域中;如果文檔中不存在您想寫入的域,則可使用 FIELD 賦值語句在公式開頭“聲明”它。@SetField 有以下格式。@SetField( field-expression-name; expression )DEFAULT 關鍵字是爲了處理當一個域不在文檔中的情況。如果文檔中存在此域,那麼就用它的值,如果沒有,則用 DEFAULT 值。DEFAULT field-name := expression@MailSend 函數郵寄文檔。不帶參數的 @MailSend 郵寄當前文檔,它必須包含一個域名爲“SendTo”,該域包含收件人。帶有參數的 @MailSend 構造文檔並按指定參數郵寄。@MailSend@MailSend( to; cc; bcc; subject; body; fields; flags )@DeleteField 函數刪除域。在 FIELD 賦值語句中指定它作爲表達式。FIELD field-name := @DeleteField@DocMark([NoUpdate]) 函數防止文檔中公式的改變被保存。在公式處理完以後的文檔與以前是一樣的。該函數隻影響代理。該表格列出返回文檔和域屬性的函數。函數        描述
@DocumentUniqueID        返回文檔唯一的標識符,這是文檔的全部複本唯一的標識符;在一個域中,創建一個當前文檔的文檔鏈接。
@InheritedDocumentUniqueID        返回文檔的父文檔唯一的標識符,在一個域中,創建一個當前文檔的文檔鏈接。
@NoteID        返回“NT”和跟在後面的文檔的項目標識符。
@DocLength        返回文檔的字節數大小。
@Author        返回全部作者的縮寫姓名。
@DocFields        返回文檔中全部域的名稱。
@IsAvailable(field)        如果某域存在於文檔中,則返回真 (1)。
@IsUnavailable(field)        如果某域不存在於文檔中,則返回真 (1)。
@Attachments        返回附件的個數。
@AttachmentNames        返回全部附件的文件名。
@AttachmentLengths        返回每個附件的字節數大小。
@Responses        返回在當前視圖中當前文檔的答覆數目。
@AllChildren        選擇匹配文檔的直接答覆;只用於選擇公式中。
@AllDescendants        選擇匹配文檔的所有答覆;只用於選擇公式中。
@IsResponseDoc        如果文檔是一個答覆則返回真 (1)。
@IsNewDoc        如果文檔未被保存過則返回真 (1)。
@IsDocBeingEdited        如果文檔處於編輯模式則返回真 (1)。
@IsDocBeingLoaded        如果文檔正在被加載則返回真 (1)。
@IsDocBeingSaved        如果文檔正在被保存則返回真 (1)。
@IsDocBeingMailed        如果文檔正在被郵寄則返回真 (1)。
@IsDocBeingRecalculated        如果文檔正在被重新計算則返回真 (1)。
樣例:訪問當前文檔1. 該計算域公式執行涉及文檔中另外兩個域的數學計算。這些域必須存在於文檔中,必須是數字型的且被初始化爲數字值。TotalSales - CostOfSales2. 該代理樣例在當前文檔中的兩個域上執行數學運算,並將結果指定給第三個域。這兩個被引用的域必須存在;GrossSales 域可以是新的。FIELD GrossSales := TotalSales - CostOfSales;SELECT @All3. 該代理公式在當前文檔中的兩個域上執行數學運算,並將一個數值放到第三個域中或者發送一個郵件信息。第一個語句初始化 GrossSales,如果您能肯定該域已經存在則無須此初始化操作。FIELD GrossSales := 0;gs := TotalSales - CostOfSales;@If(gs > 0; @SetField("GrossSales"; gs); @MailSend("Ian Perron"; ""; ""; "No gross sales"; "Gross sales are zero or less for "; Subject));SELECT @All4. 該列公式樣例判定文檔是否包含 KeyThought 域。如果文檔不包含一個 KeyThought 域,則它的缺省值爲 Topic。DEFAULT KeyThought := Topic;KeyThought5. 這是另一種實現上例的方法。@If(@IsAvailable(KeyThought); KeyThought; Topic)6. 該代理樣例刪除 GrossSales 域。@If (@IsUnavailable(GrossSales); @Return(""); "");FIELD GrossSales := @DeleteField;SELECT @All7. 該代理樣例計算 GrossSales 域,然後顯示結果,而且不標記文檔爲更新。作爲結果,保存的文檔未發生任何變化。如果忽略了 @DocMark 或者指定了“@DocMark([Update])”則變化被保存。FIELD GrossSales := TotalSales - CostOfSales;@Prompt([OK]; "Gross sales for " + Subject; @Text(GrossSales));@DocMark([NoUpdate]);SELECT @All8. 該樣例顯示當前文檔中的全部域。@Prompt([OKCANCELLIST]; "Fields"; "Fields in document"; ""; @DocFields);SELECT @All9. 該窗口標題公式爲一個新文檔顯示“New Document”。對於一個現有的文檔,該公式顯示 Subject 域和答覆的個數。@If(@IsNewDoc; "New Document"; Subject + " with " + @Text(@Responses) + " response(s)")10. 該視圖選擇公式選擇全部文檔,除了那些 Form 域包含“Profile”或“Log”的文檔。SELECT !@Contains(Form; "Profile" : "Log")11. 該視圖選擇公式選擇所有 Subject 域包含“acme”(不區分大小寫)的文檔和它們的子文檔。SELECT @Contains(@LowerCase(Subject); "acme") | @AllDescendants12. 該表單操作公式顯示所有文檔附件的名稱和長度,或者如果文檔沒有附件的話,則顯示“No attachments”。@If(@Attachments > 0; @Prompt([OKCANCELLIST]; "Attachments"; "Attachment names and lengths"; ""; @AttachmentNames + " (" + @Text(@AttachmentLengths) + " bytes)"); @Prompt([OK]; "Attachments"; "No attachments"))訪問在當前文檔和數據庫以外的數據以下函數從指定的數據庫中取得數據值。您不能用這些函數設置數值。@DbLookup 在指定數據庫的指定視圖中的第一個排序列中查找指定的值。對於每個匹配搜索值的文檔,@DbLookup 返回文檔或視圖中的列的指定域中的值。@DbColumn 返回指定數據庫的指定視圖中的指定列中的全部值。前三個參數對於每個函數是相同的:[NOTES] : [NOCACHE] 指定操作是在 Notes 數據庫上並且未使用緩存。因爲 [NOTES] 是缺省的,所以您可以爲第一個列表元素指定空串 ""。如果數據是穩定的或者您訪問過數據庫許多次了,則可以指定第二個列表元素爲空串 "",不使用緩存。您可以爲整個參數使用一個空串 "" 表示打開一個 Notes 數據庫而且沒有緩存。server : database 指定您訪問的服務器和數據庫。爲第一個列表元素指定空串 "" 以表示本地 Notes 目錄。指定整個參數爲空串 "" 以表示當前數據庫。您可以指定整個參數爲數據庫的複本標識符。Notes 將在本地和服務器上搜索,並且使用第一個它找到的複本。從“文件”“數據庫”“設計摘要”“複製”中取得複本標識符。view 指定通過哪個視圖訪問數據庫。對於 @DbLookup,第四個參數是關鍵字,它是在視圖中第一個排序列中找到的值。@DbLookup 查找每一個與該關鍵字匹配的文檔。對於 @DbLookup,第五個參數或者是數據庫中的域名,或者是視圖中的列號。@DbLookup 返回找到文檔中的域或列值的列表。對於 @DbColumn,第四個參數是列號。@DbColumn 返回列中全部值的列表。以下函數在當前數據庫中取得並設置另一個文檔的域值。不過,您必須知道文檔的唯一的標識符。@GetDocField(unid; fieldName) 給定唯一標識符,取得域值。@SetDocField(unid; fieldName; value) 給定唯一標識符,設置域值。由於父文檔的唯一標識符在子文檔的 $Ref 域中,所以該函數適用於在答覆文檔的父文檔中訪問並設置域值。在設置了“公式繼承選定文檔中的數值”的文檔中,可以在基文檔的一個隱藏域的公式中使用 @InheritedDocumentUniqueID,然後在繼承文檔的一個隱藏域的公式中使用上述隱藏域的名稱。否則,您必須設計一種保存並提取您想訪問文檔的標識符的方法。樣例:訪問當前文檔和數據庫以外的數據1. 該樣例在本地通訊錄 (NAMES.NSF) 的“個人”視圖中查找一個人的姓名,並從包含此姓名的文檔中取得辦公室的電話號碼。inputName := @Prompt([OKCANCELEDIT]; "User name"; "Enter user name as FIRST LAST"; "");adjName := @Right(inputName; " ") + ", " + @Left(inputName; " ");phoneNumber := @DbLookup("Notes" : "NoCache"; "" : "NAMES"; "People"; adjName; "OfficePhoneNumber");@Prompt([OK]; "Office phone number"; inputName + "'s office phone is " + phoneNumber)2. 該樣例除了有兩點不同以外,與上面的例子一樣。在這裏使用的是通訊錄數據庫的複本標識符而不是其名稱。Notes 先在本地搜索複本然後上服務器搜索,並確定使用第一個發現的複本。@DbLookup 的最後一個參數是列 2,而不是 OfficePhoneNumber。實際上它與列 2 是一回事,因爲列 2 中就包含電話號碼。inputName := @Prompt([OKCANCELEDIT]; "User name"; "Enter user name as FIRST LAST"; "");adjName := @Right(inputName; " ") + ", " + @Left(inputName; " ");phoneNumber := @DbLookup("Notes" : "NoCache"; "85255AD6:006AE971"; "People"; adjName; 2);@Prompt([OK]; "Office phone number"; inputName + "s office phone is " + phoneNumber)3. 該樣例在本地通訊錄的“羣組”視圖中查找一個羣組的成員。groupName := @Prompt([OKCANCELEDIT]; "Group name"; "Enter group name"; "");members := @DbLookup("Notes" : "NoCache"; "" : "NAMES"; "Groups"; groupName; "Members");@Prompt([OKCANCELLIST]; "Group members"; "Members of " + groupName; ""; members)4. 該樣例在給出辦公室電話號碼的情況下,取得與該號碼有關的人員的姓名。設計這個例子是爲了在號碼與人員一一對應的情況下使用的。由於數據庫沒有按電話號碼排序的視圖,所以此樣例使用 @DbColumn 來獲得所有電話號碼(列 2)和所有人員(列 1),然後查找與號碼對應的人員。phone := @Prompt([OKCANCELEDIT]; "Phone number"; "Enter phone number"; "");phoneList := @DbColumn("Notes" : "NoCache"; "" : "NAMES"; "People"; 2);nameList := @DbColumn("Notes" : "NoCache"; "" : "NAMES"; "People"; 1);position := @Member(phone; phoneList);@If(position = 0; @Do(@Prompt([OK]; "Not listed"; "No listing for " + phone); @Return(" " )); "");name := @Subset(@Subset(nameList; position); -1);nameAdj := @Right(name; " ") + " " + @Left(name; ",");@Prompt([OK]; "Phone number " + phone; nameAdj)使用函數通過 ODBC 訪問外部數據庫以下函數通過 ODBC 訪問外部數據庫並返回一個值或值的列表:@DbColumn 返回表的一列中的全部值,或者全部不同的值。@DbLookup 返回表的一列中通過關鍵字匹配選定的值。@DbCommand 將一個命令傳遞給外部 DBMS 並返回結果。@DbColumn 與 @DbLookup 都只能提取數據。它們不能增加、刪除、修改數據或執行其他操作。@DbCommand 能提取數據或發送其他可以改變數據的 SQL 語句。LotusScript 提供了一種更廣泛的能力,包括更新外部數據庫的能力。前四個參數對於三個函數是同樣的,通過 ODBC 建立訪問。這些參數是:"ODBC" 是字符串常量;或者 "ODBC" : "NoCache"數據源的名稱,定義在數據源表格中(在 Windows 中的 ODBC.INI)用戶標識符,兩個用戶標識符列表,或者一個空串,依外部數據源而定口令,兩個口令的列表,或者一個空串,依外部數據源而定(@DbColumn 和 @DbLookup)要訪問的表名稱(@DbCommand) 要執行的命令字符串(@DbColumn 和 @DbLookup)要訪問的列名稱處理由數據源返回的空數據的選項(@DbLookup) 包含關鍵字的列名(@DbLookup) 適當數據類型的關鍵字值,或者是一個列表(@DbColumn 和 @DbLookup)兩個元素的列表:“Distinct”作爲關鍵字或空串;“Ascending”或“Descending”作爲一個關鍵字在需要用戶標識符和口令的地方,您可以指定空串並讓用戶在執行函數時提供它們。樣例:使用函數通過 ODBC 訪問外部數據庫1. 該公式取得 MANUALS 表中的 PARTNO 列。@DbColumn("ODBC";"Oracle";"";"";"MANUALS";"PARTNO";"":"Ascending")2. 該公式從 MANUALS 表的行中取得 TITLE,在該行中 PARTNO 是 17-895A 。@DbLookup("ODBC";"Oracle";"";"";"MANUALS";"TITLE";"PARTNO";"17-895A")3. 該公式從 MANUALS 表中 ONHAND 列的數字值小於100 的每行取得 PARTNO 列值。@DbCommand("ODBC";"Oracle";"";"";"SELECT PARTNO FROM MANUALS WHERE ONHAND <100")
版權所有2001
首頁-->LOTUS文章-->強迫WEB用戶重新登錄的方法(兩種)
我們知道在Web應用中,一旦我們曾經輸入過一次用戶口令,那麼,系統將會一直使用當前Web用戶與Domino HTTP服務器連接。如果我們希望以另一名Web用戶訪問此服務器,只好關閉瀏覽器,再重新連接服務器時,重新輸入其他用戶的名程和口令。(這是我們不願意作的。)如何不關閉瀏覽器,強迫瀏覽器顯示登陸窗口呢?關於如何強迫一個Web用戶輸入登錄口令的方法,在此列出兩個:1。Java Servlet程序2. Domino URL 命令這兩種方法都是強迫瀏覽器顯示登陸窗口,以使用戶可以其他用戶名登陸。實際上不能註銷當前已連接Web用戶,除非在登陸窗口輸入錯誤的用戶名和口令或者不同於當前已連接的Web用戶的正確的用戶名和口令。註釋:這段程序有一段邏輯錯誤,本人已經對其更正這段程序可以使用Domino URL命令代替,功能完全相同。在R5中試驗可行,4.6估計可行。比如:http://host/anydatabase.nsf?login注意這裏一定要寫一個數據庫的名字,可以是任何一個數據庫,甚至是不存在的數據庫。請注意格式。你可以試試,有結果您可以寫信給我。-------丁香書 1999.8.13=====================================問題5:怎麼使一個Web用戶註銷登錄?來自:http://dingxiang.163.net更新:1999.8.14解答:How do you add a logoff button for web users?Using the username:[email protected] URL does not work because the browser thinks your realm is "username:[email protected]" instead of "www.company.com".<P>You can use a Java servlet to pass a 401 exception to the browser to log someone off of TestRealm (in most cases, this is "www.company.com"): <P>// From Terry Courtneyimport java.io.*;import javax.servlet.*;import javax.servlet.http.*;public class LogOff extends HttpServlet {  public void init(ServletConfig config)  throws ServletException  {    super.init(config) ;  }  public void doGet (HttpServletRequest req, HttpServletResponse res)  throws ServletException, IOException  {    String auth ;    // get output streem    ServletOutputStream out = res.getOutputStream() ;    // get authorization from header    auth = req.getHeader("Authorization") ;//    if (auth == null) { //It's a logic Error,rem by dingxiang    if (auth != null) {      // force prompt of login      res.setContentType("text/html");      res.setHeader("WWW-Authenticate", "WWW-Authenticate: basic realm=\"/TestRealm\"") ;      res.setStatus(401, "401 Unauthorized") ;    }    out.println("Hi") ;  } // end doGet} // end class LogOffWhen you call this servlet w/ a URL of http://www.company.com/LogOff, it will send the right HTTP headers back to the browser to trick the browser into thinking that the user did not authenticate with this Realm.<P>This servlet can also be written as a LotusScript agent.  
版權所有2001
首頁-->LOTUS文章-->自動切換用戶ID
  Sub Initialize%REM 切換用戶ID本程序的作用是:1、從指定的目錄中搜索所有ID文件,2、然後提供用戶選擇3、再從註冊用戶時保存在names.nsf數據庫中的密碼進行校對看是否相同。4、再通過用戶選擇的ID文件更換操作員ID本程序有以下缺陷:1、取得特殊指定目錄下的ID文件2、無法判斷獲得的ID文件是用戶ID,還是Server.id,cart.id3、用戶密碼需要保存在names.nsf中,首先進行密碼覈對,造成安全泄露。但不這樣做,無法截獲用戶輸入密碼錯誤,程序不好處理。4、因此此公式僅適合單機用戶。tndahttp://notes.363.net%END REMREM 首先搜索指定目錄下的所有ID文件Dim ss As New notessessionxx = ss.UserNameListIDPath = ss.GetEnvironmentString("Directory",True)IDFileAll = IDPath+"\*.id"'沒有方法遍歷所有目錄,所以假定所有ID文件在此目錄下fileName = Dir(IDFileAll, 0)num = 0Do While fileName <> ""num = num + 1fileName = Dir()LoopIf num = 0 Then Exit Sub '沒有找到ID文件就退出程序Redim ids(1 To num) num = 1fileName = Dir(IDFileAll, 0)Do While fileName <> ""ids(num) = Left(filename,Instr(1,filename,".")-1)num = num + 1fileName = Dir()LoopDim uiw As New notesuiworkspaceIDuser = uiw.Prompt( PROMPT_OKCANCELLIST,"更換操作員","請選擇一個操作員:","",ids)If IDuser = "" Then Exit SubREM 從names.nsf中獲取密碼 Dim ndb As notesdatabaseSet ndb = ss.getdatabase("","names.nsf")Dim nvi As notesviewSet nvi = ndb.getview("People")Dim pdoc As notesdocumentSet pdoc = nvi.getdocumentbykey(IDuser)pass = pdoc.comment(0)For i = 1 To 3IDpass = uiw.Prompt( PROMPT_PASSWORD,"輸入密碼","請輸入您的密碼:")If pass = IDpass Then Exit For NextIf pass <> IDpass Then Exit SubDim idfile As Stringidfile = IDPath+"\"+IDuser+".id"Dim newreg As New NotesRegistration Call newreg.SwitchToID( idfile,pass )Messagebox "當前操作員是:"+IDuser,64,"更換成功"Exit SubEnd Sub  
版權所有2001
首頁-->LOTUS文章-->RTF域全接觸
   RTF域完全掌握 1、RTF域是Notes中最重要的域,由於它能夠保存文本、聲音、圖片、動畫、附件以及按鈕操作、鏈接等多媒體信息資料,是Notes不同於普通關係型數據庫的重要特徵。2、RTF域的存儲容量僅受機器硬盤限制,可以任意大的文件和程序。3、當存儲各種類型的RTF域,改變域類型成爲文本類型時,僅其中的文本字符能夠保存,其他的圖片、附件等不能保存在文本類型域中。4、RTF域在編程中,是不能通過公式函數來計算處理的,只能通過LotusScript來對其進行復制操作。5、以下是用LotusScript複製、添加RTF域內容,經測試無誤。Sub Click(Source As Button)%REM RTF域複製操作作者:tnda 2000.3.5http://notes.363.net mail:[email protected]域值在程序中編輯修改後,只能調用doc.save(false,true)不能調用uidoc.save,也不能在文檔中單擊保存按鈕,否則後臺修改無效。並且其修改的內容當前不能顯示,只有不保存退出文檔,再打開才能顯示。因爲RTF域只能通過後臺LotusScript修改。%END REM Dim uiw As New notesuiworkspaceDim uidoc As notesuidocumentDim doc As notesdocumentSet uidoc = uiw.currentdocumentSet doc = uidoc.document '獲得當前文檔Dim rtitem1 As NotesRichTextItemSet rtitem1 = doc.GetFirstItem( "aaaa" )If rtitem1 Is Nothing Then Exit SubIf rtitem1.Type <> RICHTEXT Then Exit Sub'文檔沒有保存以前,無法發現RTF域Call rtitem1.AppendText( "這是第一個域值內容" ) Dim rtitem2 As NotesRichTextItemSet rtitem2 = rtitem1.CopyItemToDocument( doc,"bbbb")Call rtitem2.AppendText( "這是第二個域新內容" ) Call doc.Save( False, True )End Sub
版權所有2001
首頁-->LOTUS文章-->域公式
  域公式本節主要介紹域在何處需要使用公式,具體公式編程,下章介紹。可以使用域公式的事件有:域選擇公式、域隱含公式、域初始值和計算公式、域校驗公式、域刷新公式、域事件公式等。域選擇公式:在選擇域類型爲對話框列表、複選框、單選框、列表框、組合框時,需要輸入域可以選擇的選項。選擇項:對於固定不變的選擇項,如:性別、學歷等,可以手動輸入。對於可能會變化,或者說無法確定的選擇項目,如:畢業學校、所學專業等,需要使用公式獲得。手動輸入的方法爲:在選擇項目輸入框內,輸入男|1女|2“|”前面的“男”,爲顯示內容,即用戶可以看見的,“|”後面的“1”,爲實際內容,即當用戶選擇了“男”時,實際上此域保存的內容是“1”。因此,此域在表單中顯示爲“男”,但在視圖中顯示爲實際值“1”,如果希望顯示和保存的內容一致,則放棄使用“|”,即可,如:男女注意:“1”是文本字符,不是數字類型,利用選擇項輸入的域類型一律是文本類型。一行爲一個選擇項目,如果選擇項內容需要空值,直接回車,在一行中不要輸入任何內容即可。公式選擇項的方法爲:1、從視圖讀取:需要使用公式:@DbColumn,此公式的作用是從任何服務器上的數據庫中,讀取指定的視圖中的指定的列。@DbColumn( class : "NoCache" ; server : database ; view ; columnNumber )·        class:輸入空值,或"Notes" ·        "NoCache":不從緩衝區讀取 ·        server:指定的服務器,本地服務器,可以使用空值"" ·        database:指定的數據庫名稱,如果找不到則報錯,如果是當前數據庫則爲空值 ·        view:指定的視圖,可以爲隱含視圖, ·        columnNumber:指定視圖中的第n列,可以是隱含列,從視圖的左數第N個列,包括隱含列。 ·        注意:如果視圖的第N列有重複內容,則選擇項目中也會有重複內容供選擇,需要第N列排序分類即可。 如:@DbColumn("";"";"aaaa";1),讀取當前數據庫的aaaa視圖的第1列值。2、從其他文檔讀取:可以從其他文檔讀取一個多值域,作爲選擇項目,如可以將公司的部門輸入指定配置屬性文檔中,供選擇。使用公式@DbLookup,此公式的作爲是從指定的文檔中讀取一個域值內容。@DbLookup( class : "NoCache" ; server : database ; view ; key ; fieldName )·        key:根據此值,從視圖中的第一列選擇指定的文檔,如果key是多值列表,如:"男":"團員",則視圖第一列性別必須排序分類,第二列政治面貌必須排序,依此類推。 ·        filedName:指定文檔中的域名稱,函數將返回此域的值。如果輸入數字N,則表示讀取視圖中指定文檔的第N列值,建議使用域名稱。 ·        注意:如果沒有找到文檔,系統將定位爲此視圖的第一個文檔,如果視圖中沒有文檔,則出錯。 如:@DbLookup("";"" ;"aaaa"; "abc" ; "City" ),返回從當前數據庫中aaaa視圖,根據aaa值定位的文檔的City域值。返回內容必須是多值域,如果是單值域,則僅有一個選項。使用視圖對話框的方法:選擇項目可以使用視圖來選擇,可以使用函數:@PickList,其作用是顯示一個視圖對話框,可以從中選擇一個或幾個文檔,並返回指定的域值。@PickList( [Custom] : [Single] ; server : file ; view ; title ; prompt ; column ; categoryname )·        [Custom]用戶自定義選項 ·        [Single]:選擇此項表示返回單值,否則可以返回多值 ·        title:對話框標題 ·        prompt:對話框顯示提示 ·        column:返回第N列域值 ·        categoryname:5.0新增功能,表示視圖僅顯示此參數指定的分類文檔。 ·        此函數功能比較多,具體請參閱幫助數據庫 使用地址對話框的方法:顯示names.nsf的人員視圖供選擇使用存取權限框的方法:顯示當前數據庫存取權限指定的人員供選擇如果選擇了域屬性“可以使用不在列表中的數值”,則可以從選擇項目中選擇的同時,可以輸入新建內容。域隱含公式:域隱含公式必須返回@True或@False,來根據邏輯對或錯判斷域是否隱含。如:aaa = "",表示域aaa的值爲空時隱含域初始值和計算公式:根據公式返回一個指定的值,返回的值類型必須和域類型一致,否則出錯。公式位置爲:Default Value如:文檔創建時間域初始公式可以爲,@New,表示返回當前工作站時間域校驗公式:判斷域值輸入是否正確,僅編輯類型可以使用。公式位置爲:Input Validation如:數量域值大於0,小於100,其公式爲@If(ShuLian > 0 & ShuLiang < 100 ; @Success ; @Failure("數量輸入範圍是0 ~100"))·        @Success:返回正確,表示此域內容符合要求。 ·        @Failure:返回錯誤,表示此域內容不符合要求,並顯示提示內容,且輸入光標會自動進入此域輸入框中。。 域刷新公式:當表單刷新時,會根據此公式返回的值改變域值內容,僅編輯類型可以使用。公式位置爲:Input Translation如:如果在省份輸入的內容是“廣東”則自動將其內容轉化爲“廣東省”@If(@Right(ShengFen;1) = "省" ; ShengFen ; ShengFen + "省" )此公式判斷ShengFan域內容,最後一個字符是否是“省”,如果不是,則加入,否則返回原值。域事件公式:根據域觸發的事件運行一段程序,事件有:·        Entering:進入編輯域,即此域獲得輸入焦點,激活此事件,一般可以設置動態初始值。 ·        Exiting:退出編輯域,即此域失去輸入焦點,激活此事件,一般可以校驗域,或根據域內容改變其他域內容。 ·        Initialize:域調入內存時,激活此事件 ·        Terminite:域從內存中退出時,激活此事件  
版權所有2001
首頁-->LOTUS文章-->代理調試方法
     在notes編程中,尤其web開發中,代理是很常用的,但是,相對而言,代理的調試也很不方便。下面就我的經驗,列出幾種常用的方法,歡迎大家指正和補充。(這裏討論的都是lotussript代理)  1.notes端跟蹤法  使用notes開發客戶端時,對於那些在客戶端運行的代理(與服務器端運行相對)可以直接跟蹤代理的運行。  方法:選中菜單中“文件-〉工具-〉調試lotusscript”後再運行代理即可。  優點:調試直觀,代理可以單步跟蹤、設置斷點(使用stop語句或者在調試窗口中雙擊需要加斷點的語句)、觀察該中斷時刻的各種變量和對象的值等。所以使用這種調試方法可以很快地知道問題的所在。  缺點:只適用於客戶端運行的代理,而且有些web客戶端運行的代理也無法調試。 一些調試技巧:  可以把那些在服務器端運行的代理的核心代碼先在客戶端調試通過後,再改回服務器端運行,這樣有時可以節省很多調試時間。有些web端運行的代理也可照此方法調試。  2.輸出調試信息  對於那些在服務器端運行的代理,或在web端運行的代理,可以利用print命令來輸出一些關鍵的信息來幫助你瞭解問題的所在。  方法:在代理中懷疑有問題的地方或分支點附近加入print命令來打印一些關鍵信息,從而幫助瞭解問題的所在。  a.對於處於非調試狀態下的notes客戶端而言,print的信息將顯示在客戶端下部的狀態條中。  b.對於處於調試狀態下的notes客戶端而言,print的信息將顯示在客戶端下部的狀態條中和調試窗口的輸出窗口中。  c.對於web應用而言,print的信息將直接輸出到瀏覽器中。(但請注意,位於表單的webqueryopen代理中的print輸出都將被忽略)  d.對於服務器端運行的代理,print的信息將保存在NOTES.LOG文件中  附帶說一句,當代理產生錯誤時,一般都會在domino的命令窗口中產生一個錯誤信息,說明錯誤的類型,可能的話,先看看這些信息,瞭解一下錯誤的類型,可能會比一上來就盲目地跟蹤要好一些。當然,在程序編碼的同時,利用on error來建立一些錯誤報告機制,也有助於更快地分析錯誤的類型與所在。  3.代理日誌  建立一個代理日誌,這恐怕是最通用的方法了,但也相對較繁瑣。 方法:在代碼的頭部加入如下代碼(xxxx爲一隨意的日誌名,mylog爲日誌對象的名稱,可以自定):dim mylog as new noteslog("xxxx")call mylog.openagentlog在代碼需要調試的部分加入下面的語句call mylog.logaction(description$)description$ 是一個字符串常量或變量,內容根據調試的需要而定。這些內容將會寫到代理的日誌中。  日誌的察看方法:  a.在designer中打開數據庫的代理窗口。  b.在制定的代理上面點擊鼠標的右鍵  c.在彈出的菜單中選擇日誌即可  注意,代理一旦重新保存,代理日誌就會被清空。代理每次運行,新產生的代理日誌會覆蓋上一次的日誌。
版權所有2001
      某食堂管理系統,希望根據不同的用戶身份,進入相應的頁面。下面就是實現這種功能的一段代理的Initialize代碼: Sub InitializeOn Error Goto errorsDim session As New notessessionDim note As notesdocumentDim result As VariantDim i As IntegerDim viewname As StringDim querystring As StringDim doc As notesdocumentDim view As notesviewDim normaluserday As VariantDim useridday As Variantnormaluserday=Evaluate("@If(@Weekday(@Today)=1;@Adjust(@Today;0;0;-6;0;0;0);@Adjust(@Today;0;0;2-@Weekday(@Today);0;0;0))")Const notesmcro$=|@ismember("[manager]";@userroles)|'format後的normaluserday是字符串型useridday=Format(normaluserday(0),"yyyy-mm-dd")Set db=session.currentdatabaseSet view=db.getview("vshipu")Set doc=view.getdocumentbykey(useridday)Set note=session.documentcontextresult=Evaluate(notesmcro$)If result(0)=1 Then 'administratorPrint "[/"+getdbpath+"/myview?openform&view=vshipu]"Else 'normal userIf (doc Is Nothing) ThenPrint "本週食譜還未制訂,請下次再來,謝謝合作."End IfPrint "[/"+getdbpath+"/vshipu/"+doc.universalid+"?opendocument]"End IfExit Suberrors:Print ErrExit SubEnd Sub
版權所有2001
Notes R5同外部郵件系統路由的設置
 
我們知道NOTES作爲內部郵件系統是非常簡單易行的,很受大家歡迎,但習慣於使用
OUTLOOK的用戶還是喜歡使用POP3郵件格式,尤其是要和外界的POP3用戶交流信息,其實
,NOTES不僅提供了POP3服務,而且還能通過SMTP(簡單郵件傳輸協議)和其他的POP3郵
件系統進行通訊。本文主要介紹如何和其他POP3郵件系統交換信息。
  目標:
  1、使NOTES能夠同外部郵件系統通訊(包括接收和發送外來和外出郵件);
  2、爲組織內的非應用用戶提供NOTES的郵件服務,這些用戶無須安裝NOTES客戶端軟
件,就可以使用NOTES的郵件系統。
  配置服務器需要:
  1、爲服務器 啓用"在本地 Internet 網絡域外部發送消息時所用的 SMTP"
  2、爲服務器 啓用 SMTP偵聽 任務
  3、正確設置 DNS 將 DNS服務器 設置爲合適的郵件連接服務器。
  具體步驟:
  一、設置到本地 Internet 網絡域外部的 SMTP 路由
  必須啓用 SMTP 路由在本地 Internet 網絡域外部發送消息(如 Internet 或其他
私有網絡)。
  啓用到本地 Internet 網絡域外部的 SMTP 路由:
  1.確保已準備好發送郵件到 Internet 的系統。
  2.確保已經配置了服務器的"配置設置"文檔。
  3.在 Domino Administrator 中,單擊"配置"附籤,然後展開"消息處理"區段。
  4.選擇"配置"。
  5.選中"配置設置"文檔,然後單擊"編輯配置"。
  6.在"路由器/SMTP"下的"基本"附籤,完成以下域,並保存文檔:
  域 (在本地 Internet 網絡域外部發送消息時所用的 SMTP)
  輸入 (啓用,使用 SMTP 將郵件路由到 Internet)
  二、設置服務器接收通過 SMTP 路由發送的郵件
  要設置服務器接收 SMTP 路由的消息,必須啓用"偵聽程序"。然後,服務器則可以
"偵聽"TCP/IP 端口(通常端口爲 25)上的 SMTP 通信量,並可接收 MAIL.BOX 數據庫
中的 SMTP 消息。
  註釋: 不要將 SMTP 作爲任務添加到 Notes .INI 文件中的任務列表中,否則此功
能將無法工作。
  啓用"偵聽程序":
  1.在 Domino Administrator 中,單擊"配置"附籤,然後展開"服務器"區段。
  2.選擇要編輯的"服務器"文檔,然後單擊"編輯服務器"。
  3.在"基本"附籤,完成以下域,然後保存文檔:
  域 (SMTP 偵聽 任務)
  輸入 ("啓用",打開偵聽程序,以便服務器可以接收通過 SMTP 路由路由的消息)
  三、網絡域命名服務 (DNS) 和郵件路由
  在網絡域名服務器上設置Domino郵件服務器的 A記錄和MX記錄,使得Domino郵件服
務器能夠接收外來郵件;在網絡域名服務器上設置非Domino郵件服務器的 A記錄和MX記
錄,使得Domino郵件服務器能夠發送外出郵件。
  示例:
  該示例實現了兩個Domino郵件服務器的郵件路由。
  1、首先要確認兩臺服務器能夠互相PING通;
  2、要確認兩臺服務器內部郵件收發暢通;
  3、對Domino服務器進行上述修改;
  4、在網絡域名服務器上設置上設置A記錄和MX記錄。
Domino服務器1的A記錄爲:
apps.salmon.forward.com. IN A 147.25.8.17
Domino服務器1的MX記錄爲:
salmon.forward.com. IN MX apps.salmon.forward.com.
Domino服務器2的A記錄爲:
mail.ntserver.nmg.gov.cn. IN A 147.25.8.66
Domino服務器2的MX記錄爲:
ntserver.nmg.gov.cn. IN MX mail.ntserver.nmg.gov.cn.
  注:
  1、在郵遞失敗和 Domino 發送無法郵遞消息之前,消息在服務器之間所能傳送的最
大次數默認是25次。
  2、服務器在重試將消息傳送到另一臺服務器之前應等待的分鐘數。如果再次失敗,
Domino 將增加等待時間。缺省爲 15 分鐘。
  環境介紹:
  1、郵件服務器
  2、DNS服務器設置
首頁-->LOTUS文章-->如何在Notes開發的程序中實現修改留痕
如何在Notes開發的程序中實現修改留痕Notes 的一項很強大的功能是能夠實現工作流審批,但是如何能使每個審批人在對原文進行修改後留下他們的修改痕跡呢?本人寫了一段程序在Notes中嵌入word 97實現了該功能,希望對網友有所幫助。具體實現如下:首先在表單中創建一個RTF域body,以嵌入word 97,再做一按鈕,該按鈕實現對修改的留痕。其源程序爲:Dim db As New notesdatabase(servername,"jswfw")Dim handle As Variant Dim doc As NotesDocumentSet doc=source.documentDim rtitem As VariantDim object As NotesEmbeddedObject Set rtitem = doc.GetFirstItem( "Body" )Dim session As New NotesSessionDim user As Stringuser = session.commonUserNameIf ( rtitem.Type = RICHTEXT ) ThenSet object = rtitem.GetEmbeddedObject_( "Microsoft Word 文檔" )Set handle=object.activate(False)handle.showgrammaticalerrors=Falsehandle.showspellingerrors=Falsehandle.TrackRevisions = Truehandle.PrintRevisions = Truehandle.ShowRevisions = Truehandle.parent.UserName = userhandle.parent.UserInitials = userhandle.parent.UserAddress = ""handle.save End If 起草人在起草了文章後,單擊該按鈕,以後對該文章的所有修改都將保留痕跡。

 Lotus Notes/Domino是一種基於Internet/Intranet技術爲構架的羣件系統,是構造企業信息網主要工具之一。信息檢索技術作爲 LotusNotes/Domino的一個主要技術,爲用戶提供了包括全文檢索、按關鍵字查詢、視圖和文件夾等多種方式, 本文結合在實際開發中的經驗體會,對Notes應用中文檔查詢進行討論。 文檔的查詢 ---- 在LotusNotes中,信息是以文檔男問獎4嬖謔菘庵械模桓鑫牡迪嗟庇詮叵敵褪菘庵械囊桓黽鍬肌?也就是說,在NOTES應用中,對信息的查詢就是對文檔的查詢,對文檔的查詢主要有以下幾種方式:視圖、文件夾、全文檢索。下面我們來一一探討他們的特點。

---- 1. 視圖 ---- 視圖是 LotusNotes中文檔的主要瀏覽窗口,每一視圖都包含符合一定條件的文檔。當一個視圖的選擇條件給定以後,通過該視圖所看到的文檔就是符合條件的文檔,如某一視圖的選擇條件爲:Select form="請假單"; 則打開該視圖後,我們所看到的文檔都是請假單。視圖除了有選擇條件外,還可以按不同的特性將文檔進行分類和排序,使得我們可以及其快捷地導航到要查找的文檔。對於簡單的查詢,可以不編寫任何程序,而通過把視圖按合理的方式進行分類和排序就可以了。 Notes視圖設計是應用程序設計過程中較快的一步,如果數據庫第一次就設計正確,擁有在正確文檔中可用的全部必需的字段,那麼設計視圖應是一個容易的過程,且對用戶來說是直觀的,可打印輸出屏幕上顯示的視圖。

 ---- 2. 文件夾 文件夾也是文檔的瀏覽窗口之一,但是和視圖不同的是,文件夾沒有選擇條件,它裏面的文檔是通過Putinfolder來放進的,必須通過RemoveFromFolder來將其中的文檔移開。

 ---- 3. 全文檢索 ---- 全文檢索是 LotusNotes提供的基於數據庫全文索引的搜索工具,它能根據給定的檢索關鍵字在整個數據庫中搜索,並把搜索結果顯示在該視圖的頂端。

 ---- 4. 按關鍵字查詢 ---- 好的查詢設計應是對用戶的查詢給於準確快速的響應,準確,靈活地顯示用戶所需的數據。爲滿足用戶多條件的組合查詢,開發人員一般爲用戶設計一種"按關鍵字查詢"方式,需要編寫程序使用戶可以輸入一個或多個查詢條件進行組合條件查詢,找滿足條件的文檔。但是由於NOTES無法直接顯示結果,一般的解決方法是:將查詢結果存放到文件夾中,最後,打開文件夾顯示查詢結果。 文件夾方式存在的缺陷及解決方法 ---- 由於LotusNotes的文檔是可以共享的,文件夾也可以共享,也就是說,你可以用這個文件夾來存放你的檢索結果,我也可以用這個文件夾來存放我的查詢結果,而且LotusNotes應該保證互相不衝突。然而遺憾的是,LotusNotes不作這個保證,導致的結果是大家互相影響,產生訪問衝突。

爲了解決這一問題我們提出兩種方法:

 ---- 1、建立私有文件夾 ---- 所謂私有文件夾,是指文件夾屬於一人私有,其他人看不見這個文件夾。可以通過創建一個"啓動後私有"文件夾,每個用戶使用該文件夾後,系統立即根據這個啓動後私有文件夾創建一個新的屬於該用戶的文件夾。這樣,每個用戶都有一個結構完全相同而且互相不干擾的文件夾。這種解決方法保證衝突不會產生,但系統爲每個用戶保存一個文件夾,會導致系統維護上的困難。如果系統的用戶太多,情況會更壞。如果用戶註銷,它的私有文件夾不會自動刪除。 ---- 2、改進的視圖方法 ---- 視圖一般是大家共享的,我們可以通過改進視圖的選擇條件,將視圖作爲我們存儲查詢結果的地方,就能避免文件夾方式產生的問題。我們提出解決問題的思路是:把滿足某一用戶查詢條件的文檔作選擇標記,創建一個共享視圖,用視圖選擇公式來顯示該用戶的查詢結果,顯示或打印完成後,刪除選擇標記。具體實現方法如下: ---- (1) 在要查詢的數據庫文檔表單上創建一個可編輯多值的隱含?quot;SelectedUserName"用於存放查詢該文檔的用戶名。 ---- (2) 創建一個共享視圖vwSelect,視圖公式爲: ---- SELECT Form = "frmFormName" & ---- @Contains(SelectedUserName;@UserName) ---- 用於顯示該用戶查到的文檔 ---- (3) 創建一個顯示視圖的導航器"nvgQueryResult",其初始視圖爲vwSelect。 ---- (4) 用Sript語言,利用FTSearch函數進行組合條件查詢,查找滿足條件的文檔。 編程實現 ---- (1) 查詢顯示 ---- 功能:完成按關鍵字條件查詢,顯示查詢結果. Dim session As New NotesSessionDim db As NotesDatabaseDim doc As NotesDocumentDim view As NotesViewSet db = session.CurrentDatabaseitemvalues=item1.valuesCondition=itemvalues(0)For i=Lbound(itemvalues)+1 to Ubound(itemvalues)Condition=Condition+itemvalues(i)'記載用戶輸入的全部查詢條件NextCount=view.FTSearch(Condition,0) '完成全文查找If count〈〉0 ThenMessagebox"本數據庫中共有:"+Str(Count) + "個記錄滿足條件!",0+64,"提示信息" For j=1 To countSet doc=dc.getnthdocument(j)Set item = doc.GetFirstItem( "SelectedUserName" ) Call item.AppendToTextList( session.UserName ) '在域SelectedUserName中Call doc.Save( True, True )'追加用戶名NextServerName = session.GetEnvironmentString("ServerName")DirName = session.GetEnvironmentString("DirectionName")DatabaseName=DirName+"DBName.nsf" '打開導航器調用視圖,即顯示查詢結果Call workspace.OpenDatabase ( ServerName,DatabaseName,"nvgQueryResult" )ElseMessagebox "沒有滿足條件的記錄!",0 +48,"提示信息:"End Ifend(2) 退出顯示 功能:清除用戶的選擇標記 Dim session As New NotesSessionDim db As NotesDatabaseDim doc As NotesDocumentDim view As NotesViewSet db = session.CurrentDatabase ' ViewName = session.GetEnvironmentString("envViewNa")Set view = db.GetView(vwSelect)Set doc = view.GetFirstDocumentUserName=session.UserName'取現用戶名到變量:UserNameWhile Not (doc Is Nothing ) TempValue=doc.SelectedUserName '清除文檔域"SelectedUserName"中doc.SelectedUserName=""'自己的用戶名;Call doc.save(True,False) '同時保留其他用戶的用戶名.Set item=doc.getfirstitem("SelectedUserName") Forall x In TempValue If x〈〉 UserName Then Call item.AppendToTextList(x ) Call doc.save(True,False) End If End Forall Set doc = view.GetFirstDocument Wend end

主要技術要點: ---- 以上應用設計主要運用了以下技術要點來保證顯示結果的準確性和數據的共享性.

---- (1) 要查詢的數據庫文檔表單上創建的可編輯多值的隱含域"SelectedUserName" . 域是構成表單的重要元素,對一個NOTES數據庫來說,外部數據的錄入要通過域, 庫內存放數據顯示也要依靠域。我們這裏創建域"SelectedUserName"的作用是:存放查詢該文檔的用戶名作爲選擇標誌。 選擇標誌的確定:

---- 使用用戶名作爲選擇標誌主要因爲在Notes中用戶名是唯一的,不同的用戶有不同的用戶名,不會存在兩個相同的用戶名。這樣,該域記住了有哪幾個不同用戶查詢選擇了此文檔。爲用視圖顯示文檔做準備. 域的主要屬性是:

 ---- 可編輯:數據可以通過按鈕執行Formulas或Script來產生。

---- 隱含的:只作存儲,沒有顯示作用。顯示文檔時不顯示該域的數據准許多值,准許用戶存入多個值,保證該域記錄下選擇該文檔所有的用戶名。因爲在共享數據狀態下,同一個文檔同時可被多個用戶查詢選擇,你必須記住所有選擇該文檔的用戶名。這一點對於多用戶下顯示數據十分重要。 ---- (2) 視圖及視圖選擇公式: ---- 我們設計了一個共享視圖vwSelect,視圖公式爲: ---- SELECT @Contains(SelectedUserName;@UserName) ---- 視圖功能:顯示所有域SelectedUserName中含有當前的用戶名的文檔。 ---- @UserName:返回當前的用戶名。 ---- @Contains(SelectedUserName;@UserName): ---- 用於判斷是否文檔域SelectedUserName中含有當前的用戶名; 因爲在查詢時,那些滿足條件文檔的域"SelectedUserName"中已被加入了用戶名作爲選擇標誌,所以該視圖選擇顯示那些域SELECTEDUSERNAME中包含用戶名的文檔。 ---- 在視圖的設計時,使用"打開後廢棄索引"選項。 小結 ---- 綜上所述,LousNotes爲查詢應用程序開發提供了靈活快速的環境,本文所述的幾種方式都能實現對數據文檔的查詢檢索,但是,它們的實現方法和滿足的目的要求不盡相同。儘管還有不足之處需要完善, 但是仍然說明了一些能結合到你的應用程序中去的Notes技術,同時,我們必須清醒地認識到它與傳統關係型數據庫應用程序開發系統有很大的差別,查詢設計有其獨特的方式,一個應用程序能很快地被設計出來並且達到可用狀態。試圖將傳統的應用程序開發技術映射到Notes環境中的開發人員,將很難獲得Notes應用程序的優點。     
版權所有2001
LotusNotes4.5是一個很好的羣件工作平臺,它有很好的電子郵件系統,領先的全文檢索和複製功能。它還具有極強的安全措施,可以可靠地保證信息安全性。但它在解決事務處理問題上功能較弱,這時就需要傳統的關係型數據庫管理系統來協助解決。如何把現有的關係型數據庫信息轉移到Notes數據庫中,以利用Notes的許多良好性能共享數據,就是本文要討論的問題。本文以Foxpro數據庫爲例,介紹LotusNotes訪問異種數據庫的一種實現方法。LotusNotes訪問異種數據庫的途徑LotusNotes使用ODBC標準存取異種數據庫信息。通過Notes裏內嵌的公式或Script語言,可在Notes文檔中引入非Notes數據庫信息,把現成的數據轉換成Notes數據庫。Notes提供以下方法來存取外部數據:1.在Notes公式裏利用@Db函數Notes提供@DbColumn、@DbLookup及@DbCommand三個函數,這三個函數的第一個參數用“ODBC",就可訪問異種數據庫信息。但它有一個缺陷:只能按列存取信息,而不能按記錄存取信息。2.。利用LotusScript數據對象LSX兼容模塊使用LotusScript語言來編寫存取外部數據的函數,Notes的ODBCConnection、ODBCQuery及ODBCResultSet三個類爲Notes提供了用ODBC標準存取異種數據庫的屬性和操作。實例:1.定義數據源在存取外部數據之前,必須定義一個數據源,以便讓ODBC驅動程序管理器知道怎樣獲取數據。一個數據源把一個特定的ODBC驅動程序和要存取的數據聯繫在一起,幷包括要存取的數據,它與服務器或目錄、後臺DBMS以及網絡平臺相聯繫,這些信息都記錄在一個註冊文件中(在Winows95中是ODBC.INI),可採用Windows的管理工具註冊數據源。在Windows95中操作步驟如下:打開Windows控制面板,按ODBC圖標,擊Add按鈕;選擇需要的驅動程序,擊OK按鈕;輸入數據源名稱、描述信息以及所需要的其它信息;有些驅動程序還需要其他一些信息,輸入這些必需的信息,並擊OK按鈕;擊Close按鈕關閉ODBC配置。2.LotusNotes訪問Foxpro的一種實現方法實現Notes訪問Foxpro數據庫的基本編程思想是:對Foxpro的一個數據庫,按其結構相應地在Notes數據庫裏建立一個同樣結構的表單,以便把Foxpro字段的信息經轉換後存入Notes表單相應字段中;建立一個代理,用Script語言編寫轉換程序;再創建一個視圖運行這個代理,以實現異種數據庫信息向Notes數據庫轉換。現有一個Foxpro數據庫BMZBK.DBF,其結構如下:字段名類型寬度說明codeCharacter7指標編碼nameCharacter40指標名稱fullnameCharacter60指標全稱unitCharacter12計量單位3.把這個庫的所有信息轉換到Notes庫中的實現步驟如下:1.在Notes中新建一個數據庫,取名爲Convert.nsf,在這個數據庫裏創建一個表單,取名爲codelib,其內容如下:域名類型說明code文本可編輯指標編碼name文本可編輯指標名稱fullname文本可編輯指標全稱unit文本可編輯計量單位0在Convert.nsf庫中建立一個代理,取名爲vfpagent,定義如下:運行此代理的時間設定爲:人工選擇“操作”菜單執行;指定代理操作的文檔設定爲:視圖中所有文檔。2.此代理要執行的操作,用Script編寫兩個事件:(1)Option事件作如下編程:OptionPublicUselsx"*LSXODBC"'存取ODBC類庫的全局對象(2)Initialize事件作如下編程:SubInitializeDimsessionAsNewNotessessionDimdbAsNotesdatabaseDimdocAsnotesdocumentSetdb=session.currentdatabaseSetdoc=Newnotesdocument(db)doc.form="codelib"DimconnAsNewODBCConnectionDimqryAsODBCQueryDimresultAsODBCResultSetCallconn.Disconnect()Setqry=NewODBCQuerySetresult=NewODBCResultSet'VFR是ODBC裏註冊好的數據源Ifconn.ConnectTo("VFP")ThenSetqry.Connection=connqry.SQL="SELECT*fromBMZBK"'發送查詢請求Setresult.Query=qryCallresult.Execute()columns=result.Columns'取出結果集,並存入Notes相應的字段中DoUntilresult.IsEndOfDatadoc.code=Trim$(result.getvalue(1))doc.name=Trim$(result.getvalue(2))doc.fullname=Trim$(result.getvalue(3))doc.unit=Trim$(result.getvalue(4))Calldoc.save(True,True)Setdb=session.currentdatabaseSetdoc=Newnotesdocument(db)doc.form="codelib"Callresult.nextrow()LoopCallconn.Disconnect()'與數據源斷開連接ElseMessagebox("Couldnotconnecttoserver")EndIfEndSub3.在Convert.nsf庫中建立一個視圖,取名爲DemoView,在此視圖裏創建一個操作,標題爲“轉換”,運行方式爲簡單操作:運行“vfpagent"代理。這樣在打開Convert.nsf數據庫時,點擊DemoView視圖,就會在屏幕上方出現“轉換”操作按鈕,點擊這個按鈕,就可把Foxpro一個數據庫BMZBK.DBF的所有信息轉換成Notes數據庫了。

發佈了5 篇原創文章 · 獲贊 2 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章