2025/09/02

ダイアログボックスの入力チェック

これまで数回にわたり、ダイアログボックスの使い方を紹介してきました。前回前々回 は検索条件を入力することをイメージした画面を紹介しました。

このような画面では、必須項目があり、それを入力しないとダイアログボックスを閉じられない( = [OK]ボタンが通らない)というような機能が欲しくなります。

そこで、今回は、ダイアログボックスの入力チェックを紹介します。


実現方法

通常のフォームの場合、入力チェックは保存時(QuerySave イベント)に行います。ですが、ダイアログボックスの場合、文書を保存しないのでこのイベントは使えません。

利用するのは、画面の閉じる前に発生する QueryClose イベントとなります。単純に使用すると[キャンセル]ボタンで閉じるときにもチェックされてしまいます。これを回避するために、ダイアログボックス用の機能、NotesUIDocument クラスの DialogBoxCanceled プロパティを使用します。このプロパティは True の場合、[キャンセル]ボタンでダイアログが閉じられたということうを表します。


入力チェックの例

例えば上記画面で期間(From、To)とエリア(Area)を必須にしたいとします。そのスクリプトは次のようになります。

Sub QueryClose(Source As Notesuidocument, Continue As Variant)
   Dim ns As New NotesSession
   Dim ndb As NotesDatabase
   Dim nd As NotesDocument

   '[キャンセル]時はチェックなしで閉じる
   If Source.DialogBoxCanceled Then Exit Sub

   '[OK]時の入力チェック
   Set ndb = ns.CurrentDatabase
   Set nd = Source.Document

   '期間(From)
   If nd.From(0) = "" Then
      Msgbox "期間を入力して下さい。", 16, ndb.Title
      Call Source.GotoField("Form")
      Continue = False
      Exit Sub
   End If
   '期間(To)
   If nd.To(0) = "" Then
      Msgbox "期間を入力して下さい。", 16, ndb.Title
      Call Source.GotoField("To")
      Continue = False
      Exit Sub
   End If
   'エリア(Area)
   If nd.Area(0) = "" Then
      Msgbox "エリアを選択して下さい。", 16, ndb.Title
      Call Source.GotoField("Area")
      Continue = False
      Exit Sub
   End If
End Sub

構造はいたって単純です。

QueryClose は Continue 引数に False に変更する(初期値は True)と、閉じる操作をキャンセルします。そこで、[キャンセル]ボタンの操作であれば、有無を言わさず閉じるよう Exit Sub しています。

その後、対象のフィールドを順にチェックして、未入力であれば、エラーメッセージを表示して、Continue を False にして、処理を終了しています。これで、入力に不足があった場合、[OK]で閉じることができなくなります。


プリビュー時の注意

入力チェックを記述してからプリビュー表示する場合は、注意が必要です。プリビューを閉じるとき、DialogBoxCanceled は False となるので、入力チェック処理が稼働します。すべて入力しないとプリビューが閉じれなくなります。

万一、フィールド名を書き間違えた場合、入力するすべがなく、永久ループに陥ります。こうなると Designer を強制終了するしかないので、十分注意してください。


最後に

ここまで記事を書き終えた時点で何となく既視感があったのでチェックしたところ、昨年 4 月に、全く同じタイトル『ダイアログボックスの入力チェック』で記事を書いていました...。

ダイアログボックス関連の話の流れで仕方がなかったとご理解ください。


2025/09/01

ダイアログボックスと初期値の設定

前回は DialogBox メソッドで引数に文書を指定する方法を 2 つ紹介しました。既存の文書をヘルプのように表示する方法と新規文書を作成して表示する方法です。

後者は、ダイアログボックスとのインターフェースに新規文書を使うイメージですが、その活用の方法について補足します。


使いやすいダイアログを目指して

前回のプログラムでダイアログボックスを表示すると、入力項目は空っぽの状態となり、すべての項目を埋めていく必要があります。

これだとアプリとしては不便です。便利に使うためには、適切な初期値が必要です。


初期値を与える方法 ①

一番単純な方法は、ダイアログ用フォームのフィールドでデフォルト値の式をセットします。

今回のプログラムでは、新規作成した文書をダイアログに渡していたので、文書内にフィールドは存在しません。ですので、ダイアログを開くタイミングでフィールドが生成され、デフォルト値をセットする処理が実行されます。


初期値を与える方法 ②

少し複雑な処理(検索や演算)を行う場合、ダイアログ用フォームの QueryOpen で処理するという方法もあります。LotusScript で記述するので、自由度の高いコーディングが可能です。


初期値を与える方法 ③

新規作成した文書にフィールドを作ってからダイアログボックスを開くことでも初期値を与えることができます。

この方法では、ダイアログの呼び出し側で初期値をセットするので、呼び出し側の状況に応じた初期値が決定できます。よって、ダイアログを複数の用途で利用する場合に特におススメの方法といえます。

例えば、次のコードは、期間は今日から 30 日後、エリアは ”近畿” を初期値としています。

Sub Click(Source As Button)
         ・・・
   Set ndb = ns.CurrentDatabase
   Set nd = ndb.CreateDocument

   '初期値のセット
   nd.From = Today
   nd.To = Today + 30
   nd.Area = "近畿"


   If True = nuiw.DialogBox("dlgSearchCondition", True, True, , , , , "出力条件", nd) Then
      '条件を取得
      vFrom = nd.From(0)
          ・・・
End Sub

この方法であれば、”九州” を初期値にしたい場合でも、簡単に対応できますね。


2025/08/31

DialogBox メソッドと NotesDocument の利用

前回の記事では NotesUIWorkspace クラスの DialogBox メソッドを紹介しました。このメソッドでは @DialogBox とは違いダイアログボックスに表示する文書をしてする引数が存在します。今回は、この引数を使った事例を紹介ます。

flag = notesUIWorkspace.DialogBox( form$ , [autoHorzFit] , [autoVertFit] , [noCancel] , [noNewFields] , [noFieldUpdate] , [readOnly] , [title$] , [notesDocument] , [sizeToTable] , [noOkCancel] , [okCancelAtBottom] )


ヘルプ機能

ノーツの[ヘルプ]メニューから[アプリケーションの使い方]を選択するとそのアプリのヘルプを表示する機能があります。表示するコンテンツはデザイナーで記述する上、アプリで 1 つしか記述できません。これでは自由度がありませんね。ビューやフォームなどの機能ごとにヘルプが表示でき、アプリの運用部門がコンテンツを作成できるようにしておけばよりタイムリーなヘルプとなります。

DialogBox メソッドを使用すれば、このような機能が作成できます。

例えば、”はじめに” という文書を表示する[ヘルプ]ボタンは、次のようなコードとなります。

Sub Click(Source As Button)
   Dim nuiw As New NotesUIWorkspace
   Dim ndHelp As NotesDocument

   ' キーワードに一致したヘルプ文書を取得
   Set ndHelp = GetHelpDoc("はじめに")

   ' 取得したヘルプ文書をダイアログで表示
   Call nuiw.DialogBox(ndHelp.Form(0), , , True, , , True, ndHelp.Title(0), ndHelp, , , True)
End Sub

GetHelpDoc は引数に指定したヘルプ文書を取得する関数をイメージしています(関数の中身やヘルプ文書のフォームは主題ではないので割愛)。

メソッドの引数にはこれまで使っていないものが含まれますので、設定理由とともにすべてを列挙します。

1 form$ フォーム名は文書のままとする
2 autoHorzFit
省略
表やレイアウト領域に合わせせない
3 autoVertFit
4 noCancel キャンセルボタン不要なので True
5 noNewFields 省略
6 noFieldUpdate
7 readOnly 編集する必要はないので True
8 title$ ヘルプ文書のTitle フィールドを設定
9 notesDocument ヘルプ文書を指定
10 sizeToTable 省略
11 noOkCancel
12 okCancelAtBottom ボタンを下に表示したいので True

ボタンをクリックすると[OK]ボタンだけが下部に表示されたダイアログボックスが表示されます。レイアウト領域や表に合わせない設定の場合、ウィンドウサイズは、画面の解像度から適当に判断されるようです。


検索条件の入力

Excel 帳票や CSV ファイルに出力する際、対象データを限定したいことがあります。このような機能の作成にも DialogBox メソッドが使えます。

まず、ダイアログ用のフォームを作成します。

ビューのアクションボタンにこのダイアログを利用した帳票出力機能を作成します。サンプルコードは次の通りです(帳票出力する関数 ExportList は本題ではないので割愛)。

Sub Click(Source As Button)
   Dim ns As New NotesSession
   Dim ndb As NotesDatabase
   Dim nd As NotesDocument
   Dim nuiw As New NotesUIWorkspace

   Dim vFrom As Variant           '期間(開始)
   Dim vTo As Variant                 '期間(終了)
   Dim sArea As String               'エリア
   Dim vKeyword As Variant   'キーワード(リスト)

   Set ndb = ns.CurrentDatabase
   Set nd = ndb.CreateDocument

   If True = nuiw.DialogBox("dlgSearchCondition", True, True, , , , , "出力条件", nd) Then
      '入力した条件を取得
      vFrom = nd.From(0)
      vTo = nd.To(0)
      sArea = nd.Area(0)
      vKeyword = nd.Keyword   'ここだけリスト値

      '帳票出力
      Call ExportList(vFrom, vTo, sArea, vKeyword)
   End If
End Sub

ポイントは新規作成した文書を使用している点です。ダイアログボックスで入力された値は、この新規文書内のフィールドとして返ってきます。それを取得することで、入力値を取得しています。

なお、帳票出力後はそのまま処理を終了しています。新規作成された文書は、保存していないので、プログラムの終了と同時に消滅することになります。


2025/08/30

LotusScript でダイアログボックスを表示(DialogBox メソッド)

ダイアログボックスは LotusScript を使って表示することも可能です。


構文

NotesUIWorkspace クラスの DialogBox メソッドを使うと指定したフォームのダイアログボックスを表示します。構文は次の通りです。

flag = notesUIWorkspace.DialogBox( form$ , [autoHorzFit] , [autoVertFit] , [noCancel] , [noNewFields] , [noFieldUpdate] , [readOnly] , [title$] , [notesDocument] , [sizeToTable] , [noOkCancel] , [okCancelAtBottom] )

引数がたくさんありますが、[ ] は省略可能であることを表すので、必須なのは 1 つ目だけとなります。オプション種類は @DialogBox とほぼ同じですね。もちろん指定したときの動作も同じです。

@DialogBox( form ; [AUTOHORZFIT] :[AUTOVERTFIT] :[NOCANCEL] :[NONEWFIELDS] :[NOFIELDUPDATE] :[READONLY] :[SIZETOTABLE] :[NOOKCANCEL] :[OKCANCELATBOTTOM] :[NONOTE] ; title )

@DialogBox のオプション設定は : (コロン)を使用してリスト値のように指定しました。DialogBox メソッドではオプション毎に別の引数になっており、その順に正しく指定する必要があるので注意が必要です。


また、LotusScript の DialogBox メソッドには、notesDocument 引数があり、ダイアログボックスに表示する文書を指定することができます。この機能については次回に詳しく紹介します。


利用例

前回 作成した[選択]ボタンの式は次の通りでした。

@DialogBox("dlgSetDept2"; [AutoHorzFit]:[AutoVertFit]; "部門の選択")

これを LotusScript で記述すると次のようになります。間にある省略できる引数は、,(カンマ)だけは記述しておく必要があります。記述は必要な引数まででよく、後続の引数は完全に省略できます。

Sub Click(Source As Button)
   Dim nuiw As New NotesUIWorkspace
   Call nuiw.DialogBox("dlgSetDept2", True, True, , , , , "部門の選択")
End Sub

ちなみに、前々回 の表に合わせてダイアログボックスを表示する式は次のようになります。

@DialogBox("dlgSetDept"; [AutoHorzFit]:[AutoVertFit]:[SizeToTable]; "部門の選択")

           ↓↓↓

Sub Click(Source As Button)
   Dim nuiw As New NotesUIWorkspace
   Call nuiw.DialogBox("dlgSetDept", True, True, , , , , "部門の選択", , True)
End Sub


戻り値の利用

ダイアログボックスを[OK]で閉じると戻り値が True となります。後続処理の実行判断に使うと便利です。

Sub Click(Source As Button)
   Dim nuiw As New NotesUIWorkspace
   If True = nuiw.DialogBox("dlgSetDept2", True, True, , , , , "部門の選択") Then
      '選択した部門に応じた処理を実行
            ・・・
   End If
End Sub


2025/08/29

レイアウト領域のダイアログボックス

前回は、@DialogBox を紹介しました。ダイアログボックスとして表示する画面は、通常のフォームと同様に作るのですが、前回の事例では表を利用しました。今回は、もう一つのデザイン方法であるレイアウト領域を使った例をご紹介します。


レイアウト領域とは

Visual Basic のフォームを作成するような操作で画面を作成できるのがレイアウト領域です。

ノーツフォーム上では段落(1 行)単位で文字やボタンなどを配置していきますが、レイアウト領域では、エリア内にオブジェクトを自由に配置できます。上記画面では前回作成した、部門の選択画面をレイアウト領域に書き換えてみたものです。自由な位置とサイズで、固定のテキストやフィールドを配置しています。


レイアウト領域の作成

フォーム内にカーソルを置き[作成]-[レイアウト領域]-[新規レイアウト領域]で作成します。追加された白い四角がレイアウト領域となります。領域の大きさは、黒い四角の点をドラッグドロップして変更できます。

レイアウト領域のプロパティでもサイズの調整は可能です。

3D スタイルにチェックを付けると背景がグレーになり、ダイアログボックスらしい色遣いになります。また、グリッドを表示して、グリッドに合わせると、この先のオブジェクトの位置揃えがしやすくなります。


オブジェクトの作成

レイアウト領域を選択してフィールドを作成すると、次のようになります。マウスで移動やサイズを変更ができるところが特徴ですね。ツールバーからさまざまなオブジェクトが作成できます。

フォームでは文字は直接入力できるのですが、レイアウト領域では、テキストボックスを作成してその中に文字を入れることになるので注意してください。

ペイントなどで作成した画像を配置することも可能です。クリップボードから貼り付ける際に[図形要素ボタン]を選ぶと、ホットスポットとして動作する画像にすることも可能です。

この記事の最初の画像で、メッセージ下にある青い線はこの ”図形” で作成しています。


なお、非表示設定はオブジェクト単位で行います。通常のフォームのように段落という考え方はない点もポイントです。


レイアウト領域のテスト

フィールドの設定などは通常のフォームとは多少違いますが、似たような操作で作業を進めます。でき上がったらプレビューで確認します。

希望通りのデザインになっていれば完成です。プレビューを閉じるとき保存するとそのフォーム名の文書ができるので注意してください。


ダイアログボックスとしての利用

フォームが完成したら、ダイアログボックスとしてテストします。前回作成したメインフォームの[選択]ボタンの式を書き換えます。フォーム名を変更し [SizeToTable] キーワードを削除します。

@DialogBox("dlgSetDept2"; [AutoHorzFit]:[AutoVertFit]; "部門の選択")

メインフォームをプリビューして[選択]ボタンをクリックします。次のようなダイアログボックスが表示されたら成功です。


まとめ

今回は、レイアウト領域を使ったダイアログボックスの作成方法についてまとめました。

レイアウト領域を使った場合、表より細やかな制御や自由な画面が作成できます。半面、位置合わせは非効率ですし、非表示制御など設定個所が増え煩雑となります。特徴を理解したうえで使い分けるといいでしょう。


2025/08/28

@Dialogbox の使い方

@Dialogbox 関数はその名の通り、ダイアログボックスを表示することができます。この関数の使い方についてまとめます。


@Dialogbox の概要

@Dialogbox 関数を実行すると現在開いている文書をポップアップの画面(以下、ダイアログボックス)で開き、それを閉じるまで元に戻ることができません。ダイアログボックス内では、関数の引数で指定したフォームに切り替えて表示されます。

通常、ダイアログボックス内で更新したフィールドは、画面を閉じたタイミングで元の文書に反映されます。


@Dialogbox の仕様

デザイナーヘルプによると @Dialogbox の構文は次のように記載されています。

@DialogBox( form ; [AUTOHORZFIT] :[AUTOVERTFIT] :[NOCANCEL] :[NONEWFIELDS] :[NOFIELDUPDATE] :[READONLY] :[SIZETOTABLE] :[NOOKCANCEL] :[OKCANCELATBOTTOM] :[NONOTE] ; title )

なんだかややこしいですね。

整理すると引数は 3 つであることがわかります。

1 form 文字列 フォーム名
2 オプション キーワード 動作オプション設定(後述)

3 title 文字列 ウィンドウタイトル

オプションにはたくさんの種類がありますが、普段使いのものだけ列挙すると次の通りです。

[AUTOHORZFIT] ダイアログボックスの横幅を、レイアウト領域または表に合わせます。
[AUTOVERTFIT] ダイアログボックスの高さを、レイアウト領域または表に合わせます。
[NOCANCEL] ダイアログボックスに[キャンセル]ボタンを表示しません。
[SIZETOTABLE] [AUTOHORZFIT] と [AUTOVERTFIT] とともに指定することで、フォーム内の最初の表に合わせて、ダイアログボックスを表示します。

複数のオプションを指定する場合は、:(コロン)で連結して指定します。


ダイアログフォームの作成

サンプルとして部門を選択する画面を作ってみます。

ダイアログフォームは通常のフォームと同じように作成します。フォーム名には dlg を接頭語につけるなるなど、それとわかる名前を付けましょう。私は、通常のフォームではないことを明示するため名称に ( ) を付け、別名を指定するようにしています。

サンプルのダイアログフォームは表に合わせるタイプで作成します。

まず、1 行 1 列の表を配置し、その中にダイアログの画面を作ります。この中身がダイアログボックスに表示されるということですね。表のセルには文字でメッセージを記述し、フィールドは見栄えがいいようにカスケードした表に配置しています。

フィールドの設定は、以下の記事で紹介したものを流用するのですが、主題ではないので割愛します。必要に応じて、リンクをご確認ください。


メインフォームの作成

ダイアログボックスを呼び出す側のフォームは次のようなイメージです。

部門用の Dept と Func フィールドは テキスト / 作成時の計算結果 となっており、初期値は null です。そして、[選択]ボタンには以下の@式を記述します。

@DialogBox("dlgSetDept"; [AutoHorzFit]:[AutoVertFit]:[SizeToTable]; "部門の選択")


@Dialogbox の動作

メインフォームをプリビューして動作確認をします。[選択]ボタンをクリックするとダイアログが表示されます。

部門を選択して[OK]ボタンを押すと選択した結果がメインフォームに反映されます。[キャンセル]ボタンで閉じたときにはメインフォームには反映されません。

もう一度[選択]ボタンをクリックするとメインフォームの部門がダイアログボックスに表示されます。メインフォームとダイアログで同じ文書を参照していることがよくわかりますね。


まとめ

今回は @DialogBox 関数を紹介しました。

ポップアップで表示することにより、入力に集中させたり、関連する項目だけを入力させるなど、強調させることが可能となります。また、メインフォーム書いては冗長になる、入力時のガイドの表示も可能ですね。

また、複数のフォームで利用できる機能をダイアログボックス化することで、部品化することも可能です。うまく活用すると、メインフォームの設計をシンプルにできますね。


2025/08/26

ビューで条件に応じて色を設定する方法

ビューで特定の文書だけを目立たせたいことはよくありますよね。今回は、条件に応じて、ビューの文字や背景色を設定する方法についてまとめます。以下のサンプルビューでは、10000 円以上の商品を赤、1000 円以上の商品を黄色で表示しています。

ビューの色の設定は、列のプロパティの[色で値を表示]を使用して設定します。少々クセのある設定ですので、順に確認しましょう。


初期状態

まず、作業前のビューの確認です。

文字色は、商品名を青、それ以外の項目をグレーで表示しています。ビューの背景は白で、一行おきの色に薄いグレーを設定しています。

単価のフィールド Price の値に応じてビューに色を設定します。


文字色の指定

色を指定する列を一番左に追加します。列式には表示する文字色を決定する式を記述します。

@If(
  Price >= 10000;
    128:0:0;
  Price >= 1000;
    128:128:0;
    ""
)

10000 円以上は赤、1000 円以上は黄色を指定します。色の指定は R G B の順でリスト値で指定します(それぞれ 0 ~ 255)。色を変えない場合は、null 文字列を指定しています。このあたりはいかにも Notes らしいですね。

列のプロパティとしては、[色で値を表示]にチェックを入れ、列を非表示に設定ます。

これで、行全体の文字色が金額に応じて変化します。


背景色の指定

もう少し目立たせたい場合には、背景色を設定することができます。一列目の列式を以下のように変更します。

@If(
  Price >= 10000 ;
     255:240:240:128:0:0;
  Price >= 1000 ;
    255:255:240:128:128:0;
    ""
)

色の指定が 6 つのリスト値となっています。この場合、前の 3 つが背景色、後ろの 3 つが文字色として利用されます。この式ではそれぞれ、薄い赤と薄い黄色を背景色として追加して、文字の色はそのままです。


特定の列だけ色を指定

色を指定する列は先頭である必要はありません。例えば 2 列目に移動するとそれ以降の列にだけ反映されます。

商品名の列だけに色を付けたい場合には、商品名の後ろの列でも色を指定します。

今回のビューは後ろの列はすべて、文字がグレーで背景は白なので、試しにその色を指定してみました。

@If(
  Price >= 10000 ;
    255:255:255:128:128:128;
  Price >= 1000 ;
    255:255:255:128:128:128;
    ""
)

すると、ビューの一行ごとの色が "白" に強制されてしまいました。赤の行でわかる通り、縞々の設定が微妙で、文字の背景が白なのに、余白は背景色の薄いグレーです。これでは中途半端で美しくないですね。

これを回避するためには、-1 を指定すると元の色で表示できるようです。

指定した式は次の通りです。

(-1):(-1):(-1):(-1):(-1):(-1)

なお、-1 をそれぞれ ( ) でくくっているのは、符号の演算子であるマイナスより、リスト連結の演算子であるコロンの方が優先順位が高いことから、確実に符号を処理させるためです。


応用技

元の列色で表示する技を応用すると、冒頭のような色設定が可能となります。

具体的には、次のように設定ます。色を指定する列は合計 3 つ作成し、背景色は条件に一致する場合には色を変えます。文字色は商品名だけ色を変え、それ以外の列は列のプロパティの色に従う設定としています。

各 ”(色を値で表示)” 列の式は左から順に以下のように設定します。

@If(
  Price >= 10000 ;
    255:240:240:(-1):(-1):(-1);
  Price >= 1000 ;
    255:255:240:(-1):(-1):(-1);
    ""
)
@If(
  Price >= 10000 ;
    255:240:240:128:0:0;
  Price >= 1000 ;
    255:255:240:128:128:0;
    ""
)
@If(
  Price >= 10000 ;
    255:240:240:(-1):(-1):(-1);
  Price >= 1000 ;
    255:255:240:(-1):(-1):(-1);
    ""
)

こうしておけば、将来、金額やカテゴリの色を変えたくなっても自由に設定できますね。


まとめ

今回はビューで条件に応じて色を設定する方法について、紹介しました。

途中で登場した、-1 を指定して元の色を表示する方法は、デザイナーヘルプやテクニカルサポートに確認して記載したものではありません。きっとインプリされているだろうと思い、トライ&エラーで確認した結果となります。正しい方法か確認できておりませんので、あらかじめご了承ください。

なお、動作検証は Notes 14.5 を使用して行いました。


2025/08/25

GetDocumentByKey が正しくヒットしない現象 !?

前回、約 20 年前に GetAllEntriesByKey を使用して、トラブルが発生した話をしました。これがきっかけでトラブルを引き寄せたのかもしれませんが、またしても、ビューの検索でトラブルが発生しました。

今回は、GetDocumentByKey に起因する問題でした。トラブル内容をまとめますので、みなさまもお気を付けください...


発生した問題

まずは、問題の原因からです。Google で検索した結果、すでに不具合情報(Defect Article)が上がっておりました。

Domino Designer 64ビット版で設計を保存すると、Notes 32ビット版では GetDocumentByKey が正しく動作しない

発生条件としては次の通りです。

  • 32 ビットと 64 ビットの Notes が混在する環境で発生
  • 64 ビットで保存し、32 ビットで実行すると発生
  • GetDocumentByKey の検索キーに配列を指定した場合に発生
  • 11.0.1 FP9、12.0.2 FP3 以降の 32 ビット版では発生しない


発生状況

私がサポートしている環境は、一般ユーザは Notes 11 を使用中です。現在バージョンアップを計画中で、検証のため私の PC には 14.5 が入っています。私の PC だけが 64 ビット版ということです。

私が開発作業をすればするほど、正常に動作しない DB が増え、傷口が広がるというトラップでした...

現象としては、GetDocumentByKey の検索キーが配列ときに発生する現象のため、頻度は低めだったのは幸いでした。それでも、いくつかの症状に見舞われました。

「ビューを検索して、ヒットしなかったら文書を新規作成する」という処理では、かったぱしから新規作成されていました。また、申請番号を管理する機能において、管理文書が取得できず、初期番号が付与され、番号が重複する現象が出ました。

特に後者は後続の業務に番号を使用していたので、システムだけでなく、業務部門にも訂正作業が発生し、大きな影響がありました。


まとめ

最初に掲載した不具合情報は 2025年5月29日 の掲載でした。最新情報ではありませんが、注意喚起のため記事にしました。Notes / Domino 11 がサポート切れになったこともあり、これからバージョンアップする方もいるかと思います。移行期間中は、32 ビットと 64 ビットの混在環境になりますので、この現象にご注意ください。

本件の対策は、32 ビットで LotusScript コンパイルすることです。[すべての LotusScript をリコンパイル]でも回避できます。開発者のマシンを最後にバージョンアップ(64 ビット化)するのは非現実的ですので、32 ビットでコンパイルしてから運用 DB に反映することをリリース手順に入れた方がいいかもしれませんね。

私のような被害者がにとりでも減ることを祈っております...


2025/08/24

LotusScript でビューを検索するメソッドの違い

先日、8 月 22 日は、ノーツコンソーシアムの Domino Lounge Osaka(旧研究会)の京都開催でした。現地参加 17 名の大所帯で、大変な盛り上がりと熱量の中の開催でした。途中 10 分程度の休憩はあったものの、4 時間びっしり多種多様なセッションが目白押しでした。

私はというと『あの頃敵だった GetAllEntriesByKey が、実は最強だった件』と題して、ノーツコンソーシアム主催の次世代エース養成ワークショップのテキスト作成作業で知った新事実について発表しました。今回の記事は、そのまとめ記事となります。


きっかけ

20 年以上前の 2003 年に R5 にバージョンアップした時の出来事です。新機能だった GetAllEntriesByKey を利用したところ、サーバがダウンする現象が発生するようになりました。Lotus テクニカルサポート(当時)に問い合わせたところ、GetAllEntriesByKey から取得したオブジェクトで ColmunValue プロパティを利用すると障害が発生するとのことでした。

この結果を得て私のチームでは GetAllEntriesByKey の利用禁止を開発ルールに組み込みました。そして、私はビューの検索を GetAllDocumentsByKey しか使わないようになってしまいました。

失敗はこの問題修正をウオッチせず、利用禁止を解除することなく、現在に至っていることです。こんな、大きな問題が 20 年以上放置されるはずがなく直されているはずです(FixList をざっと確認したのですが、この障害を発見できなかったので ”はず” という表現になっています)。

そんな中、次世代エース養成ワークショップのテキスト作成で、GetAllDocumentsByKey の戻り値がビューの並び順とはならないこと、GetAllEntriesByKey は並び順の通り出力されることを紹介するため、改めて、2 つのメソッドの違いをサポートに確認しました。


メソッドの比較

まず、この 2 つのメソッドの機能の違いは次の通りだそうです。

GetAllDocumentsByKey GetAllEntriesByKey
文書そのもの (NotesDocument) のコレクションを返す ビューの行情報 (NotesViewEntry) のコレクションを返す
ビューの索引で文書を特定した後、文書全体のデータを一つ一つ読み込む 軽量な索引情報を読み込むため、高速でメモリ消費も少ない傾向
メモリ消費が多くなりがち(特に文書数が多い場合)
文書の単なる集まりであるため、並び順は保証されません ビューで定義された通りの並び順を保証
ColumnValues プロパティで各列の値にアクセス

並び順とビューの列情報にアクセスできることは知っていましたが、高速でメモリ効率がいいとは知りませんでした。明らかに、GetAllEntriesByKey の方が高性能です。

そして、ビューを検索するおススメの手順は次の通りだそうです。

  • GetAllEntriesByKey で高速に行情報を取得
  • 必要な場合にのみ、Document プロパティで文書全体を取得

GetAllEntriesByKey 一択といった感じだったので、GetAllDocumentsByKey の存在意義について質問したところ、GetAllEntriesByKey は R5 で追加された機能で、それ以前のスクリプトとの互換性を保つ目的が大きいとの説明でした。

なんだか GetAllDocumentsByKey が不憫になってきました...

なお、ここまでの情報は、Customer Support FAQ に掲載されています。詳しくは、下記のリンクをご確認ください。

NotesView クラスの GetAllDocumentsByKey と GetAllEntriesByKey メソッドの比較


メソッドの使い方

参考までに、2 つのメソッドと関連するクラスの関係をまとめると以下のような感じです。

NotesViewEntry クラスには Document プロパティがあり、ここから文書を取得できます。ただ、文書を取得することが目的であれば、GetAllDocumentsByKey の方が文書に素早く到達できます。コードをシンプルに保ちやすいと言えるかもしれません。

また、NotesViewEntry クラスのプロパティには、IsCategory や IsTotal が示すように、ビューのカテゴリや合計にアクセスできるようです。GetAllDocumentsByKey と同じように扱うと想定外の結果になる可能性がありそうですね。

GetAllEntriesByKey が機能的に優位であるのは間違いなさそうですが、機能の違いを理解した上で使い分けるべきだと思いました。

具体的には、検証した上で別途記事にしたいと思います。


まとめ

過去のトラウマがきっかけで、GetAllDocumentsByKey しか利用しない偏ったスタイルだったと気づかされました。そのおかげできっといろいろ損をしたと思います。情報のアップデートは必要ですね。また、重鎮の方は、これらメソッドの違いを知っていて、しっかり使い分けられていると伺いました。まだまだ修行が足りないと感じました。

ノーツコンソーシアムの Domino Lounge Osaka では、最初の画像にあるアジェンダの通り、さまざまな立場の方が発表します。内容は技術的なものからプロジェクト事例まで難易度も幅広く、どの発表にも「伝えたい思い」が込められています。そのため、参加者は多くの気づきを得られるだけでなく、自分の知らなかった世界を知るきっかけにもなるはずです。

そして、京都開催では本編以外にもお楽しみがあります。納涼川床での懇親会です。普段では味わえない非日常の環境で Notes/Domino の本音トークができます。今年は、台風やにわか雨に邪魔されることもなく無事開催できてよかったです。


2025/08/23

DXL Step-by-Step:#63)ビューの列

数回にわたりビューの設計と DXL について紹介してきました。最後はビューの列 についてまとめます。


列の基本構造

まずは、一番シンプルなパターンです。次のような列を DXL に変換して基本構造を確認します。


列のプロパティが column ノードの属性に設定されています。列幅は width、サイズ変更可能は resizable、複数値の分離記号は separatemultiplevalues 属性です。属性名を見ればどの設定か想像できますね。

column 直下にあるサブノードの font は、列に表示される値のフォントです。

columnheader ノードはその名の通り列ヘッダーの設定で、ヘッダに表示する値が title 属性に、ヘッダーのフォント設定がサブノードに出力されます。


列の値と計算式

列の値としてフィールドを指定した場合は、そのフィールド名が itemname 属性に出力されます(上図の DXL 参照)。

計算式の場合には、event が 'value' の code ノードが追加され、そこに式が出力されます。

itemname には '$5' とフィールド名ではないものがセットされます。これは、列のプロパティの[詳細]タブにある名前のようなのですが、この名前と式がどのように関連しているのか不明瞭に感じます。ただ、DXL では式がサブノードにセットされているので、明確ですね。


前回 DXL Step-by-Step