[Notes/Domino] 設計解析講座: アイテムの取得、アイテムヘッダ
今回は、API でアイテムを取得する方法について説明します。ついでに、アイテムヘッダ情報の取得方法も触れてみます。
アイテムの取得方法(アイテム名指定)
アイテムを取得するには、NSFItemInfo 関数を使用します。また、同名のアイテムが複数個作成されていることもありますので、NSFItemInfoNext もセットで使用します。
LotusScript でも GetFirstItem で同様のことが簡単にできますが、データを解析する際にはデータ部の BLOCKID が必要になってきますので、これらの関数を使うことは必須となります。覚えておいてください。
まず、アイテム名を指定して取得するサンプルです。
(※大幅に省略しています。実際に動作するものは、後述のアイテムヘッダ情報取得のサンプルを見てください。)
Const NOTESDLL = "nnotes.dll" Type BLOCKID hPool As Long Block As Integer End Type Declare Function NSFItemInfo Lib NOTESDLL (Byval hNote As Long, Byval ItemName As Any, _ Byval NameLen As Integer, ItemBlockid As BLOCKID, ValueDatatype As Integer, _ ValueBlockid As BLOCKID, ValueLen As Long) As Integer Declare Function NSFItemInfoNext Lib NOTESDLL (Byval hNote As Long, Byval hPool As Long, _ Byval Block As Integer, Byval ItemName As Any, Byval NameLen As Integer, ItemBlockid As BLOCKID, _ ValueDatatype As Integer, ValueBlockid As BLOCKID, ValueLen As Long) As Integer '(中略) strTgtName = "{アイテム名}" strTgtName = APITranslate(OS_TRANSLATE_NATIVE_TO_LMBCS, strTgtName & Chr(0)) intRet = NSFItemInfo(doc.handle, strTgtName, Lenbp(strTgtName), ItemBlockid, intDataType, ValueBlockid, lngLen) If intRet <> 0 Then Msgbox APIGetError(intRet), 0, "エラー" Exit Sub Else Do '(アイテムの情報を取得する処理) Loop While NSFItemInfoNext(doc.handle, ItemBlockid.hPool, ItemBlockid.Block, strTgtName, Lenbp(strTgtName), _ ItemBlockid, intDataType, ValueBlockid, lngLen) = 0 End If
アイテム名はいちおう日本語などもOKなので、Taranslate で一旦 LMBCS にする必要があります。
引数でよくわからないのは BLOCKID だと思いますが、まぁざっくり「メモリを管理している構造体」と考えてください。hPool メンバは割り当てられたメモリ領域へのハンドル、Block メンバはオフセット値が入っています。
アイテムの取得方法(ノートの全アイテム)
次に、ノートに含まれる全アイテムを取得する方法です。API では通常、全アイテムを取得する場合は NSFItemScan という関数で処理するのですが、この関数はコールバック関数を引数に取りますので、AddressOf に対応していない LotusScript では、使うことができません。
代わりに、NSFItemInfo の第2・第3引数、および NSFItemInfoNext の第4・第5引数をNULL(= 0 )にすることにより、NSFItemScan の機能を実現することができます。(ですので、この引数は Any で宣言しておくのがよいでしょう。)
'(略) intRet = NSFItemInfo(doc.handle, 0, 0, ItemBlockid, intDataType, ValueBlockid, lngLen) If intRet <> 0 Then '(略) Else Do '(アイテムの情報を取得する処理) Loop While NSFItemInfoNext(doc.handle, ItemBlockid.hPool, ItemBlockid.Block, _ 0, 0, ItemBlockid, intDataType, ValueBlockid, lngLen) = 0 End If
引数を 0 にするだけでよいので、簡単ですね。
アイテムヘッダ
アイテムヘッダは、文書のプロパティに表示されているおなじみのデータです。すでにご存知かと思いますが、もう一度復習してみましょう。
ヘッダの種類 | 説明 |
---|---|
フィールド名 | アイテムの名前です。 |
データ形式の種類 | アイテムのデータ形式です。このタイプによって、データ部の格納形式が変わります。詳細は次回の連載で説明する予定です。 |
データのサイズ | データ部のサイズです。ヘッダのサイズは含まれません。 |
シーケンス番号 | アイテムの値が変わった回数です。 |
重複アイテムID | 同名アイテムが複数ある場合、それぞを識別するためのIDです。 連番になっているとは限りません。 |
フィールフラグ | アイテムのフラグ値です。
ATTACH …… 添付オブジェクトかどうか (※ PLACEHOLDER は、フォーム一覧の画面でプロパティを表示した際、2番目のタブに表示されるフィールドのところで見ることができます。) |
更新日時 | アイテムの値が変わった日時です。 文書のプロパティには表示されません。 |
シーケンス番号と重複アイテムID以外は、NotesItemクラスで取得できますね。
シーケンス番号と更新日時は、複製の際に使用される情報です。このうち更新日時は文書のプロパティに表示されていないせいか、わりと知られていないかもしれませんが、アイテムごとにデータがいつ変更されたかがわかるので、かなり役に立つ情報です。NotesItem.LastModified でも簡単に取れますので、値を出力するツールを作っておくと便利でしょう。拙作の一括置換ツールでも、次期バージョンで更新日時の表示機能を追加する予定です。
アイテムヘッダ情報の取得
アイテムヘッダの情報を取得するには、NSFItemQueryEx 関数(R5以前はNSFItemQuery)を使用します。更新日時だけは別途 NSFItemGetModifiedTime を使用する必要があります。
以下、アイコンノートのすべてのアイテムのヘッダ情報を表示するサンプルを示します。
Const WORDLEN = 65534 Const OS_TRANSLATE_NATIVE_TO_LMBCS = 0 Const OS_TRANSLATE_LMBCS_TO_NATIVE = 1 Const ITEM_SIGN = &H0001 Const ITEM_SEAL = &H0002 Const ITEM_SUMMARY = &H0004 Const ITEM_READWRITERS = &H0020 Const ITEM_NAMES = &H0040 Const ITEM_PLACEHOLDER = &H0100 Const ITEM_PROTECTED = &H0200 Const ITEM_READERS = &H0400 Const ITEM_UNCHANGED = &H1000 Const NOTESDLL = "nnotes.dll" Type BLOCKID hPool As Long Block As Integer End Type Public Type TIMEDATE Innards(1) As Long End Type Declare Function NSFItemInfo Lib NOTESDLL (Byval hNote As Long, Byval ItemName As Any, _ Byval NameLen As Integer, ItemBlockid As BLOCKID, ValueDatatype As Integer, _ ValueBlockid As BLOCKID, ValueLen As Long) As Integer Declare Function NSFItemInfoNext Lib NOTESDLL (Byval hNote As Long, Byval hPool As Long, _ Byval Block As Integer, Byval ItemName As Any, Byval NameLen As Integer, ItemBlockid As BLOCKID, _ ValueDatatype As Integer, ValueBlockid As BLOCKID, ValueLen As Long) As Integer Declare Function ConvertTIMEDATEToText Lib NOTESDLL (Byval IntlFormat As Integer, _ Byval TimeFormat As Integer, InputTime As TIMEDATE, Byval retTextBuffer As String, _ Byval TextBufferLength As Integer, retTextLength As Integer) As Integer Declare Function NSFItemGetModifiedTime Lib NOTESDLL (Byval hNote As Long, Byval ItemName As String, _ Byval ItemNameLength As Integer, Byval Flags As Long, retTime As TIMEDATE) As Integer Declare Sub NSFItemQueryEx Lib NOTESDLL (Byval hNote As Long, Byval hPool As Long, _ Byval iBlock As Integer, Byval ItemName As String, Byval BufLen As Integer, _ NameLen As Integer, ItemFlags As Integer, ValDataType As Integer, _ ValueBlockid As BLOCKID, ValueLen As Long, retSeqByte As Integer, retDupItemID As Integer) Declare Function OSTranslate Lib NOTESDLL (Byval TranslateMode As Integer, _ Byval InData As String, Byval InLength As Long, Byval OutData As String, _ Byval OutLength As Long) As Integer Declare Function OSLoadString Lib NOTESDLL (Byval hModule As Long, Byval StringCode As Long, _ Byval retBuffer As String, Byval BufferLength As Integer) As Integer Sub Initialize Dim ss As New NotesSession Dim db As NotesDatabase Dim doc As NotesDocument Dim ItemBlockid As BLOCKID Dim ValueBlockid As BLOCKID Dim blockid As BLOCKID Dim td As TIMEDATE Dim strItemName As String Dim strTgtName As String Dim strFlags As String Dim strModTD As String Dim lngLen As Long Dim lngVal As Long Dim intRet As Integer Dim intNameLen As Integer Dim intFlags As Integer Dim intDataType As Integer Dim intSeq As Integer Dim intDup As Integer Set db = ss.CurrentDatabase Set doc = db.GetDocumentByID("FFFF0010") intRet = NSFItemInfo(doc.handle, 0, 0, ItemBlockid, intDataType, ValueBlockid, lngLen) If intRet <> 0 Then Msgbox APIGetError(intRet), 0, "エラー" Exit Sub Else Do 'アイテムの情報を取得 strItemName = Space$(1024) Call NSFItemQueryEx(doc.handle, ItemBlockid.hPool, ItemBlockid.Block, strItemName, 1024, _ intNameLen, intFlags, intDataType, blockid, lngVal, intSeq, intDup) '更新日時を取得する intRet = NSFItemGetModifiedTime(doc.handle, Leftbp(strItemName, intNameLen), intNameLen, 0, td) If intRet = 0 Then strModTD = APITIMEDATE2String(td) Else strModTD = "エラー" End If 'アイテム名 strItemName = Trim(APITranslate(OS_TRANSLATE_LMBCS_TO_NATIVE, strItemName & Chr(0))) 'フラグを調べる strFlags = "" If strItemName = "$FILE" Then strFlags = strFlags & ",ATTACH" If (intFlags And ITEM_SIGN) = ITEM_SIGN Then strFlags = strFlags & ",SIGN" If (intFlags And ITEM_SEAL) = ITEM_SEAL Then strFlags = strFlags & ",SEAL" If (intFlags And ITEM_SUMMARY) = ITEM_SUMMARY Then strFlags = strFlags & ",SUMMARY" If (intFlags And ITEM_READERS) = ITEM_READERS Then strFlags = strFlags & ",READ-ACCESS" If (intFlags And ITEM_READWRITERS) = ITEM_READWRITERS Then strFlags = strFlags & ",READ/WRITE-ACCESS" If (intFlags And ITEM_NAMES) = ITEM_NAMES Then strFlags = strFlags & ",NAMES" If (intFlags And ITEM_PLACEHOLDER) = ITEM_PLACEHOLDER Then strFlags = strFlags & ",PLACEHOLDER" If (intFlags And ITEM_PROTECTED) = ITEM_PROTECTED Then strFlags = strFlags & ",PROTECTED" strFlags = Strright(strFlags, ",") '表示 Msgbox "フィールド名: " & strItemName & Chr(10) & _ "データ形式の種類: " & intDataType & Chr(10) & _ "データのサイズ: " & (lngLen - 2) & Chr(10) & _ "シーケンス番号: " & intSeq & Chr(10) & _ "重複アイテムID: " & intDup & Chr(10) & _ "フィールドフラグ: " & strFlags & Chr(10) & _ "更新日時: " & strModTD, 0, "アイテム情報" Loop While NSFItemInfoNext(doc.handle, ItemBlockid.hPool, ItemBlockid.Block, 0, 0, ItemBlockid, intDataType, ValueBlockid, lngLen) = 0 End If End Sub Function APITranslate(Byval intMode As Integer, Byval strBuf As String) As String Dim strOut As String strOut = Space$(WORDLEN) Call OSTranslate(intMode , strBuf, Lenbp(strBuf) - 1, strOut, WORDLEN - 1) APITranslate = Strleft(strOut & Chr(0), Chr(0)) End Function Function APIGetError(Byval intErrCode As Integer) As String Dim strIn As String Dim strOut As String Dim intCode As Integer strIn = Space$(255) strOut = Space$(255) intCode = intErrCode And &h3FFF Call OSLoadString(0, intCode, strIn, Lenbp(strIn) - 1) strOut = APITranslate(OS_TRANSLATE_LMBCS_TO_NATIVE, strIn) APIGetError = Trim(strOut) End Function Function APITIMEDATE2String(td As TIMEDATE) As String Dim s As String * 81 Dim i As Integer Call ConvertTIMEDATEToText(0, 0, td, s, 80, i) APITIMEDATE2String = Strleft(s & Chr(0), Chr(0)) End Function
※ アイテム名を LMBCS から Native に戻すところでは、LeftBP 使えばよいはずなのですが、なぜか日本語名のアイテムでうまくいかなかったので、Trim を使っています。
※ フィールドフラグの ATTACH は、NSFItemQueryEx が返すフラグの中にはありません。よくわからないので、「アイテム名が$FILEかどうか」で判断しています。
コメント
コメントはありません
※コメントは承認制となっております。管理者が承認するまで表示されません。申し訳ありませんが、投稿が表示されるまでしばらくお待ちください。