2026/04/27

Domino 体力測定:#5)ビュー操作 ⑤ - ハードウェアパフォーマンスとの関係

しばらく間が空いてしまいましたが、これまで4回にわたり GetAllDocumentsByKey と GetAllEntriesByKey の速度比較を行ってきました。検証のテーマは、

テーマ
#2 一般的な環境(SSD)での基本挙動確認
#3
文書サイズと検索/値取得の特性
#4 ビューの列数と検索/値取得の特性

でした。結果はいずれも GetAllDocumentsByKey が高速であるという結論でした。

連載のきっかけとなった 訂正記事 に挙げたパフォーマンスに影響を与える要因を順番に検証し、GetAllEntriesByKey が早くなるパターンを探してきました。今回は、複数の PC を使用して、CPUやメモリ、ストレージの I/O が与える影響について観察します。

本来であれば別々に観察すべきですが、個人的に用意できるリソースには限りがありますので、おおざっぱなテストになります。予めご了承ください。


検証環境

今回の検証で使用する PC は以下の 3 台で、構成は次の通りです。

  PC1 PC2 PC3
CPU Ryzen 7 7900X Ryzen 5 3600 Celeron G540
メモリ 128 GB 32 GB 2 GB
ストレージ SSD SSD HDD
OS Windows 11 Windows 10 Windows 10 

検証に当たり、各 PC のベンチマークを行いました。主な項目と測定結果の画像は次の通りです。

  PC1 PC2 PC3
All 26,123 11,522 756
CPU 17,564 7,065 3842
ランダムリード 713 590 6
ベンチマーク結果



テスト項目と手順

テスト項目はこれまでと同じです。GetAllEntriesByKey では、ビューから値を取得するだけなら 1 ~ 3、文書フィールドにアクセスするなら 1、2、4、5 の合計時間となり、GetAllDocumentsByKey と比較できます。


検証項目 D)GetAllDocumentsByKey E)GetAllEntriesByKey
1 コレクション作成 GetAllDocumentsByKey で検索し、コレクションを取得GetAllEntriesByKey で検索し、コレクションを取得
2 エントリ取得 GetFirstDocument、GetNextDocument で文書を取得GetFirstEntry、GetNextEntry でエントリを取得
3 値の取得 文書から値を取得ColumnValues で値を取得
4 文書の取得 Document プロパティで文書を取得
5 文書から値の取得 文書から値を取得

測定する DB はこれまでのものを流用します。100 Byte のダミーフィールドを 200 個追加した文書(#3 で紹介)を列数の違うビュー(000 と 200)で検索します。000 はダミーフィールドなしの軽いビュー。200 はすべてのダミーフィールドを列に追加した重いビューをイメージしています(#4 で紹介)。

測定手順も同じです。ビューに対して 20 回の検索を行い、取得したコレクションからエントリと値を順に取得する操作を 50 回行います。測定回数は 10 回としますが、PC3 はあまりに遅いため 3 回としました。


結果

測定した結果をグラフに表すと次の通りです。

(図 #5-1)

縦軸をそろえたグラフは次の通りです。

(図 #5-2)


考察

◇ 基本特性の変化

図 #5-1 を確認します。

上段(軽いビュー)の結果を比較すると PC1、2 に比べ PC3 でその差が幾分詰まっています。貧弱なリソース環境においては GetAllEntriesByKey の方が効率的に動くように設計されているのかもしれません。

下段の重いビューでは、処理の比率に変化は見られません。ビューの列が増えることで、効率の良さを打ち消しているのではないかと想定できます。

どちらの検証結果についても GetAllDocumentsByKey が優位であることには変わりがなく、GetAllEntriesByKey が逆転することはありませんし、その気配すら感じません。


◇ リソースの確保は重要

図 #5-2 では縦軸をそろえているので、絶対的なレスポンスがわかります。

最も時間を要している処理1を使って比較します。PC1 の処理時間を基準にすると次のような差(単位:倍)となりました。

環境 View = 000 View = 200
PC2 2.48 2.30
PC3
11.58 64.77

PC3 ではストレージが HDD であることに加え、CPU やメモリも貧弱です。これが原因で、テスト時にはスラッシングが発生していたと推察できます。これが原因となり PC2 に比べ異常ともいえるパフォーマンスの劣化が発生したと考えられます。リソース確保の重要性がよくわかる結果ですね。


まとめと今後の進め方

PC3 の View = 200 のテストはスラッシングが発生し、スペック以上に能力が低下していたと推察しました。ということは、さらに昔の世代のテストができたのかもしれません。しかし、この状況においても GetAllDocumentsByKey が優位であることには変わりがありませんでした。本当に昔の常識とされた GetAllEntriesByKey 優位というシナリオは存在するのでしょうか?

残された可能性は ODS ぐらいですかね。最近の ODS では GetAllDocumentsByKey に対する最適化が進み、逆転するシナリオが存在しないという可能性です。ODS については腰を据えて、検証してみたいと思っていたので、別途検証したいと思います。よい結果が出れば、塩漬けされた Domino サーバをバージョンアップする理由になるかもしれませんね。


これまでの『Domino 体力測定』は、きっかけとなった 過去の神話 を検証する方向で進めてきました。明確な答えが出ないまま方向転換するのは残念なのですが、過去を振り返るより将来にわたって ”使える” 検証に時間を割きたいと思います。

今後 ODS の評価以外にも、NotesDocumentCollection クラスの GetNextDocument と GetNthDocument の比較など、複数の手法がある開発を題材に比較してみたいと思います。


前回 Domino 体力測定

2026/04/09

Notes 14.5.1 とデフォルトフォント

Notes 14.5.1 ではデフォルトフォントが Inter 系に変更されました。このフォントはシンプルでモダン、英数字のバランスが良く、特に画面表示において読みやすいフォントだそうです。


設定画面とデフォルトフォント

Notes クライアントのファイルメニューから[設定]を選択します。

14.5.1 ではこのメニューが階層表示するよう改善されています。ちょっとスペースを取りすぎているような気もしますが、わかりやすくなっています。また、検索もできるようになったのもよさそうですね。

デフォルトフォントの設定は[クライアントの構成]-[Notes クライアントの基本設定]にあります。

[デフォルトフォント]ボタンで確認すると Default Sans Serif が Inter Medium となっています。この設定で Notes 内のすべてのアプリを一気にモダンにしようという算段のようですね。

この設定でアプリを使用していて、いくつか気が付いたことがあります。


¥マークの表示

最初に気が付いたのは、半角の ¥ がバックスラッシュ(\)として表示されることです。

フォルダの区切り文字が変わる程度であれば問題はありませんが、金額に¥マークを付けているような通常の文書では気になると思います。


折り返し注意

Inter 系のフォントはこれまでのフォントより幅広となります。これがきっかけとなり、折り返しが発生したり、日付と時刻がひっついて表示される現象が出ました。

フォームの設計を確認すると、日付と時刻をそれぞれ表のセルに入れる仕組みになっていました。列幅を固定することで隙間を開けていたのですが、フォントの幅が変わることで想定外の状況になったようです。


このような現象はノーツの文書でも発生します。

リッチテキスト内の表では[自動サイズ]が利用でき、その時点のセル内の文字に合わせて表の幅をピッタリに合わせてくれる機能があります。

旧バージョンでこの設定を実行し 14.5.1 で確認すると、折り返しが発生してしまいます。


まとめ

今回は 14.5.1 のデフォルトフォント変更について、気が付いた点を紹介しました。フォント系のトラブルとしてはよくある話ですね。

見た目を一気にモダンにできる反面、今回のように多少の影響も発生します。対策として「旧来フォントに戻す」という手もあります。確かに安心で手軽です。また、フォーム設計で Default Sans Serif を使わず、「メイリオ」などに固定する方法もあります。

そんなことを考えていたら、ふと思い出したセリフがあります。

『地球の重力に魂を引かれた人々』

これら対策は最適解なのか、それとも“慣れ”に引かれているだけなのか。さて、あなたはどちらを選びますか?

ニュータイプになるには、試練を乗り越える必要がありそうです。


2026/04/05

Notes 14.5.1 の絵文字の仕組み

先日リリースされた Notes 14.5.1 の新機能の中に絵文字のサポートがあったので、試しに触ってみました(Notes 14.5.1 の一般的な機能強化)。


絵文字の使い方

Notes 14.5.1 ではリッチテキストエディタの拡張として絵文字をサポートしています。ツールバーのフォントのエリアに絵文字を入力するための機能が追加されています。

実際にメールを新規作成して、入力してみます。

ツールバーから絵文字を選択するとカーソルのある所に挿入されます。使い方は他のアプリと同じですね。

実際にメールを送信して、Gmail で確認すると Notes と全く同じように表示されています。


絵文字の仕組み

どのように実現されているのか仕組みを確認します。

Notes で送信したメールを開き文書のプロパティで確認します。残念ながら、絵文字らしき情報は確認できないですね。



詳細を調べようと思い、リッチテキストを DXL に変換して確認するとすぐにわかりました。絵文字はただの画像なんですね。リッチテキスト内に直接貼り付けたインラインイメージと同じ構造になっています。

DXL について興味のある方は別の連載『DXL ことはじめ』『DXL Step-by-Step』を参照ください。


Notes らしい実装

画像だとわかれば DXL を使わず、もっと簡単に確認できます。絵文字を選択してプロパティを開くと[画像]として表示され、インラインイメージとして表示されます。

”絵文字”って言うので、Unicode で定義されている絵文字を想定していましたが、今回の対応では画像としての対応でした。

文字 vs 画像。文字は、軽量で検索も可能な反面、フォントなど環境に依存します。画像は、環境依存が少ない反面、データサイズが大きくなります。どちらも一長一短あります。

Notes/Domino は過去のバージョンとの互換性を重視しているシステムです。今回実装の画像での対応は、以前からある機能そのまま利用しているだけですから、過去のバージョンの Notes クライアントでも問題なく表示できます。

Notes/Domino らしい実装だと言えますね。


2026/04/01

複数値を分離して表示とヘッダーソート

以前『リスト値とビュー』という記事で、Notes の特徴的な機能であるリスト値(複数値)をビューで活用するテクニックを紹介しました。先日、このテクニックに関して新しい注意点を発見したので紹介します。


複数値を分離して表示の動作

まずは、前回の記事を再編集して、そのテクニックのおさらいします。以下のフォームは交通費精算書をイメージしています。交通機関や金額は1申請につき複数必要となりますが、これをリスト値で管理させています。

このような構造とすることでフィールド数が削減でき、入力できる件数に実質制限がなくなります。Notes ではよく使う手段ですよね。

紹介したテクニックは、このような複数のリスト値が対になって保存されている文書をビューでバラバラに表示する方法です。利用するのは列のプロパティにある『複数値を別のエントリで表示』です。

例えば、交通機関でカテゴリ化して、金額と備考を『複数値を別のエントリで表示』させると次のようになります。リスト値の各要素がうまく分離されて表示できます。

なお、この『複数値を別のエントリで表示』機能は少々癖のある制限があります。前回の記事では、次の2つを紹介しました。

  • 『複数値を別のエントリで表示』する列より左の列でソートする
  • 『複数値を別のエントリで表示』する列ではソートできない

例えば、金額列でソートも有効にします。すると、次のようにすべての組み合わせがビューに表示されるという症状が出ます。今回の文書で言うと青が正しい行で、赤が正しくない行となります。


今回発見した現象

前置きが長くなりましたが、ここまでは復習で、ここからが今回の本題です。

リスト値を活用したアプリ開発において、私はこの技をよく使用するのですが、まれに思い通りに動かないことがありました。ずっと原因不明だったのですが、先日理由がわかったので紹介します。

発生した問題は次の通りです。一見、リスト値がうまく分離されているように見えるのですが、各行で本来異なるはずの金額が、すべて「リストの1件目の値」で上書きされたような表示になっています。

この現象は、先に挙げたすべての組み合わせが表示される症状とは違います...。


原因

このビュー、以前は正常に動作していたんです。ただ、ある時ユーザの要望でちょっとだけ修正したタイミングから正しく動作しなくなりました。

間違い探しみたいですが、先の画像の修正前後を見比べるとその原因がわかります。


そうです。原因は、ビューヘッダーのソート機能を有効にしたからなんです。

実際にそのカラムでソートしてみると次のようになります。ソートしたときに表示されている値が、ヘッダーソートをしない状態でも採用されており、しかも、すべてのリストエントリで表示されるという現象が発生していたようです。


まとめ

今回は『複数値を別のエントリで表示』機能で新たに発見した現象を紹介しました。うまく動作すれば便利に使える機能ですが、落とし穴がいくつもあるので注意が必要です。

きっかけとなったヘッダーソートの機能は、便利でユーザ受けもいいので、安請け合いしがちなのですが、思わぬ影響が出てクレームにつながりました。おいしい話には裏がある、慎重に行動しないと駄目ですね...


2026/03/24

それ、バグじゃなくて“索引”です

先日、ユーザさんからの調査依頼がありました。「ビューに表示されている値と、文書を開いたときの値が違う」というのです。若手担当者にはバグに見えたのでしょう。懸命に調査していました。

しばらくたって、相談を受けたのですが、私のような ”古参 Notes オタ” ならピンときます。なんだかわかりますか?

そうです。「ビューの索引が壊れた」ってやつですね!

そういえば最近の Notes/Domino ではあまり発生しなくなったような気がします。ずいぶん性能が上がって、安定したんでしょうね。私がノーツを始めた 30 年前はよくありました。だからこそ、察しがつくんです。


本当に壊れてる?確認してみよう

私がよく使うビュー索引のチェック方法を紹介します。

対象のビューを Domino Designer で開き、F9 を押し、ビューの中身を表示させます。Designer 上に表示された中身と Notes クライアント上のビューを比較します。差がある場合には索引が壊れている可能性が高いです。


索引の再構築(Shift + F9)

ビュー索引の再構築は Notes クライアントから簡単に行えます。対象のビューを開き、Shift + 'F9' キーを押すだけです。ステータスバーに『索引を再構築します...』とメッセージが表示され、終了すると再構築したビューが表示されます。文書数が多い DB では時間がかかることもあるので注意しましょう。

昔の Notes では、メールでこの操作を行うことがありました。ノーツ利用歴が長い人ほどこの操作になじみがあるのはこのためですね。

ちなみに、Shift をおさない F9 はビューの更新だけなので、索引は再構築されません。


他にもある再構築方法

ビュー索引の再構築は他にもいろいろな手段があります。例えば、

  1. ビューの設計を変更する
  2. サーバコマンド updall -R を使う
  3. Administrator クライアントの[ファイル]タブで、[データベース]-[ビューの管理...]がらビューの索引を消す

 などです。

1 と 3 の操作では索引が消えたままとなるので、次にユーザが開いたタイミングで索引が構築されます。DB が大きい場合、最初のユーザが割を食うことになります。もはや、管理者による無差別テロです。...なので、ちゃんと索引は作っておいてあげましょう。


2026/03/20

Notes/Domino 2026 (v14.5.1) がリリースされました!

2026/3/19 の夕方(日本時間)、Notes/Domino の最新バージョンがリリースされました。ところどころで ”2026” と表記されていますが、バージョン番号でいうと 14.5.1 となります。早速インストールしてみました。

今回は Notes クライアントのファーストインプレッションを紹介します。

Notes クライアントを起動すると、いつも通りパスワード入力画面が表示されます。マージンを広くとった今風の画面に変更されていますね。入力したパスワードに応じてアイコンが切り替わる伝統的な機能はそのままなので、オールドタイプなユーザにもなじめるように配慮されているのがありがたいです(笑)。

最初に表示される画面に Notes 2026(v14.5.1)の新機能がまとめて紹介されていますね。


プロパティボックスの変更

私が一番インパクトのあると感じたのは、プロパティボックスの変更です。これまでの Notes クライアントでは小さなポップアップ画面に表示されていましたが、14.5.1 ではサイドバーに統合されています。

文書を選択して Alt + Enter でプロパティボックスを開こうとすると、サイドバーが開きそこにプロパティが表示されます。旧文書プロパティ画面の上部にあったタブは、アコーディオン形式のインターフェースに変更されています。サイドバーアプリらしい仕様変更ですね。

サイドバーのプロパティアプリ(呼び方が正しいかは不明)の最上部にはオブジェクトを切り替えるコンボボックスがあり、『データベース』のプロパティに切り替えることができます。基本的な機能は旧来のプロパティボックスを踏襲しているので、操作に迷うことはなさそうです。

旧来のフロート型では Windows で 150% などに拡大した場合や 2 画面以上のディスプレイを使用すると、プロパティボックスが行方不明になることがあったので、この仕様だと安心ですね。

サイドバープロパティはマージンを十分にとった今風の画面に仕上がっています。マウスの移動距離が少し長いこと、見た目が Excel ぽいのが少し気になりますが、正しく進化しているということなのでしょうね。

なお、右クリックメニューの一番上から[プロパティ]が消えていて、プロパティとしては詳細プロパティが採用されいます。プロパティボックスを開く操作で右クリックメニューを利用していた方は注意が必要ですね。なお、初めにも書きましたが、Alt + Enter の操作でプロパティを開く操作は引き続き有効です。


文字のプロパティは便利

サイドバーに入ったプロパティで大きく変わったのは『文字』の設定です。特に色の設定は他のアプリでも一般的にありそうなインターフェースになっています。マウス操作でフルカラーから選択できますし、16進数で色コードを入力することもできます。

秀逸だと感じたのはスポイト機能です。これを使えば色番号がわからなくても同じ色に設定することが可能になります。

このスポイト機能は、Notes クライアントの外側、Windows の他のアプリからも色を拝借できるのでとても便利そうです。

ポップアップ表示される”点眼器”って日本語訳はいただけないですが...。


がんばれ Designer!

さて、今回はインストールほやほやの Notes 2026(v14.5.1)を紹介しました。いろいろ書きたかったのですが、結果的にプロパティボックスの話だけになってしまいました。その他の機能については、おいおい紹介したいと思います。

ところで、このサイドバーのプロパティボックスは、残念ながら Notes クライアントのみで有効です。残念なことに Designer では利用できず従来通りのフロート型のボックスで表示されます。プロパティの複雑度がはるかに高いことや UI の構造が違うのが原因でしょうが、統一してほしいですね。

しかも、Designer をインストールしたマシンの Notes クライアントでも使用できないんです。ということは私にとっては縁のない機能ってことになります。スポイト機能は開発者こそ必要な機能だと思うんですけどね。

早急な対応を希望します。がんばれ!HCL の”中の人” !!

 

2026/03/11

LotusScript のオンサイトサポート

先日、ノーツコンソーシアムの研究会 Domino Lounge で一緒に活動しているユーザ企業の方から LotusScript に関する問い合わせがありました。ちょうど良いタイミングでオフ会があったので、前乗りしてオンサイトサポート活動を行いました。LotusScript におけるハマりポイントがいくつかあったので、許可をもらって記事にさせていただくことにしました。

なお、材料となるのは Domino IQ のサンプルアプリですが、Domino IQ の機能に特化した話ではありません。予めご了承ください。


お問い合わせ内容

ディスカッションテンプレートをもとに Domino IQ のサンプルアプリを作っており、次の2つの処理をまとめて実行させたいとのことでした。

  1. 文書内の本文を IQ に要約させて Summary フィールドにセット
  2. その要約からさらにカテゴリを生成させ、Categories フィールドにセット

お問い合わせがあった時点でのコードは次の通りでした(記事化に当たり一部調整済み)。

Sub Initialize
   Dim ns As New NotesSession
   Dim ndb As NotesDatabase
   Dim nuiw As New NotesUIWorkspace
   Dim nuid As NotesUIDocument
   Dim llmreq As NotesLLMRequest
   Dim llmres As NotesLLMResponse
   Dim sText As String

   Set ndb = ns.CurrentDatabase
   Set nuid = nuiw.CurrentDocument

   '要約の問い合わせ
   sText = nuid.FieldGetText("Body")
   Set llmreq = ns.CreateLLMRequest()
   Set llmres = llmreq.Completion(ndb.Server, "DiscussSummerry", sText)

   If (llmres.FinishReason = LLM_FINISH_REASON_STOP) Then
      Call nuid.FieldAppendText("Summery",llmres.Content)
      Call nuid.Save()
      Call nuid.Reload()
   End If

   'カテゴリの問い合わせ
   Dim sText1 As String

   sText1 = nuid.FieldGetText("Summery")
   Set llmreq = ns.CreateLLMRequest()
   Set llmres = llmreq.Completion(ndb.Server, "DiscussCategory", sText)

   If (llmres.FinishReason = LLM_FINISH_REASON_STOP) Then
      Call nuid.FieldAppendText("Categories",llmres.Content)
      Call nuid.Save()
   End If
End Sub

このスクリプトを実行すると『文書は保存されていません。』とエラーが出るので、何が悪いのか教えてほしいというお問い合わせでした。

コードを見る限り、処理 1 と 2 をそれぞれ作成し、スクリプトをつなげたように見えます。そして、つなげる前のスクリプトは単体では正常に動作したとのご報告がありました。


エージェントの対象と NotesUIDocument

調査にあたり、まず、現象を確認します。

新規で文書を作成し、エージェントを実行すると確かに『文書は保存されていません。』エラーが発生します。

どこでエラーが発生しているのか確認するために、デバッグモードにして実行してみます。すると、デバッガが起動することなくエラーが発生します。この結果より LotusScript のエラーではないと判定できます。

Use したスクリプトライブラリ内の Initialize 内でエラーが発生した場合、LotusScript が原因でもデバッガは起動しません。今回はそのようなパターンではないので LotusScript のエラーではないと判定しています。

このような場合、エージェントのプロパティの確認が必要です。今回のエージェントでは次のようになっていました。さて、問題点がわかりますか?


エラーの原因は[実行時]-[対象]の設定が『すべての選択文書』となっているからです。

LotusScript のエージェントの場合、この対象の設定は NotesDatabase クラスの UnprocessedDocuments プロパティの利用を前提にした機能だと理解しておくとよいでしょう。ビューで選択した文書や新着メールなどを効率よく取得することができます。

そうした仕様からなのか UI の文書が新規文書でまだ保存されていない状態だと『文書は保存されていません。』エラーが発生することになります。UI の文書がバックエンドの nsf 内に存在しないからだと思います。

今回のスクリプトでは、処理対象の文書は NotesUIDocument 経由で取得しているので、対象による文書の特定は不要です。このような場合では、対象を『なし』としておく必要があります。

その結果、問題のエラーが回避でき、デバッガが起動するようになります。これでやっと LotusScript の土俵に乗った状態といえます。

今回は LotusScript のエージェントのエラーではあったのですが、原因はスクリプト外にあったという点がポイントですね。


保存は何度も行わない

お問い合わせのコードを見ていて気が付いた点です。nuid.Save() を 2 カ所で実行している点です。先の『文書は保存されていません。』エラーに対応するため試行錯誤で入れたコードだと思われますが、よい対応とは言えません。

本件に限らずエンドユーザ作成のコードを見ていると、一連の処理で何度も保存しているコードを見ることがあります。正常に動けばそれでいいじゃないか、細かいこと言うなと思うかもしれませんが、私は気になりました。

例えば、将来の改造で作成者や読者の操作する機能を追加したことを考えてください。一度目の保存で文書に対する権限がなくなったとすると、二度目の保存ではエラーが発生することになります。複数回の保存が、将来の改造において足かせになりかねません。後任者(将来の自分を含む)に対するトラップになりうるので、保存は一回にとどめるようにしましょう。

また、保存するなら目立つ場所で行うのも重要です。コードの最後や関数のできるだけ外側がよいと思います。文書の取得や作成と同レベル(同じ関数内)にしておくと気づきやすいですね。


サポート終了後のスクリプト

今回のお問い合わせに対しては、最終的に以下のコードを回答としました。

'これは編集モード前提のエージェントです。
Option Declare

Sub Initialize
   Dim ns As New NotesSession
   Dim ndb As NotesDatabase

   Dim nuiw As New NotesUIWorkspace
   Dim nuid As NotesUIDocument
   Dim llmreq As NotesLLMRequest
   Dim llmres As NotesLLMResponse
   Dim sBody As String
   Dim sSum As String

   '変数初期化
   Set ndb = ns.CurrentDatabase
   Set nuid = nuiw.CurrentDocument

   '本文をテキストで取得
   sBody = nuid.FieldGetText("Body")

   '要約問い合わせ
   Set llmreq = ns.CreateLLMRequest()
   Set llmres = llmreq.Completion(ndb.Server, "DiscussSummerry", sBody)

   If (llmres.FinishReason = LLM_FINISH_REASON_STOP) Then
      '要約取得
      sSum = llmres.Content

      '要約セット
      Call nuid.FieldAppendText("Summery", sSum)
   End If

   'カテゴリ問い合わせ
   If sSum <> "" Then
      'カテゴリ問い合わせ
      Set llmres = llmreq.Completion(ndb.Server, "DiscussCategory", sSum)

      If (llmres.FinishReason = LLM_FINISH_REASON_STOP) Then
         'カテゴリ取得とセット
         Call nuid.FieldAppendText("Categories",llmres.Content)
      End If
   End If
End Sub

修正にあたり意識した点は次の通りです。私が担当した LotusScript 講座の受講経験をお持ちだったので、(復習を兼ねて)少々細かな点についても補足させていただきました。

  • 編集モード(入力中の実行)を前提に、保存をなくし、IQ の結果をフィールドにセットするだけにした(保存は UI の操作に任せ、スクリプトに頼りすぎない)
  • IQ が作成した要約を文字列変数に保管し、カテゴリ作成に利用(UI と スクリプト間の往復を減らす)
  • NotesLLMRequest の初期化は 1 回でよい
  • Option Declare を宣言し、暗黙の変数宣言を禁止

2026/03/05

NotesDbDirectory の使い方

Domino サーバの管理アプリを作成しているとサーバ内のアプリケーションの一覧を取得したくなることがあります。このようなときに利用するのが NotesDbDirectory クラスです。

先日久しぶりにこのクラスを利用しようとしたとき、思い出せずヘルプのお世話になりました。いい機会なので使い方などをまとめておきたいと思います。


オブジェクトの取得方法

NotesDbDirectory クラスは NotesSession クラスと同様に New でオブジェクトを新規作成することができます。

    Dim ndbdir As NotesDbDirectory
    Set ndbdir = New NotesDbDirectory( serverName$ )

引数には一覧を取得したいサーバ名を設定します。Null を指定するとサーバではなく、ローカルに接続します。


一覧の取得

接続したサーバの一覧を取得するには GetFirstDatabase というメソッドを使用します。

    Set ndb = ndbdir.GetFirstDatabase(DATABASE)

引数には、データベースの種類を指定します。次の定義済みの定数が利用できます。

定数 説明
1247 DATABASE Notes データベース (NSF ファイル)
1248 TEMPLATE Notes データベースのテンプレート (NTF ファイル)
1245 REPLICA_CANDIDATE 複製不可ではない Notes のデータベースまたはテンプレート
1246 TEMPLATE_CANDIDATE Notes データベースまたはテンプレート

GetFirstDatabase 実行すると一覧の最初のデータベースが返されます。その次のデータベースは GetNextDatabase メソッドを使用ます。

例えば、次のスクリプトでは、ローカルのすべてのデータベースのファイルパスを順にメッセージボックスで表示します。

    Dim ndbdir As NotesDbDirectory
    Dim ndb As NotesDatabase
    
    Set ndbdir = New NotesDbDirectory("")    'ローカルに接続
    Set ndb = ndbdir.GetFirstDatabase(DATABASE)    '最初のDB

    While Not (ndb Is Nothing)
        MsgBox ndb.FilePath
        Set ndb = ndbdir.GetNextDatabase()    '次のDB
    Wend

最後のデータベースの次は Nothing となる点がポイントですね。


一覧はソートされていない

NotesDbDirectory クラスが作成する一覧がどのような順序なのかは不明です。例えば、上記スクリプトをあるサーバに対して実行したところ次のような結果でした。少なくともファイルパス順ではないようです。

    homepage.nsf
    AgentRunner.nsf
    PwdResetSample.nsf
    help\decsdoc.nsf
    help\lccon.nsf
    help\lsxlc.nsf
    help\help14_admin.nsf
    help\help14_client.nsf
    help\jconfr11.nsf
    help\help14_designer.nsf
    help\help145_admin.nsf
    help\help145_client.nsf
    help\help145_designer.nsf
    panagenda\PMCInstaller.nsf
    panagenda\pmc_config.nsf
    panagenda\pmc_analyze.nsf
    iNotes\Forms9.nsf
    ontime\installer.nsf
    ontime\ontimegc.nsf
            ・・・

作成する処理によってはソートする必要があります。LotusScript でソートするには以下の記事を参考にしてください。


DB は Open されていない

NotesDbDirectory クラスを利用した特徴をもう一点。取得した NotesDatabase は「Open されていない」点に注意が必要です。

例えば、上記スクリプトを変更して文書数を取得するように変更します。

        MsgBox ndb.AllDocuments.Count


すると、次のようなエラーが発生します。

このエラーを回避するためには NotesDatabase クラスの Open メソッドで DB を開く必要があります。

NotesDbDirectory クラスは、DB をリストアップすることが目的のクラスです。この時点では、ファイルパスや DB 名のように公開されている情報のみにアクセスできます。これが Open されていない状態ということになります。

DB 内の文書(数)にアクセスするためには適切な ACL が必要です。Open することで ACL が評価され、文書にアクセスできるということになります。

アプリケーションを開くダイアログでは、アクセス権のない DB もリストアップされます。DB を選択して開こうとすると ACL が評価されます。このタイミングと Open が同じだと理解すればわかりやすいですね。

ちなみに、LotusScript のヘルプでは、Open が必要な機能は明示されています。

2026/02/26

DXL Step-by-Step:#64)システムアクションとアクションの種類の判定

#62 でアクションバーに配置するボタンの DXL について紹介しました。この記事でシステムアクションの記述に関して漏れていたので追記します。


システムアクション

システムアクションは、アクションバーの右クリックメニューで[システムアクションの挿入]を選択することで追加できます。

挿入すると複数のアクションがまとめて挿入されます。アクションの名称やアイコンなどのプロパティ、非表示式などは変更できますが、動作の変更はできません。また、不要なアクションは削除することが可能です。


システムアクションの DXL

このシステムアクションをDXL で確認すると systemcommand 属性が存在し、アクションの動作が値に設定されています。

システムアクションのプロパティでは名称や非表示設定などを変更することができます。修正した設定はノードや属性に追加されます。このあたりの動作は他の DXL と同様ですね。


アクションボタンの種類の判定

今回はシステムアクションを紹介しましたが、それ以外のアクションの DXL は次の通りです。

これらの DXL の構造からアクションの種類を判定することができます。

1 systemcommand 属性が存在 システムアクション
2 code ノードが存在し event 属性が 'action' シンプルアクション
3 code ノードが存在し event 属性が 'click' formula や lotusscript などサブノードの名称で言語が決定

なお、code ノードには非表示式(event = 'hidewhen')など、アクションの動作ではないものも含まれるので注意が必要です。


前回 DXL Step-by-Step


2026/02/25

複製と競合

複製環境でアプリを運用していると、競合文書が発生することがあります。同じ文書を別々のレプリカで編集してから複製が走ると、Domino はどちらの変更を正とするか判断できず、片方の結果を “競合文書” として扱います。

今回は複製と競合文書の関係についてまとめます。


複製競合の発生

複製競合は次のようなケースで発生します。

  • サーバで文書を更新
  • ローカルでも同じ文書を更新
  • その後双方のレプリカ間で複製が実行される

この時 Notes/Domino は、どちらの更新を ”親文書” とするか判定し、もう一方の更新を ”競合文書” として保存します。結果として、1 つの文書に対して、複数のバージョンが存在することになります。

このような現象はサーバ/ローカル間だけでなく、サーバ間の複製でも発生します。


競合文書の状態

通常の競合文書と複製競合はどちらも同じ ”競合文書” で、内部的に次のような状態・関係になっています。

競合文書には3つの特殊フィールドが追加されています。

フィールド名 説明
$REF 元の文書(親文書)のユニバーサル ID。
$Conflict フィールドが存在することで競合文書であること表す。
値としては文字列で Null。
$ConflictItems 競合したフィールドを記録。

$ConflictItems は公式ヘルプには項目単独で解説がありませんが、競合したフィールド名を内部的に保持するフィールドとして実際に存在します(仕様として公開されない内部アイテムのひとつです)。


競合文書とビュー

ディスカッションテンプレートなど一般的な Notes アプリの場合、競合文書が発生すると次のように、インデントされ特別な表示となります(開くと通常通りのフォームで文書が確認できます)。

このような表示を行うビューのプロパティでは「返答文書を階層表示する」がチェックされています。これは $REF フィールドが存在することからわかる通り、返答文書の機能を利用しているからです。

競合文書の発生はアプリ開発者にとって、招かざる客といえます。競合文書の発生を監視できるビューがあると便利です。次のような選択式のビューを作成すると競合文書だけを表示するビューを作成できます。

   SELECT @IsAvailable($Conflict)

@IsAvailable は引数のフィールドが存在するかを判定します。フィールド名には引用符が付かない点に注意が必要です。

なお、このビューではプロパティの「返答文書を階層表示する」のチェックを必ず外してください。選択式に合致する文書に親文書が含まれないことから、何も表示されなくなります。


競合の解消方法

上記の通り Notes は競合を表示する機能はあるだけで、競合を解消する作業はユーザの手で行う必要があります。その操作の流れは次の通りです。

  1. 親文書と競合文書を確認し、競合内容を調べる($ConflictItems でフィールドを特定)
  2. 競合文書から親文書に反映すべき内容があれば、コピー&ペースト反映する
  3. 競合文書を削除する


競合文書側を残したい場合、競合文書をいったん編集し、保存すると親文書になります。その後、元の親文書を削除する対応が可能です。この操作でもともと親文書にぶら下がっていた子文書は、新しい親文書の下に付け替えられます。

ただ、この方法では新しい親文書のユニバーサル ID が変わりますので、元の親文書に対する文書リンクは機能しなくなるので、注意が必要です。

また、親文書の付け替えにより、子文書の $REF フィールドが更新されます。 これに伴い、子文書が未読になる点にも注意が必要です。

このような背景から競合文書側を残す運用は現実的ではないと思います。