出直し!! ヘルプ

連載中

連載 終了

2024/01/31

@DbColmun の使い方

今回は@関数の中でもかなり使用頻度の高い @DbColumn の基本的な使い方について紹介します。


機能イメージ

まずは作成する機能にです。部門名を管理するフォームがあり、あらかじめ社内の部をマスタデータとして登録しておいたとします。

報告書フォームのフィールド ”部” の選択肢をマスタデータから読み込むというものです。例えば次のように部門欄の[▼]ボタンをクリックするとマスタデータから部を選択します。ユーザは選択するだけなので操作が簡単ですし、手入力と違い表記ブレが発生しないので、データの精度も上がりますね。


フォームの設計

このような機能を提供するのが、ダイアログリストという種類のフィールドとなります。

このフィールドに対して選択肢を与える機能がフィールドプロパティの2つ目の[制御]タブにあります。選択肢の指定方法はさまざまな種類があるのですが、”式で選択肢を設定”を選び、その下に事前に作成したビューからデータを取得する式を記述します。ここで使用する式が今回のテーマの @DbColmun 関数になります。


@DbColmun の仕様

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

@DbColumn(class:cache; server:database; view; columnNumber)

引数は 4 つです。class と cache、server と database は ":"(コロン)でつながっている点に注意が必要です。コロンはリスト演算子ですので、2 つの値をリスト値(複数値)として 1 つの引数に渡す仕様ということです。プログラミング言語的には、配列で指定するということになりますね。

引数の指定方法は次の通りです。

class 文字列 アクセスするデータベースの種類を指定
Notes/Domino の場合 "Notes" または "" (Null 文字列) を指定
cache 文字列 "" (Null 文字列) で結果をキャッシュ
“ReCache” で最新データによってキャッシュが更新
“NoCache” で常に結果を取得
server 文字列 サーバとファイル名を指定
"" (Null 文字列) で自分自身の DB
database 文字列
view 文字列 結果を取得するビュー名
columnNumber 数値 結果を取得するビュー内の列番号を指定

戻り値は、指定したビューの指定した列にある値がリスト値で返されます。


@DbColmun の動作

改めて先のサンプルの式を確認しましょう。

@DbColumn("Notes":"NoCache"; ""; "vDept"; 1)

引数では、次のように指定されていることが読み取れます。

  • Notes/Domino から結果を取得
  • キャッシュは利用せず常に最新の結果を取得
  • 自分自身のDB に接続
  • vDept ビューの 1 列目を取得

この式を中心にビューの設計とアプリの動作を図式すると以下の通りとなります。


2024/01/28

DXL Step-by-Step:#27)イメージリソースの表示

DXL 活用の調査・検証で、実現できたことや発見したことご紹介する『DXL Step-by-Step』シリーズの第 27 回です。前回の実験結果をもとに、リッチテキストにイメージリソースを表示するサンプルプログラムを作成します。


サンプルと実行結果

リッチテキストにイメージリソースを表示する方法として、次の 3 パターンを作成しました。サイズを指定しない場合、ピクセル数で指定し縦横ともサイズを倍にした場合、そして、画像のサイズを長さ(センチメートル)で指定するパターンです。


メインプログラム

前回『段落と文字の装飾』で作成したエージェントをコピペして修正する前提で記載します。記載していない部分のプログラムについては変更はありません。

まずは、DXL を作成するメインルーチン xSetDXL です。上記 3 パターンごとに関数を作成してコールしています。

Function xSetDXL(vdprs As NotesDOMParser)
         ・・・
   'リッチテキスト作成
   Set den = ddn.CreateElementNode("richtext")
   Set denRT = denItem.AppendChild(den)

   '段落定義
   Call xSetDXL_pardef(ddn, denRT)


   'イメージリソースの追加
   Call xSetDXL_ImageResource(ddn, denRT)

   'イメージリソースの追加(ピクセル指定)
   Call xSetDXL_ImageResource_px(ddn, denRT)

   'イメージリソースの追加(cm 指定)
   Call xSetDXL_ImageResource_cm(ddn, denRT)
End Function


イメージリソースの追加

最小のサブ関数、サイズの指定をせずに単純にイメージリソースを表示するだけの xSetDXL_ImageResource 関数です。par、picture、imageref の3 つのノードを階層化して順に挿入しています。最下層の imageref にはイメージリソース名を指定する name 属性を設定しています。

Function xSetDXL_ImageResource(vddn As NotesDOMDocumentNode, vdenRT As NotesDOMElementNode)
   Dim denPar As NotesDOMElementNode
   Dim denPic As NotesDOMElementNode
   Dim den As NotesDOMElementNode
   Dim dtn As NotesDOMTextNode

   '段落の作成
   Set den = vddn.CreateElementNode("par")
   Call den.SetAttribute("def", "1")
   Set denPar = vdenRT.AppendChild(den)

   '画像の作成
   Set den = vddn.CreateElementNode("picture")
   Set denPic = denPar.AppendChild(den)

   'イメージリソースの指定
   Set den = vddn.CreateElementNode("imageref")
   Call den.SetAttribute("name", "411.PNG")
   Call denPic.AppendChild(den)

   'コメントの表示
   Set dtn = vddn.CreateTextNode("← サイズ指定なし")
   Call denPar.AppendChild(dtn)
End Function


画像サイズの指定

xSetDXL_ImageResource_px では、画像サイズをピクセルで指定しています。関数の構造は、上記関数と揃えています。唯一違うのは、picture ノードにサイズを指定する属性 width と height を指定しているところです。

Function xSetDXL_ImageResource_px(vddn As NotesDOMDocumentNode, vdenRT As NotesDOMElementNode)
         ・・・
   '画像の作成
   Set den = vddn.CreateElementNode("picture")
   Call den.SetAttribute("width", "268px")
   Call den.SetAttribute("height", "152px")

   Set denPic = denPar.AppendChild(den)
         ・・・
   'コメントの表示
   Set dtn = vddn.CreateTextNode("← ピクセルで指定")
   Call denPar.AppendChild(dtn)
End Function


同様に長さで指定する場合は次の通りです。第 17 回で作成したセンチメートル(数値)をインチ(文字列)に変換する DXL_CMToInch 関数を利用しています。幅を 2 cm、高さを 1.5 cm に設定してみました。

Function xSetDXL_ImageResource_cm(vddn As NotesDOMDocumentNode, vdenRT As NotesDOMElementNode)
         ・・・
   '画像の作成
   Set den = vddn.CreateElementNode("picture")
   Call den.SetAttribute("scaledwidth", DXL_CMToInch(2))
   Call den.SetAttribute("scaledheight", DXL_CMToInch(1.5))

   Set denPic = denPar.AppendChild(den)
         ・・・
   'コメントの表示
   Set dtn = vddn.CreateTextNode("← CM をインチに変換して指定")
   Call denPar.AppendChild(dtn)
End Function


まとめ

イメージリソースの表示は、文字の装飾に比べ、ノードの階層構造が固定され比較的シンプルな構造と言えます。たったこれだけのことで、通常の NotesRichText 関連のクラスでできなったイメージリソース貼り付けができるようになります。DXL の可能性を感じる瞬間ですね。

前回 DXL Step-by-Step 次回


2024/01/27

DXL Step-by-Step:#26)イメージリソースの DXL

DXL 活用の調査・検証で、実現できたことや発見したことご紹介する『DXL Step-by-Step』シリーズの第 26 回です。前回までは段落(par ノード)内に配置されるオブジェクトとして、文字(テキスト)を配置し、その装飾について紹介しました。今回は別のオブジェクト、イメージリソースについてまとめます。

LotusScript 標準の NotesRichText 関連のクラスでは、イメージリソースをはじめ画像をインライン(見える状態)で貼り付けることができません。DXL を使えばそれが可能となり、Notes の可能性を広げることになりますね。


DXL の確認

まずは、イメージリソースを貼り付けたリッチテキストの DXL を確認しましょう。単にイメージリソースを貼り付けた場合とプロパティでサイズを変更した場合を例にします。

このリッチテキストを DXL に変換すると次のようになります。

まずはノードの構成です。段落 par ノードの下に picture ノードがあり、インラインイメージを表しています。その下に imageref ノードがあり、属性でイメージリソース名が指定されていることがわかります。構造はシンプルですね。


画像サイズとスケールの指定

picture ノードの属性で画像のサイズを指定しています。

width と height が画像のピクセル数で、スケールを設定した場合には scaledwidth と scaledheight が設定されています。単位が % ではなく、インチなのが厄介ですね...

試しに、scaledwidth='268px' や scaledwidth='200%' と記述した DXL を作成してインポートしましたが、どちらもエラーとなりました。プロパティボックスでは % 指定ですが、内部的にはインチに変換して保持しているということなのでしょう。


画像サイズの謎

今回実験に使用したイメージリソースの画像サイズは 134 x 76 ピクセルでした。DXL の width と height がその値となっているのは当たり前です。ただ、イメージリソース側に画像サイズを持っているのに、なぜ必要なのか疑問です。

そこで、イメージリソースをサイズの違う別の画像に差し替えて文書を表示すると、元の画像サイズ  134 x 76 ピクセルで差し替えられた画像が表示されました。

小さいほうの画像のプロパティを確認したところ、スケールが 100% ではなくなっていました。この結果より、width と height の属性でも拡大/縮小に利用できそうであることがわかります。


画像サイズ指定のテスト

では、テスト的な DXL をインポートして挙動を確認しましょう。

テストする項目は、

  1. width と height の設定は必須か?
  2. width と height は拡大/縮小に利用できるか?
  3. scaledwidth と scaledheight だけでも有効か?

の 3 点です。

インポートする DXL は次の通りです。

この DXL は、エラーなくインポートでき、結果は希望通りと言えます。width と height を設定しない場合は、イメージリソース通りのサイズで表示され、それ以外は指定したサイズで表示されました。なかなか柔軟に動いてくれますね。

この DXL からインポートした文書を再度 DXL に変換したところテストで作成した DXL のままでした。最初に紹介した DXL では、width と scaledwidth 両方が設定されていました。これはノーツクライアントが付加したものであり、ドミノオブジェクト的には双方の指定が必須ではないことがわかりますね。

前回 DXL Step-by-Step 次回


2024/01/25

DXL Step-by-Step:#25)サンプルコード(段落と文字の装飾③)

DXL 活用の調査・検証で、実現できたことや発見したことご紹介する『DXL Step-by-Step』シリーズの第 25 回です。「段落と文字の装飾」のサンプルプログラム紹介の最終回です。


文字サイズの指定

前回は文字の色を指定する例を示しました。今回は、色に加えてサイズも指定するパターンです。また、色の設定は定義済みの文字列を使わず、色番号で指定します。

フォントサイズは 18、13、8 と 5 刻みで小さくし、色はサイズに 8 をかけ 16 進数に変換し RGB に指定しています。8 では '#404040'、13 では '#686868' とフォントが大きいほど薄いグレーになるようにしてみました。

色とサイズの設定は、属性を 2 つセットするだけなので、難しいことはありませんね。

Function xSetDXL_par2_Size(vddn As NotesDOMDocumentNode, vdenRT As NotesDOMElementNode)
   Dim denPar As NotesDOMElementNode
   Dim denRun As NotesDOMElementNode
   Dim den As NotesDOMElementNode
   Dim dtn As NotesDOMTextNode

   Dim sTmp As String
   Dim i As Integer

   '段落の作成
   Set den = vddn.CreateElementNode("par")
   Call den.SetAttribute("def", "2")
   Set denPar = vdenRT.AppendChild(den)

   For i = 18 To 8 Step -5
      Set den = vddn.CreateElementNode("run")
      Set denRundenPar.AppendChild(den)

      '文字装飾の準備
      Set den = vddn.CreateElementNode("font")

      '色の指定
      sTmp = Hex$(i*8) & Hex$(i*8) & Hex$(i*8)
      Call den.SetAttribute("color", "#" & sTmp)
      'サイズの指定
      sTmp = CStr(i) & "pt"
      Call den.SetAttribute("size", sTmp)

      '文字装飾の追加
      Call denRun.AppendChild(den)

      'プレーンテキスト(テキストノード)追加
      Set dtn = vddn.CreateTextNode("文字サイズ " & sTmp)
      Call denRun.AppendChild(dtn)

      '段落内改行の追加
      Set den = vddn.CreateElementNode("break")
      Call denPar.AppendChild(den)
   Next
End Function

この関数で作成される DXL は次の部分となります。


パーマネントペンの指定

最後のサブ関数は、パーマネントペンの設定です。

パーマネントペンは font ノードではなく、run ノードの属性でした。サンプルコード上で青字で表示している run ノードに対して属性 highlight を設定している点に注意が必要です。

Function xSetDXL_par2_ParPen(vddn As NotesDOMDocumentNode, vdenRT As NotesDOMElementNode)
   Dim denPar As NotesDOMElementNode
   Dim denRun As NotesDOMElementNode
   Dim denFont As NotesDOMElementNode
   Dim den As NotesDOMElementNode
   Dim dtn As NotesDOMTextNode

   Set den = vddn.CreateElementNode("par")
   Call den.SetAttribute("def", "2")
   Set denPar = vdenRT.AppendChild(den)

   'フォントの準備
   Set denFont = vddn.CreateElementNode("font")
   Call denFont.SetAttribute("size", "18pt")

   'パーマネントペン なし
   Set den = vddn.CreateElementNode("run")
   Set denRundenPar.AppendChild(den)
   Call denRun.AppendChild(denFont.Clone(True))
   Set dtn = vddn.CreateTextNode("パーマネントペン:")
   Call denRun.AppendChild(dtn)

   'パーマネントペン 黄色
   Set den = vddn.CreateElementNode("run")
   Call den.SetAttribute("highlight", "yellow")
   Set denRun denPar.AppendChild(den)
   Call denRun.AppendChild(denFont.Clone(True))
   Set dtn = vddn.CreateTextNode("黄色")
   Call denRun.AppendChild(dtn)

   'パーマネントペン なし
   Set den = vddn.CreateElementNode("run")
   Set denRun denPar.AppendChild(den)
   Call denRun.AppendChild(denFont.Clone(True))
   Set dtn = vddn.CreateTextNode("、")
   Call denRun.AppendChild(dtn)

   'パーマネントペン ピンク
   Set den = vddn.CreateElementNode("run")
   Call den.SetAttribute("highlight", "pink")
   Set denRun denPar.AppendChild(den)
   Call denRun.AppendChild(denFont.Clone(True))
   Set dtn = vddn.CreateTextNode("ピンク")
   Call denRun.AppendChild(dtn)
End Function

この関数ではすべての文字を 18 pt で表示する前提としています。font ノード毎回生成するのは面倒なので、事前に作成して denFont 変数に保持させています。それを各 run ノードで適用しています。この時、Clone メソッドを使用している点がポイントです。これを実行しないと denFont の設定は最後の”ピンク”の部分にしか適用されません。

AppendChild メソッドは指定したノードをどこに配置するのかを操作しているだけで、ノードそのものを追加しているのではないようです。

この関数で作成される DXL は次の部分となります。


まとめ

「段落と文字の装飾」を例にリッチテキストフィールドを新規作成してみました。

作成するプログラムは、ノードを作成して追加する作業の繰り返しです。段落定義の pardef と 段落の par ノードの関係を理解すれば、あとは、構造通りにノードを配置するだけのパズルのようなものだとわかります。

サンプルで示したコードを見直していただきたいのですが、プログラムの流れは、

  1. NotesDOMDocumentNode からノードを新規作成
  2. 作成したノードに属性を設定
  3. 出来上がったノードを希望する位置に AppendChild する

の繰り返しです。

掲載したサンプルでは、変数ごとに色分けして見やすくしていますが、デザイナーのエディら上では同じ色で表示されます。変数名をわかりやすくしておかないと、理解しずらくなるうえ、親を取り違えるなどバグのもとにもなります。

今回のサンプルコード作成に当たっては、新規作成したノードのように一時的に利用する変数や再利用する変数は den や dtn など型だけを表す単純な名前にして、親となりうる変数は denPar, denRun や denFont のように意味の分かる基本名をつけています(命名規則については『命名規則:LotusScript (変数)』を参照)。

また、使用する変数を減らし混乱しにくくするため、サブ関数化を進めて構造化しています。

DXL のプログラミングは、コーディング能力の”素養”が一番重要な技術のような気がしてきました。昔から上司に「もっとエレガントに書け!」と指摘を受けていたので自信はありませんが...

前回 DXL Step-by-Step 次回


2024/01/23

DXL Step-by-Step:#24)サンプルコード(段落と文字の装飾②)

DXL 活用の調査・検証で、実現できたことや発見したことご紹介する『DXL Step-by-Step』シリーズの第 24 回です。前回に引き続き、段落と文字の装飾のサンプルプログラムのご紹介です。


作成するリッチテキスト

まずは、作成するリッチテキストのイメージです。サンプル然とした画像ではありますが...

段落と文字の装飾に関して紹介したすべての機能は網羅していませんが、インデント、文字色やサイズ、パーマネントペンの指定を行います。


エージェント

これまでと同様にエージェントで作成します。Initialize の構成はこれまでとほぼ同じですが、DXL 用のライブラリを Use していて、事前に準備した共通関数を使用しています。

また、保存(インポート)エラーが発生したときは DXL を出力するようデバッグ機能を付けています。

Option Declare
Use "lsDXL"

Private xns As NotesSession

Sub Initialize
   Dim dprs As NotesDOMParser
   Dim ndb As NotesDatabase

   Set xns = New NotesSession
   Set ndb = xns.CurrentDatabase

   Set dprs = xns.CreateDOMParser()
   'DXL の構築
   Call xSetDXL(dprs)

   '保存(インポート)
   If Not DXL_Import(dprs, DXLIMPORTOPTION_CREATE, False) Then
      'エラーの場合 DXL を出力
      Call Debug_SaveDXL(dprs)
   End If
End Sub


DXL 出力のメインルーチン

xSetDXL 関数が DXL を構築するメインルーチンになります。この関数ではリッチテキストフィールドを作成する部分までを行い、それより詳細なノードの構築は、目的ごとのサブ関数で実施しています。

Function xSetDXL(vdprs As NotesDOMParser)
   Dim ddn As NotesDOMDocumentNode
   Dim den As NotesDOMElementNode
   Dim denDoc As NotesDOMElementNode
   Dim denItem As NotesDOMElementNode
   Dim denRT As NotesDOMElementNode

   Set ddn = vdprs.Document

   '文書作成
   Set den = ddn.CreateElementNode("document")
   Call den.SetAttribute("form", "Doc")
   Set denDoc = ddn.AppendChild(den)

   'フィールド作成
   Set den = ddn.CreateElementNode("item")
   Call den.SetAttribute("name", "Body")
   Set denItem = denDoc.AppendChild(den)

   'リッチテキスト作成
   Set den = ddn.CreateElementNode("richtext")
   Set denRT = denItem.AppendChild(den)

   '段落定義
   Call xSetDXL_pardef(ddn, denRT)

   'テキストノード追加
   Call xSetDXL_par1_Text(ddn, denRT)

   '文字色の指定
   Call xSetDXL_par1_TextRed(ddn, denRT)

   '文字サイズと色を変更
   Call xSetDXL_par2_Size(ddn, denRT)

   'パーマネントペンの設定
   Call xSetDXL_par2_ParPen(ddn, denRT)
End Function

各サブ関数は、仕様がわかりやすくなるよう引数をそろえています。ノードの新規作成に必要となる NotesDOMDocumentNode と 親となる richtext のノードです。


段落の定義

第 20 回『pardef と par ノードの関係② インポート時』でまとめたように段落の定義である padef ノードはリッチテキストの先頭にまとめて記述しても問題ありません。そこで、今回のサンプルで使用する段落定義を一気に作成する関数 xSetDXL_pardef を作成しました。

Function xSetDXL_pardef(vddn As NotesDOMDocumentNode, vdenRT As NotesDOMElementNode)
   Dim den As NotesDOMElementNode
   Dim denPar As NotesDOMElementNode
   Dim denRun As NotesDOMElementNode

   '段落定義 id='1'
   '-------------------------
   Set den = vddn.CreateElementNode("pardef")
   Call den.SetAttribute("id", "1")

   '1 行目は 4 cm
   Call den.SetAttribute("firstlineleftmargin", DXL_CMToInch(4))

   '2 行目以降は 3 cm
   Call den.SetAttribute("leftmargin", DXL_CMToInch(3))

   '段落定義を追加
    Call vdenRT.AppendChild(den)


   '段落定義 id='2'
   '-------------------------
   Set den = vddn.CreateElementNode("pardef")
   Call den.SetAttribute("id", "2")
 
   '行間は 1.5

    Call den.SetAttribute("linespacing","1.5")

   '段落定義を追加
   Call vdenRT.AppendChild(den)
End Function

マージンの指定では、以前に作成した長さ(センチメートル)をインチの文字列に変換する関数 DXL_CMToInch を使用しています。

この関数で作成される DXL は次の部分となります。


テキストノード追加

段落にプレーンテキストを追加する場合のパターンです。

段落を表す par ノードを作成、段落定義は id 1 を設定しています。その配下のノードにテキストノードを追加しています。途中に段落内で改行する break ノードを挿入しています。

Function xSetDXL_par1_Text(vddn As NotesDOMDocumentNode, vdenRT As NotesDOMElementNode)
   Dim denPar As NotesDOMElementNode
   Dim den As NotesDOMElementNode
   Dim dtn As NotesDOMTextNode

   '段落の作成
   Set den = vddn.CreateElementNode("par")
   Call den.SetAttribute("def", "1")
   Set denPar = vdenRT.AppendChild(den)

   'プレーンテキスト(テキストノード)追加
   Set dtn = vddn.CreateTextNode("この段落はインデントをしています。")
   Call denPar.AppendChild(dtn)

   '段落内改行の追加
   Set den = vddn.CreateElementNode("break")
   Call denPar.AppendChild(den)

   'プレーンテキスト(テキストノード)追加
   Set dtn = vddn.CreateTextNode("この行は段落内で改行した2行目です。")
   Call denPar.AppendChild(dtn)
End Function

この関数で作成される DXL は次の部分となります。


文字色の指定

文字色を指定するには font ノードが必要でした。そして、適用する範囲を設定するために run ノードで括る必要がありましたね。以下のコードでは par、run の順で階層化したノードを作成し、その配下に font とテキストノードを作成しています。 

Function xSetDXL_par1_TextRed(vddn As NotesDOMDocumentNode, vdenRT As NotesDOMElementNode)
   Dim denPar As NotesDOMElementNode
   Dim denRun As NotesDOMElementNode
   Dim den As NotesDOMElementNode
   Dim dtn As NotesDOMTextNode

   '段落の作成
   Set den = vddn.CreateElementNode("par")
   Call den.SetAttribute("def", "1")
   Set denPar = vdenRT.AppendChild(den)

   '範囲の作成
    Set den = vddn.CreateElementNode("run")
   Set denRundenPar.AppendChild(den)

   '文字装飾の追加
   Set den = vddn.CreateElementNode("font")
   Call den.SetAttribute("color", "red")
   Call denRun.AppendChild(den)

   'プレーンテキスト(テキストノード)追加
   Set dtn = vddn.CreateTextNode("同じ段落スタイルですが赤字で表示します。")
   Call denRun.AppendChild(dtn)
End Function

font ノードには色を設定する color 属性を追加し、定義済みの色である red を指定しています。

この関数で作成される DXL は次の部分となります。


続きは次回

まだ、すべてのサブ関数を紹介していないのですが、長くなったので続きの文字サイズの設定とパーマネントペンは次回とします。

前回 DXL Step-by-Step 次回


2024/01/21

DXL Step-by-Step:#23)サンプルコード(段落と文字の装飾①)

DXL 活用の調査・検証で、実現できたことや発見したことご紹介する『DXL Step-by-Step』シリーズの第 23 回です。第 14 回から前回まで、段落に関する DXL の調査結果をまとめてきました。解説ばかりだとつまらないので、この間の復習を兼ねて、サンプルプログラムを作りたいと思います。


共通関数の準備

第 17 回『段落の定義② 余白の設定』で、DXL 用のライブラリ lsDXL を新規作成しました。そろそろサンプルコードが長くなってきますので、共通で利用できる関数は、このライブラリに集約しようと思います。

lsDXL ライブラリでは、インターフェースを明確にするため、外部からアクセスさせたい関数だけを Public 宣言する前提としています。


◇ 共通変数

まずはライブラリ全般の準備として以下のコードを追加します。

Option Declare
Private xns As NotesSession

Sub Initialize
   'ライブラリのプライベート変数の初期化
   Set xns = New NotesSession
End Sub

NotesSession のオブジェクトは、さまざまなシーンで使用しますし、値が変化しないので、ライブラリ内で共通の変数としています。


◇ DXL の保存(インポート)

DXL をノーツオブジェクトとして保存する関数です。

これまで第 4 回『文書の更新』では文書として保存する関数、第 10 回『イメージリソースの新規作成』では設計要素を保存する関数として登場した xImportDXL 関数です。

汎用的な関数となるよう、作成するドミノオブジェクトが ”設計” or ”文書” なのかを引数で指定するようにしています。また、保存エラーがあった場合、エラーメッセージを表示して、False を返すようにしました。

Public Function DXL_Import(vdprs As NotesDOMParser, ByVal viOption As Integer, ByVal vbIsDesign As Boolean) As Boolean
   Dim nst As NotesStream
   Dim ndb As NotesDatabase
   Dim dimp As NotesDXLImporter

   On Error GoTo Err_Proc

   'DXL の抽出準備
   Set nst = xns.CreateStream()
   Call vdprs.SetOutput(nst)
   Call vdprs.Serialize()

   '保存(インポート)
   Set ndb = xns.CurrentDatabase
   Set dimp = xns.CreateDXLImporter()
   If vbIsDesign = True Then
      '設計の保存
      dimp.DesignImportOption = viOption
   Else
      '文書の保存
      dimp.DocumentImportOption = viOption
   End If

   'DXL の保存
   Call dimp.Import(nst.ReadText(), ndb)
   DXL_Import = True

Exit_Proc:
   Exit Function

Err_Proc:
   MsgBox Error$, 16, "DXL_Import"
   DXL_Import = False

   Resume Exit_Proc
End Function


◇ デバッグ用の関数

最後に万一 DXL の保存(インポート)でエラーが発生した場合に、保存しようとした DXL を出力できるよう、デバッグ用の関数を準備します。

元となるのは、第 6 回『エージェント(設計要素)の DXL』で登場した xSaveDXL 関数です。デバッグ用ということで、関数名は Debug_SaveDXL としています。

Public Function Debug_SaveDXL(vdprs As NotesDOMParser) As Boolean
   Dim ndb As NotesDatabase
   Dim nd As NotesDocument
   Dim nrti As NotesRichTextItem

   Set ndb = xns.CurrentDatabase
   Set nd = ndb.CreateDocument()
   nd.Form = "DXL"

   Set nrti = nd.CreateRichTextItem("Body")
   Call nrti.AppendText(xGetDXL(vdprs))

   Debug_SaveDXL = nd.Save(True, False)
End Function

Function xGetDXL(vdprs As NotesDOMParser) As String
   Dim nst As NotesStream

   Set nst = xns.CreateStream()
   Call vdprs.SetOutput(nst)
   Call vdprs.Serialize()

   xGetDXL = nst.ReadText()
End Function

なお、サブ関数の xGetDXL はそのまま変更せずに移設しました。

前回 DXL Step-by-Step 次回


2024/01/19

DXL Step-by-Step:#22)文字の装飾

DXL 活用の調査・検証で、実現できたことや発見したことご紹介する『DXL Step-by-Step』シリーズの第 22 回です。 今回は、段落内に配置されるオブジェクトの中からテキストについてまとめます。


文字の装飾 と font ノード

文字サイズや太字や斜体などの装飾を変化させた文字を 1 つの段落内に配置するサンプルを作成してみました。

この文書を DXL に変換すると次のようになります。

まず、大前提として、文字の装飾が指定されていない部分である "の" や "です" は par ノード直下にテキストノードとして存在ます。装飾が指定されている部分については同じ装飾が指定されている範囲を run ノードで括り、そのサブノードとして font ノードとテキストノードが存在します。そして、装飾は font ノードの属性で指定されています。

この構造さえ理解できれば、 font ノードの属性を指定するだけで、自由に文字を装飾できることになります。


文字のサイズ

文字サイズを指定するには size 属性でポイント数を指定します。設定できる範囲は、プロパティボックスの設定では、フォントサイズは 1 ~ 250 までの値がセットできます。確認する限り、範囲外のサイズを指定しても保存(インポート)時にエラーにはならないようですが、指定したサイズで表示されないようです。

設定 属性設定値
サイズ size ポイントを整数で指定('1pt' 以上、'250pt' 以下)。
(なし) 指定しない場合、10 ポイント。

また、size 属性を設定しない場合、10 ポイントとして取り扱われるようです。ためしにフォームでリッチテキストのサイズを 24 ポイントにして、size を指定せずにインポートしたところ、10 ポイントで表示されました。指定しない場合、フォームのフィールドのフォントにゆだねるというわけではなさそうです。


文字のスタイル

太字や斜体などの装飾の設定です。代表的な 4 種のみ記載しています。複数のスタイルをセットする場合、スペース区切りで指定します。

設定 属性設定値
太字 style 'bold'
斜体 'italic'
下線 'underline'
取消線 'strikethrough'


文字の色

色の指定を行う属性は color となっています。設定法については下表のとおり 2 種類あります。

設定 属性設定値
文字色 color 定義済みの 16 色については文字列で指定。
'red' や 'purple' など(下表参照)。
RGB を 2 桁の 16 進数で指定。
先頭に # をつけ '#8242ff' のように記述。

プロパティボックスで文字の色を設定する際の上部にある 16 色が定義済みの色です。

DXL で指定できる色名は、それぞれ以下の通りです(画像と同じ順)。

white yellow lime aqua blue fuchsia red silver
black olive green teal navy purple maroon gray

なお、何も指定しない場合は 黒 となるのですが、'black' と指定しても 黒 となるようです。


フォントの指定

ノーツは一般にデフォルトフォントを呼ばれる 4 種類のフォントを使用します。デフォルトフォントは『Notes クライアントの基本設定』でクラアインと PC 内の実際のフォントにマッピングする仕組みとなっていて、クライアントごとのフォントの違いを吸収しやすいように作られています。

もちろん、デフォルトフォント以外のフォントもダイレクトに指定できます。例えば、リッチテキストに次のようにフォントをセットして DXL に変換してみます。

結果は次のようになりました。

まず、フォント名の指定は name 属性で指定することがわかります。そして、デフォルトフォントでない場合には、pich や truetype など複数の属性が付加されていることがわかります。これら属性の役割は現時点で不明ですが、name 以外の属性を省いた DXL をインポートしたところ正しくフォントが反映されました。フォントは name 属性さえ指定すればとりあえず OK ということなのでしょう。

設定 属性設定値
Default Sans Serif name 属性を作成しない
Default Serif 'serif'
Default Monospace 'monospace'
Default Multilingual 'multilingual'
その他フォント フォント名を直接指定


パーマネントペン

リッチテキストには文字を強調するため、蛍光ペンでマーキングしたように背景色を設定する機能があり、パーマネントペンと呼びます。

今回初めて利用したのですが、パーマネントペンには 3 色の設定があるようで、DXL では次のように表現されました。

パーマネントペンペンの設定は run ノードの属性となっている点に注意が必要です。操作的には文字の装飾と同等のように感じるのですが、DXL 的には少し違うようです。難しいですね...

設定属性設定値
黄色highlight'yellow'
ピンク'pink'
'blue'


まとめ

今回は、リッチテキスト内の文字の装飾と DXL の関係についてまとめました。

run というノードで括りその範囲に対して文字の装飾を font ノードとその属性で詳細に指定するという点がポイントですね。

前回 DXL Step-by-Step 次回


2024/01/17

DXL Step-by-Step:#21)段落内に入るオブジェクト

DXL 活用の調査・検証で、実現できたことや発見したことご紹介する『DXL Step-by-Step』シリーズの第 21 回です。

近い将来、DXL を利用したサンプル DB の公開の計画があり、そこで使用する機能までは記事にしておきたいと、この連載を連投しています。もうしばらく DXL ネタが続きますが、ご了承ください。また、サンプル DB が公開されましたら改めて紹介記事を投稿いたします。

さて、前回までは段落を表す par ノードの定義について数回にわたってまとめました。要は段落全体の書式設定に当たる部分でした。今回からは、par ノードの中身、段落内のコンテンツがどのように表現されるかについてまとめます。


サンプルと DXL

サンプルデータとしてリッチテキストに次のようなデータを入力した文書を作成してみました。

文字だけでなく、イメージリソースや URL リンクなどを配置しています。なお、各行は Shift + Enter で改行しており、全体が一つの段落となるようにしています。

この文書を DXL に変換すると、リッチテキストフィールドは次のように表現されます。

まず、par ノードは1つしかありませんので、段落が 1 つであることがわかりますね。

そして par ノードの中には、入力した文字やさまざまなサブノードが作成されていることが確認できます。このように、各種ノードを順に配置することにより、段落内に柔軟にオブジェクトを配置できる仕組みとなっています。

では、各サブノードを順に確認しましょう。


テキスト

最初は文字(テキスト)です。DXL の以下の部分です。

入力した文字がそのまた羅列されているただの文字列ですが、DXL では、これもノードとして取り扱われます。NotesDOM クラスでは、NotesDOMTextNode で扱われます。タグで挟まれていないのが特徴ですね。


段落内の改行

次は Shift + Enter で入力する段落内の改行です。ノードは次の通り "<break />" となります。


画像

画像は <picture> タグで表されます。属性で画像のサイズを指定しています。また、サブノードで表示する画像を指定しています。今回はイメージリソースなので、その名称を指定されていることがわかります。

画像の横には『← 左の画像はイメージリソースです』と表示していました。この文字列が <picture> タグに続き、テキストノードとして出力されています。このような構造となることで画像の横に文字列(テキスト)が配置できています。


文字の装飾

次は太字や色の変更を行う文字の装飾です。まず、<run> というタグで設定する範囲を決定し、サブノードとして装飾の設定 <font> タグとテキストノードが存在します。

<run> というタグ名からこの機能が想像できないので、辞書で run という単語を調べてみたところ、『[範囲などが]及ぶ、広がる』という意味があるようです。私は英語は苦手なのですが、きっとこれが理由なのでしょうね...


URL リンク

最後の例は、URL リンクです。以下の赤枠の部分が URL リンクの DXL です。URL は href 属性で表されていますね。また、リンクの文字列はテキストノードとなっていますが、装飾を指定するため <run> ノードで括られています。

URL の前後には、リンクではない文字列を配置していました。これらが、<urllink> タグの前後に存在します。ここまでの例を総合すると”なるほど”という感じですね。


まとめ

段落 <par> ノードの中に配置されるサブノードを事例とともに紹介しました。どのような構造でリッチテキスト内のコンテンツ(オブジェクト)が管理されいるのか概要がつかめたかと思います。

今回は概要をつかむことが目的だったので、各オブジェクトのノード名を紹介する程度の解説にとどめました。 今後はそれぞれのオブジェクトについて掘り下げたいと思います。

前回 DXL Step-by-Step 次回


2024/01/15

DXL Step-by-Step:#20)pardef と par ノードの関係② インポート時

DXL 活用の調査・検証で、実現できたことや発見したことご紹介する『DXL Step-by-Step』シリーズの第 20 回です。前回に引き続き、pardef と par ノードの関係の調査なのですが、今回は、テスト的に手書きした DXL を文書としてインポート(保存)させ、より詳しく条件を調査します。


定義位置のテスト

padef の定義の前に id を使用した場合のテストです。次のように、pardef の前後にその礼儀を使用した段落 par を配置してみました。

作成した文書は次の通りで、1行目には行間がセットされず、2~3行目は正しくセットされています。この結果より、pardef の定義は使用する前に設定しないと無視されるようです。

ちなみに、作成した文書をもう一度 DXL に変換すると次のようになりました。1行目の前に pardef ノードが挿入され、id が再付番されています。

この結果より、DXL で記述した通りに保存されるのではなく、ドミノオブジェクトとして正しい状態に調整して保存していること、id は関連付けが目的で番号自体に意味はないことがわかりますね。


定義位置と id

続いては複数の実験をまとめて行います。テスト項目は次の3点です。

  1. pardef の定義は直前である必要があるか?
  2. pardef は使用する順で定義しなければならないか?
  3. id は 1 から連番で付与する必要があるか?

テストする DXL は次の通りです。

この DXL はエラーもなくインポートでき、正常に2~3行目だけ行間が設定されました。

pardef は先頭にまとめても正常に動作するんですね。まとまっているほうが、見やすいですし、書式の種類の確認など簡単になると思うんですけどね...


複数フィールドと id

最後に複数のリッチテキストがある場合についてテストします。前回の確認では、既存文書を DXL に変換すると次のような変わった仕様が確認できました。

  • pardef の定義はフィールドごと
  • id は文書内でユニーク

これが必須なのか確認するため次のような DXL を作成してみました。各フィールドで同じ id を設定しています。

インポートは正常に終了し、各フィールドとも行間は正しく設定されていました。この結果より、フィールド内で整合性が正しければ正常にインポートできることが確認できました。


まとめ

pardef と par の関係を2回にわたって調査しました。その結果をまとめると次のようになります。インポートでは、今回の実験で最低限守ればよい条件を記述しています。


エクスポート インポート
pardef 初回使用の par ノードの直前 使用前に定義すればよい
先頭にまとめてもかまわない
id 付番 文書内で連番 フィールド内でユニークであれば連番でなくてもよい
定義の重複 同じスタイルを複数の pardef で定義しても問題なし

DXL を利用してリッチテキストを含む文書を作成する場合、pardef と par ノードを正しく記述できないと、希望通りのフォーマットで表現できません。

ただ、今回のテストで、思った以上におおらかな仕様であることがわかりました。エクスポートと同じ仕様で DXL を自作するなら大変そうですが、今回の実験で得た最低限の条件を守るだけなら少し楽ができそうですね。

前回 DXL Step-by-Step 次回


2024/01/13

DXL Step-by-Step:#19)pardef と par ノードの関係①

DXL 活用の調査・検証で、実現できたことや発見したことご紹介する『DXL Step-by-Step』シリーズの第 19 回です。リッチテキストの構造を理解する上で一番不明瞭と思われる pardef と par ノードの関係について整理します。


pardef と par ノードとは

まずはおさらいです。#15)リッチテキストを構成する基本要素 で、これらノードの役割を紹介しました。

  • pardef ノードは段落のスタイルを定義
  • par ノードは段落のコンテンツを定義
  • par ノードに適用されるスタイルは、def 属性に pardef の id で指定

上記 DXL を例にすると、段落スタイル(pardef ノード)の id は '1' と '2' の 2 種類が定義されいいます。コンテンツ(par ノード)で、def='1' のなっている行は '1'、def='2' のなっている行は '2' の段落スタイルが適用されます。リッチテキスト内で同じスタイルを複数回使用する場合、事前に定義した id を指定するだけでよく、記述が簡素化できるようになっています。

また、pardef による定義は、par ノードで使用する前に定義しておく必要があるようです。


なお、入力の仕方にもよるのですが、スタイルの id が再利用される場合(def='1')とされない場合(def='3')がありました。同じスタイルを複数の id に定義することができるようです。そして、id の '1' は必ずしも、何も設定されていない <pardef id='1' /> に限定されているわけではなく、属性が設定されることもあるようです。


複数のフィールドの場合

3つのリッチテキストフィールドを持つフォームを作成し、それぞれに同じ段落スタイルで文字を入力した文書を作成してテストします。

これを DXL で出力すると次のようになりました。

この結果より、pardef による定義はリッチテキストごとに実施する必要があることがわかります。ところが、id の付番については文書内でユニークとなるようです。なかなか複雑?不思議?な仕様ですね。


次回の予告

今回は既存文書を DXL で出力させ、pardef と par ノードの関係を調査しました。結果、さまざまな条件や仕様が見えてきました。次回はこれらが必須条件なのか確認するため、テストの DXL を文書としてインポート(保存)させる実験を行います。


前回 DXL Step-by-Step 次回


2024/01/11

DXL Step-by-Step:#18)段落の定義③ インデント

DXL 活用の調査・検証で、実現できたことや発見したことご紹介する『DXL Step-by-Step』シリーズの第 18 回です。前々回からまとめている段落の書式を定義する pardef ノードに関してです。今回はインデントの設定を紹介します。


インデントの設定

段落の設定で最初の行を字下げすることをインデント、その逆でほかの行よりも左に出すことをアウトデントと言います。ノーツのプロパティボックスでいると以下の設定ですね。

ショートカットキーでは、インデントが F7、Shift + F7 がアウトデントの設定になります。私はプロパティボックスを使用するより、左余白を操作する F8、Shift + F8 とあわせて、キーボード操作で行うことが多いです。

また、より詳細な位置設定をする場合には、ルーラを使用します。▼ がインデント、▲ が左余白の設定となります。ちょっと小さくてドラッグしにくいですが、視覚的に設定できて便利ですよね。


では、以下のように設定したリッチテキストを DXLで出力してみます。1つ目の段落がインデント、2つ目の段落がアウトデントの設定をしています。


出力した DXL のリッチテキスト部分は次の通りです。


firstlineleftmargin という属性が出力されています。その名の通り、1行目の左マージンの設定です。前回登場した leftmargin 属性と組み合わせて、leftmargin < firstlineleftmargin ではインデント、leftmargin > firstlineleftmargin ではアウトデントとなるということですね。


この属性の設定についてまとめると次の通りとなります。

設定 属性設定値
最初の行 firstlineleftmargin 1行目の左マージンインチで指定('0in' 以上)。
2行目以降は leftmargin 属性で設定。
設定がない場合、すべての行が leftmargin でそろう。


pardef ノード まとめ

第 16 回 から 3 回にわたって  pardef ノードの属性について整理しました。

pardef ノードは、段落の書式を定義するためのノードで、行間や文字揃え余白の設定、インデントの設定を紹介しました。そのほかにも、リスト(箇条書き)やタブ位置の設定も pardef  ノードの役割となっています。

まだ紹介していない属性は、別途まとめるとして、話を先に進めたいと思います。次回は、pardef ノードと par ノードの関係について、実験結果をまとめます。


前回 DXL Step-by-Step 次回