Notes開発者のためのXPagesデザインレシピ

簡単でCoolなXPagesアプリケーションを作るための情報を発信していきます

Notesクライアント

NotesビューにYoutubeAPIから取得したサムネイルを表示したい(後編)

はじめに

 前編では、YoutubeAPIから取得したレスポンスを文書に登録することところまでできました。今回は本題であるサムネイル画像の取得とイメージリソースへの保存、ビューへの表示をやっていきます。 LotusScriptにはイメージリソースを操作する関数やクラスは用意されていませんが、DXL(Domino XML Language)を拡張することでイメージリソースの登録、削除が実装できるようになります。

DXL(Domino XML Language)って何?

 DXL(Domino XML Language)は、ノーツ文書やノーツの設計要素をXMLとして出力、入力する機能です。例えばビューの設計を出力→変更→入力することで、ビューの色やフォントなど変えることができます。(頑張れば、既存の設計をなしにLotusScriptソースのみから設計要素を作成することもできます。)

【DXLとは】

  1. Dominoの文書や設計要素を、XMLフォーマットで出力したもの
  2. Domino文書型定義(Domino DTD)のタグ定義に従って出力される
  3. LotusScriptを使ってインポート、エクスポートができる
  4. NotesR6から利用可能

【参考】DXLを使ってビューをコピーする

 DXLのサンプルとして、ビューの設計をコピーし、ビューの背景色を変更、新規ビューとして登録してみます。属性は一つ一つ調べる必要がありますが、スタイルシートのプロパティに近いものなので、HTMLやCSSを学んだことがある方は容易に理解出来ると思います。

【ソース】

Sub Click(Source As Button)
	'---------- ---------- ---------- ---------- ---------- 
	' ビューをDXLにエクスポート、背景色を変更、新しいビューとしてインポート
	'---------- ---------- ---------- ---------- ---------- 
	Dim session		As New NotesSession
	Dim db				As NotesDatabase
	Dim vw				As NotesView
	Dim d_doc			As NotesDocument		'NotesViewの設計Document
	Dim dxlExp			As NotesDXLExporter
	Dim domParser		As NotesDOMParser
	Dim domNode		As NotesDOMDocumentNode
	Dim domElm		As NotesDOMElementNode
	Dim dxlImp			As NotesDXLImporter
	Dim stream			As NotesStream
	
	Dim sUnid			As String					'NotesViewのUNID
	Dim iRet			As Integer					'Msgbox戻り値
	
	Set db			= session.CurrentDatabase
	Set vw			= db.GetView("ApiSettingVw")
	sUnid			= vw.UniversalID						'NotesViewのUNIDを取得
	Set d_doc		= db.GetDocumentByUNID(sUnid)		'NotesViewのDocumentを取得
	
	'実行確認
	iRet = Msgbox("このボタンはDXLでビューをコピーするサンプルです。" & Chr(13) _
	& "実行結果はDominoDesignerで確認してください。" & Chr(13) & "実行しますか?",1+16,"確認")
	If iRet <> 1 Then
		Exit Sub
	End If
	
	'DXLのエクスポート
	Set dxlExp		= session.CreateDXLExporter
	Call dxlExp.SetInput(d_doc)								'ViewのDXLを取得
	
	'DXL編集
	Set domParser	= session.CreateDOMParser()
	Call domParser.SetInput(dxlExp)						'DXLを展開						'
	Call dxlExp.Process
	
	Set domNode 	= domParser.Document
	Set domElm	= domNode.DocumentElement			'DXLからViewの属性にアクセス
	Call domElm.SetAttribute("name","API設定2")
	Call domElm.SetAttribute("alias","ApiSettingVw2")
	Call domElm.SetAttribute("bgcolor","red")
	
	'DXLのインポート
	Set stream		= session.CreateStream()
	Call domParser.SetOutput(stream)						'DOMParserの出力先を指定
	Call domParser.Serialize								'DXLをStreamに出力
	Set dxlImp		= session.CreateDXLImporter
	dxlImp.DesignImportOption = 2							'2-新規追加、5-更新
	dxlImp.DocumentImportOption = 2						'2-新規追加、5-更新
	Call dxlImp.Import(stream,db)							'設計にインポート
	
	Msgbox "Done."
End Sub

YoutubeAPIを使ってサムネイル画像をローカルにダウンロードする

 さて本題に戻ります。YoutubeAPIのレスポンスから抽出したサムネイルURLからバイナリを取得し、画像として保存するサンプルコードを書いてみます。バイナリの保存は「ADODB.Stream」を使用します。NotesStreamクラスを使っても保存できるのですが、サムネイル画像が64Kを超えるとエラーが出ますので念のため「ADODB.Stream」を使います。

【ソース】

Sub Click(Source As Button)
	'---------- ---------- ---------- ---------- ---------- 
	'サムネイル画像のパスを指定し、取得したバイナリを画像として保存
	'ADODB.Streamを使用(64k制限なし)
	'---------- ---------- ---------- ---------- ---------- 
	
	Const TMPPATH		= "C:\tmp\"						'画像の一時保存フォルダ
	
	Dim sUrl			As String			'サムネイル画像URL
	Dim sFileName		As String			'サムネイル画像名
	Dim xml			As Variant			'MSXML2オブジェクト
	Dim fileStream		As Variant			'ADOストリームオブジェクト
	Dim sTmpFilePath	As String			'サムネイル画像保存パス
	
	sUrl		= "https://i.ytimg.com/vi/6EKg0SpHflE/default.jpg"
	sFileName	= "6EKg0SpHflE.jpg"
	
	'HTTP リクエストの実行
	Set xml = CreateObject("MSXML2.ServerXMLHTTP.6.0")
	xml.Open "GET", sUrl, False
	xml.send ""	
	
    ' HTTPステータスコードが200の場合 (成功) のみファイルを保存します
	If xml.Status = 200 Then		
		Set fileStream = CreateObject("ADODB.Stream")
		
		fileStream.Type = 1 ' バイナリ形式
		fileStream.Open
		fileStream.Write xml.responseBody					' レスポンスボディをStreamに書き込み
		sTmpFilePath	= TMPPATH & sFileName			'サムネイル保存パス
		fileStream.SaveToFile sTmpFilePath, 2				'Streamをファイルとして保存
		fileStream.Close									'Streamをクローズ
		Set fileStream = Nothing	
	Else
		Msgbox "HTTPリクエストが失敗しました。ステータスコード"
	End If
	
	Set xml = Nothing	
	
	'完了メッセージ表示	
	Msgbox "Done!"	
	
End Sub

LotusScriptのDXLでイメージリソースを登録する関数

 大阪研究会の浜さんに作成して貰ったスクリプトライブラリの関数一覧がこちらです。たくさんの関数が定義されていますが、利用するのは下記の3つだけです。

  • ImageResource_New    :イメージリソースの登録
  • ImageResource_Remove    :イメージリソースの削除
  • InlineImage_Replace    :リッチテキストフィールドへのイメージリソース表示

 これらの関数を作成するにはかなり試行錯誤が必要です。でも、安心して下さい。許可を頂き、最後の方でこのライブラリを含む設計公開NTFダウンロードリンクを配置しています。

YoutubeAPIから取得したサムネイル画像をイメージリソースに登録する

 上記関数を使って、ローカルに保存したサムネイル画像をイメージリソースに保存後、削除するコードを書いてみます。ここまでできれば「前編」のソースと合わせてYoutubeAPIからレコード、サムネイル画像を取得し、文書とイメージリソースに登録するLotusScriptは書けるかと思います。

【ソース】

Option Declare
Use "DXL_Tiny"

Sub Click(Source As Button)
	'---------- ---------- ---------- ---------- ---------- 
	'サムネイル画像のパスを指定し、取得したバイナリを画像として保存後、ImageResourceに登録
	'ADODB.Streamを使用(64k制限なし)
	'---------- ---------- ---------- ---------- ---------- 
	
	Const TMPPATH		= "C:\tmp\"						'画像の一時保存フォルダ
	
	Dim sUrl			As String			'サムネイル画像URL
	Dim sFileName		As String			'サムネイル画像名
	Dim xml			As Variant			'MSXML2オブジェクト
	Dim fileStream		As Variant			'ADOストリームオブジェクト
	Dim sTmpFilePath	As String			'サムネイル画像保存パス
	
	sUrl		= "https://i.ytimg.com/vi/6EKg0SpHflE/default.jpg"
	sFileName	= "6EKg0SpHflE.jpg"
	
	'HTTP リクエストの実行
	Set xml = CreateObject("MSXML2.ServerXMLHTTP.6.0")
	xml.Open "GET", sUrl, False
	xml.send ""	
	
    ' HTTPステータスコードが200の場合 (成功) のみファイルを保存します
	If xml.Status = 200 Then		
		Set fileStream = CreateObject("ADODB.Stream")
		
		fileStream.Type = 1 ' バイナリ形式
		fileStream.Open
		fileStream.Write xml.responseBody					' レスポンスボディをStreamに書き込み
		sTmpFilePath	= TMPPATH & sFileName			'サムネイル保存パス
		fileStream.SaveToFile sTmpFilePath, 2				'Streamをファイルとして保存
		fileStream.Close									'Streamをクローズ
		Set fileStream = Nothing
		
		'ImageResourceに登録
		Call ImageResource_New("tmpimage", sTmpFilePath)
		
		'一時フォルダのサムネイルを削除
		If Not Dir$(sTmpFilePath,0) = "" Then
			Kill sTmpFilePath			
		End If
		
	Else
		Msgbox "HTTPリクエストが失敗しました。ステータスコード"
	End If
	
	Set xml = Nothing	
	
	'完了メッセージ表示	
	Msgbox "Done!"	
	
End Sub

サムネイルを表示するビューの開発

 Notesビューではサムネイル画像の高さに応じて高さを変更することはできないため、行の高さを「4行」に設定します。

文書の削除時にイメージリソース内のサムネイル画像を削除する

 これでYoutubeAPIから取得したレコードを使って、文書を登録、ビューにサムネイルを表示するプログラムを作ることができました。実運用するには文書を削除した際に、関連するイメージリソースも消えて欲しいです。そこで「データベーススクリプト」の「Postdocumentdelete」イベントで削除対象文書に関連するイメージリソースを削除するコードを書きます。

【ソース】

Sub Postdocumentdelete(Source As Notesuidatabase)
	
	On Error Goto ErrRtn
	
	'---------- ---------- ---------- ---------- -----------
	'文書が削除される前にImageResourceを削除する
	'引数	:Source-現在のUIデータベース	
	'---------- ---------- ---------- ---------- -----------
	
	'クラス・変数宣言
	Dim db				As NotesDatabase
	Dim dc				As NotesDocumentCollection
	Dim doc			As NotesDocument
	
	Dim sResourceName	As String					'削除対象リソース名
	
	'クラス、変数セット
	Set db				= Source.Database
	Set dc				= Source.Documents			'削除対象文書のCollectionを取得
	
	'削除対象文書がなくなるまでループ
	Set doc		= dc.GetFirstDocument
	While Not(doc Is Nothing)
		sResourceName	= doc.ThumbnailIcon(0)
		
		Call ImageResource_Remove(sResourceName)
		
		Set doc	= dc.GetNextDocument(doc)
	Wend
	
	Print "delete ResourceFile:" & Cstr(dc.Count)
	
	Exit Sub
	
ErrRtn:
	Msgbox Error() & Chr(13) & "Line: " & Erl(), 16, "Error"
	Print Error(), "ErrorCode: " & Err(), "Line: " & Erl()
	Print "モジュール: PostDocumentDeleteでエラーが発生しました。"
	End 	
	
End Sub

設計公開NTFのダウンロード

 今回のブログで紹介したコードを含む設計公開NTFをアップロードしましたので、必要に応じてご活用下さい。YoutubeAPIのAPIKEYは含んでおりませんので、各自で取得し、設定文書に登録して頂く必要があります。

【ダウンロードリンク】
youtube.zip

最後に

 YoutubeAPIからの情報取得を応用すれば他のWebAPI(ChatGPTなど)とも連携できるようになりますし、イメージリソースの登録がLotusScriptからできるようになれば、製品イメージや、在庫の保管場所マップ、不良箇所イメージなどもビューから見ることができ、Notesクライアントの活用シーンが広がります。Notesクライアントで表示できると言うことはNomadWebやNomadMobileでの表示もできますので、今までできないと思っていた業務改善が実現できるのではないかと思います。
【参考リンク】
ノーツコンソーシアム大阪研究会 浜さんブログ
出直し!! ドミノ塾 (denaoshidomino.com)