DXL 活用の調査・検証で、実現できたことや発見したことご紹介する『DXL Step-by-Step』シリーズの第 10 回です。
イメージリソース(設計要素)の読み込みについて、第 8 回、第 9 回 で紹介しました。今回は、イメージリソースを新規作成する方法についてまとめます。
DXL を利用すれば、設計要素も新規作成できるようになります。これは、通常の NotesObjectClass だけではできないことなので DXL で Notes アプリの可能性が広がる部分となりますね。
Base64 のエンコード
DXL 内の画像データは、Base64 でエンコードされていました。今回は、イメージリソースに画像データを渡すことになるので、画像データ(バイナリファイル)を Base64 でエンコードされた文字列に変換する必要があります。
前回紹介したデコードと同じく OpenNTF の LotusScript Gold Collection プロジェクトに関数がありました。次のようなコードです。
%REM Function StreamToBase64 Description: Convert a binary NotesStream to a string of Base64 data. The output can be used as part of DXL data for importing. %END REM Function StreamToBase64(streamIn As NotesStream) As String On Error GoTo theOldWay ' ReadEncoded function is not documented. In case it doesn't work have a backup. StreamToBase64 = Replace(streamIn.ReadEncoded(ENC_BASE64, 76), Chr$(13), "") Exit Function theOldWay: Dim session As New NotesSession Dim db As NotesDatabase Dim doc As NotesDocument Dim mime As NotesMIMEEntity Set db = session.CurrentDatabase Set doc = db.CreateDocument Set mime = doc.CreateMIMEEntity("Body") streamIn.Position = 0 Call mime.SetContentFromBytes(streamIn, "image/gif", ENC_NONE) mime.EncodeContent(ENC_BASE64) StreamToBase64 = Replace(mime.ContentAsText, Chr$(13), "") End Function |
この関数は、なかなか興味深いですね。
コード内のコメントにも記載がありますが、ReadEncoded というヘルプに記載のないメソッドを使用しています。確かに最新の 12.0.2 のデザイナーヘルプを見ても NotesStream クラスにそのようなメソッドは記載されていません。この OpenNTF のプロジェクト、きっと、Notes/Domino 開発の ”中の人” かその周辺の方の業物なのでしょうね...
そして、この関数には保険がかかっています。万一このメソッドでエラーが発生した場合に備えて、エラー処理の中(theOldWay)に Plan B が記述されています。こちらは、デコードと同様の方法で実現されており、NotesMIMEEntity クラスを活用して変換しています。
サンプルプログラム
上記関数を利用しながら、イメージリソースを新規作成します。次のようなプログラムを作成しました。
まず、メインルーチンです。DXL をコントロールするために NotesDOMParser のオブジェクトを作成し、これに DXL をセットする xSetDXL 関数と 設計要素としてを保存する xImportDXL 関数をコールしています。
Sub Initialize Dim dprs As NotesDOMParser Dim ndb As NotesDatabase Set xns = New NotesSession Set ndb = xns.CurrentDatabase Set dprs = xns.CreateDOMParser() Call xSetDXL(dprs, "d:\denaoshi.png", "denaoshi2.png") Call xImportDXL(dprs, DXLIMPORTOPTION_CREATE) End Sub |
次はイメージリソースの DXL を生成するための xSetDXL 関数です。作成する DXL は最低限のタグだけとしています。まず、画像ファイルを NotesStream で開き、それを Base64 の文字列に変換して、<png> タグを作成しています。
Function xSetDXL( _ vdprs As NotesDOMParser, _ ByVal vsFilePath As String, _ ByVal vsResourceName As String) Dim ddn As NotesDOMDocumentNode Dim denNew As NotesDOMElementNode Dim denDoc As NotesDOMElementNode Dim denItem As NotesDOMElementNode Dim dtnNew As NotesDOMTextNode Dim nst As NotesStream '画像ファイルを開く Set nst = xns.CreateStream() Call nst.Open(vsFilePath) 'イメージリソースのエレメント作成 Set ddn = vdprs.Document Set denNew = ddn.CreateElementNode("imageresource") Call denNew.SetAttribute("name", vsResourceName) Set denDoc = ddn.AppendChild(denNew) '画像イメージの追加 '-------------------- Set denNew = ddn.CreateElementNode("png") Set denItem = denDoc.AppendChild(denNew) '画像データセット Set dtnNew = ddn.CreateTextNode(StreamToBase64(nst)) Call denItem.AppendChild(dtnNew) Set denNew = ddn.CreateElementNode("text") 'フィールドの追加 '-------------------- '$FileSize Call xAppendField(ddn, "$FileSize", nst.Bytes) '$MimeType Call xAppendField(ddn, "$MimeType", "image/png") End Function |
その後必要なフィールドである $FileSize と $MimeType を作成しています。ファイルサイズは、NotesStream クラスの Bytes プロパティで取得しています。これは便利ですね。
フィールドを作成する関数は次の通りです。第 4 回 で紹介したフィールドを作成する関数 xAppendField_Text を少し改造し、テキストに限らず数値でも利用できるようにしました。具体的には、セットする値 vvValue を Variant 型に変更し、関数内で型をチェックして、型に合わせたタグを生成し、値をセットしています。
Function xAppendField( _ vddn As NotesDOMDocumentNode, _ ByVal vsFldName As String, _ ByVal vvValue As Variant) As Boolean Dim sType As String '型判定 If IsArray(vvValue) Then '配列は未対応 Else If TypeName(vvValue) = "STRING" Then sType = "text" If TypeName(vvValue) = "INTEGER" Then sType = "number" If TypeName(vvValue) = "LONG" Then sType = "number" If TypeName(vvValue) = "SINGLE" Then sType = "number" If TypeName(vvValue) = "DOUBLE" Then sType = "number" End If If sType = "" Then Exit Function '未対応のため中断 'document ノード取得 Dim denCur As NotesDOMElementNode Set denCur = vddn.DocumentElement 'item ノード作成とフィールド名の指定 Dim denNew As NotesDOMElementNode Set denNew = vddn.CreateElementNode("item") Call denNew.SetAttribute("name", vsFldName) Set denCur = denCur.AppendChild(denNew) '値のノードと値のセット Dim dtnNew As NotesDOMTextNode Set denNew = vddn.CreateElementNode(sType) Set denCur = denCur.AppendChild(denNew) Set dtnNew = vddn.CreateTextNode(CStr(vvValue)) Call denCur.AppendChild(dtnNew) End Function |
日付や配列にはまだ対応できていませんので、実用化するにはまだ改善が必要ですね。
最後は DXL を設計要素として保存する関数です。第 4 回 で文書を保存する関数として紹介した xImportDXL とほぼ同様なのですが、今回は設計要素なので DesignImportOption プロパティを使用しています。
Function xImportDXL(vdprs As NotesDOMParser, ByVal viOption As Integer) As Boolean 'DXL の抽出準備 Dim nst As NotesStream Set nst = xns.CreateStream() Call vdprs.SetOutput(nst) Call vdprs.Serialize() '保存(インポート) Dim ndb As NotesDatabase Dim dimp As NotesDXLImporter Set ndb = xns.CurrentDatabase Set dimp = xns.CreateDXLImporter() dimp.DesignImportOption = viOption Call dimp.Import(nst.ReadText(), ndb) End Function |
今回は設計要素の新規作成ですのでこの viOption には、DXLIMPORTOPTION_CREATE が指定されています(この関数をコールしているメインルーチンを参照)。
実行結果
このプログラムを実行すると次のように設計要素が作成されます。
前回 | DXL Step-by-Step | 次回 |
0 件のコメント:
コメントを投稿