[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かどうか」で判断しています。

コメント
コメントはありません
※コメントは承認制となっております。管理者が承認するまで表示されません。申し訳ありませんが、投稿が表示されるまでしばらくお待ちください。