投稿

6月, 2008の投稿を表示しています

フォームと文書の関係

フォームにはフィールドを作成することができる。
文書はフォームのフィールドに入力することで作成できる。

これらは一見すると同じもののように見えるが、当然のごとく違うものである。

フォームはフィールドを配置してある図面のようなもので、中には何もない。
文書は単なる内容を集めたものである。

文書自身は通常、表現能力を持たないためフォームの表現能力を借りて画面上に表示しているのである。

そのため、フォームが適切でないと文書が正しく表示できないことがある。

フォームには「a」「b」「c」というフィールドがあり、文書は「b」「c」「d」というフィールドに内容を持っているとする。
すると、この文書をフォームで表示した場合、「b」と「c」は正しく表示される*1が、「d」は表示できない。
また、「a」という余計なフィールドが表示される。

*1もっともフィールドの形式が適切でなければ正しく表示はできないが・・・

このとき、「a」が単なる編集可能フィールドなら大した問題ではないが、計算結果フィールドの場合、ちょっと面倒なことになる。
「a」の計算結果を表示してしまうからである。
これによって、実際の文書には存在しない「a」というフィールドがさも存在するかのように見えてしまうのである。


このことはスクリプトのNotesDatabaseクラスのCreateDocumentメソッドを使って文書を作成してみると、よく分かる。
スクリプトの場合、そのスクリプトの中でフィールドに代入しないとフィールドの値が作成されないのである。

また、文書にそのフィールドが存在するかどうかは、ビュー上で文書のプロパティを見るとわかりやすい。
ビューでは、その文書で持っているフィールドしか表示しないからである。
文書をフォーム上で表示してしまうと、文書のプロパティは「フォームのフィールドのプロパティ」+「文書の内容のプロパティ」という内容に変わってしまうのである。


余談になるが、「表示用の計算結果」もビューでは見えない。これは、「表示用の計算結果」は実体を持たないフィールドであるからだ。
そのため、文書の内容自体を表示するビュー上での文書のプロパティでは、見えないと言うことになる。


スクリプトのバックグラウンドで文書を作成すると、フィールドの属性も無視してしまう。スクリプトの中で与えた形式を属性として認識するのである。
たとえば、「c」というフィールドは数…

バックグラウンドで返答文書を作成する

自動で、現在の文書の返答文書を作成するサンプル。
関連するデータの登録や、主文書は変更したくないので追加で文書を作成する
という時などに利用するとよい。

Sub Click(Source As Button)     Dim session As New NotesSession     Dim db As NotesDatabase     Dim uiws As New NotesUIWorkspace     Dim uidoc As NotesUIDocument     Dim doc As NotesDocument     Dim resdoc As NotesDocument         '自文書の設定     Set db = session.CurrentDatabase     Set uidoc = uiws.CurrentDocument     Set doc = uidoc.Document         '新規に文書を作成した後、返答文書として位置づける     Set resdoc = db.CreateDocument     Call resdoc.MakeResponse( doc )         'スクリプトで文書を作成した場合、フィールドに何も設定されないので自分で設定する     resdoc.Form = "Response"     resdoc.Subject = "バックグラウンドで作成した返答文書"         '文書の保存     Call resdoc.Save( True , True ) End Sub





アップデート試験延長!

http://guylocke.blogspot.com/2008/04/blog-post_19.html
の記事で、2008/06/06にNotes8のアップデート試験を受験する!と書いたが、諸事情により延期しました。

いやぁ、そんな場合じゃないって。
まだNotes8の仕事なんかしてないから(日本IBMさん、ごめんなさい)、試験どころじゃないよ。
と言いつつ、6/27に延期したのですが。

さて、こんな状態で受験できるかわからないけど、1日も早くアップデートしないといけないからね。
LotusDay2008までには受かっていたいな。

DB中の各フォームのフィールド一覧

ノーツDBのフォームにどのようなフィールドが存在しているのかを調べる方法です。
ノーツ文書ではなく、フォームのフィールドというところがミソ。

サンプルは、現在のノーツDBの各フォームに作成されているフィールドの一覧を表示するものである。

Sub Click(Source As Button)     Dim session As New NotesSession     Dim db As NotesDatabase     Dim title As String     Dim sbj As String         Set db = session.CurrentDatabase     'xはNotesFormクラスが返される     Forall x In db.Forms         'x.Nameはフォーム名が返される         title = x.Name         sbj = ""         i = 0         'yにはxフォームのフィールド名が入る         Forall y In x.FIelds             i = i + 1             sbj = sbj & Cstr( i ) & "." & y & Chr$(10)         End Forall         Messagebox sbj, 0, "【" & title & "】のフィールド一覧"     End Forall End Sub


添付ファイルをディスクに保存する

ノーツ文書にファイルを添付することや、添付してあるファイルを削除するというサンプルは紹介していたが、
ローカルディスクに保存するというサンプルを提供していなかった。

下記のサンプルでいえば、
Call x.ExtractFile( res & x.Name )
がそうなのだが、変わったことが可能である。

保存する際、好きな名前で保存できるのである。
同一文書内に、同じ名前のファイルが存在している場合に、ファイル名を変更して保存できる。
という具合に使うことが可能である。


Sub Click(Source As Button)     Dim uiws As New NotesUIWorkspace     Dim uidoc As NotesUIDocument     Dim doc As NotesDocument     Dim item As Variant         '現在の文書を取得する     Set uidoc = uiws.CurrentDocument     Set doc = uidoc.Document     '添付ファイルがあるフィールドを取得する     Set item = doc.GetFirstItem( "Body" )         'フィールドが本当にリッチテキストかどうかを判断する(添付ファイルはリッチテキストにしかないので)     If item.Type = RICHTEXT Then         if doc.HasEmbedded then             Forall x In item.EmbeddedObjects                 'オブジェクトが添付ファイルかどうかを判断する(OLEオブジェクトとは扱いが異なるため)                 If x.Type = EMBED_ATTACHMENT Then                     res = Inputbox ( "添付ファイルを保存するパスを入力してください。", "添付ファイルの保存箇所", "c:\" )                     If res = &…

ノーツデータベースの一覧を表示する

ディレクトリに存在するノーツDBの一覧を取得するサンプルを用意した。
カタログDBに出力していないものや「データベースを開く」ダイアログに表示しないDBも取得できる。
隠れたDBがいそうだな?と思ったら使うとよい。

Sub Click(Source As Button)     'データベースの一覧の変数の定義     Dim session As New NotesSession     Dim directory As NotesDbDirectory     Dim db As NotesDatabase         'プログラム変数の定義     Dim res As String     Dim sbj As String     Dim i As Integer         'データベースの一覧を取得する場所を選択する     res = Inputbox ( "サーバー名を入力してください。" & Chr$(10) & "loaclの場合はローカルコンピュータを参照します。",_     "データベースの一覧", "local" )     'キャンセルを押した場合は処理を中断、localの場合はNULLに変換     If res = "" Then         Exit Sub     Elseif res = "local" Then         res = ""     End If     Set directory = New NotesDbDirectory( res )         i = 0     '最初のデータベースを取得する     Set db = directory.GetFirstDatabase( DATABASE )     'データベースを全部取得するまで繰り返す     Do While Not (db Is Nothing )         i = i + 1         sbj = sbj & Cstr( i ) & "." & db…

DBオープン時のエラーハンドリング

DBをオープンするときに、エラーハンドリングを行うと思うが、DBが存在しない場合とDBにアクセスできない場合とでエラーの種類が違う。
わかりやすいのが、NotesSessionクラスのGetDatabaseメソッド。

DBが存在しない場合は、NotesDatabaseオブジェクトをNothingとして返すが、
存在していてなおかつ、アクセスできない場合は、Err4060を返すのである。
もちろん、DBが存在していてなおかつ、アクセスできる場合は、NotesDatabaseオブジェクトを返す。

区切り文字による文字列の抜き出し

特定の区切り文字で区切られた文字列であれば、その部分を抜き出すことが出来る。
サンプルは、文字列を","で区切って、その中のx番目の文字列を抜き出すというもの。
フィールドの設定を誤ってしまい、複数値フィールドにならなかったときなどのメンテナンス用に持っておくとよいだろう。

TMP := "一番目の文字列,二番目の文字列,三番目の文字列,四番目の文字列"; @Prompt([OK];"元の文字列";TMP); TMP1 := @Prompt([OKCANCELLIST];"選択";"表示する文字列の箇所を選択してください。";"1";"1":"2":"3":"4"); REM "TMP文字列を「,」で区切った内のTMP1番目の文字列を抜き出すという関数 TMP2 := @Word(TMP;",";@TextToNumber(TMP1)); @Prompt([OK];"抜き出した文字列";TMP2)
ただし、区切り文字がデータとして存在しているような場合は注意が必要。

フォルダの作成

今回のサンプルは、Lotus Scriptでフォルダを作成するというもの。
1階層であれば、Mkdir フォルダ名で作成できるが、それでは芸がない。
ということで、複数階層のフォルダを作成するということにチャレンジしたい。
MkDirでは、上位階層のフォルダが存在しないと、下位のフォルダは作成できない。

なので、各階層ごとにフォルダが存在しているかどうかのチェックをする必要がある。
それを踏まえたサンプルである。
なお、サンプル内では省略したが、次のことにも注意しておきたい。
すでに存在しているフォルダを作成しようとすると、MkDirはエラーの75を返す。
On Errorで判断して、75の時はスキップするようにするとよいだろう。






Sub Click(Source As Button)     Dim dirname As String     Dim ret As Integer         dirname = "c:\abcde\hijkl\"     Msgbox dirname & "のフォルダを作成します。"         '1つ目を探す     ret = Instr( dirname, "\" )         'n個目を探す     Do While ret <> 0         ret = Instr( ret+1, dirname, "\" )         If ret <> 0 Then             Mkdir Left(dirname, ret)         End If     Loop End Sub




@Command([EditDocument])のノーツとブラウザでの利用方法の違い

@Command([EditDocument])という@コマンドがあるが、ノーツとブラウザでは書式に違いがあることに気をつけて欲しい。


@Command([EditDocument])
 この場合、文書を「編集モード」←→「読み込みモード」に切り替える。

@Command([EditDocument];"1")
 この場合、文書を「編集モード」に変更する。

@Command([EditDocument];"0")
 この場合、文書を「読み込みモード」に変更する。


というのが、ノーツ上での動作だが、
ブラウザ上では、
@Command([EditDocument])しか有効にならない。

ブラウザ上ではこのコマンドは、「文書を編集モードにする」だけのものなのであるためだ。
(であれば、"1"のオプションは有効になっても良さそうだが、しっかりとエラーになる)

※これらのコマンドをフォームアクションに登録して、DBのオプションで「Javaスクリプトを利用する」のチェックを外すとよく分かる。
 →オプションなしは表示されるが、オプションありは表示されないのである(実行できないコマンドは表示しないと言うルールがある)


※これは、オンラインヘルプに出ていない内容なので忘れがちだが、利用時には注意が必要。

グループの階層化の限界数

ノーツ/ドミノでは、グループの中にグループを作るという階層化を実現することが可能である。
さて、その階層数には限界がある。

R5/6/7ともに共通で、20階層である。
それを超えると、エラーになる。


エラーメッセージはこんな感じ。

「グループはメール送信の場合、20レベル以上の階層にすることはできません。」

ビューから編集モードで開かせない

ビューから直接編集モードで開かれては困る場合などにそれを制御する方法。

FormのQueryOpenイベントに下記のスクリプトを記述する。
ここで、Queryopenイベントに定義してある変数を利用すると簡単に書ける。

Source 現在開かれている文書
Mode 現在の文書のモード。読み取りモードなら0、編集モードなら1が入っている
Isnewdoc 現在の文書が新規文書かどうか。新規文書ならTrue、そうでなければFalseが入っている
Continue 処理を続けるかどうか。止める場合はFalseを代入すると良い

Sub Queryopen(Source As Notesuidocument, Mode As Integer, Isnewdoc As Variant, Continue As Variant)     '新規文書でなく、編集モードで開かれた場合は確認のメッセージを表示する     If Isnewdoc = False And Mode = 1 Then         res = Messagebox( "編集モードで開くのですか?", 4 + 32, "スクリプトサンプル集" )         '「いいえ」が選択された場合は、処理を中断する         If res = 7 Then             Continue = False         End If     End If End Sub