Takenoff Labs » Notes/Domino » Notes API » 設計解析講座: アイテムの取得、アイテムヘッダ

[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 …… 添付オブジェクトかどうか
SIGN …… 署名される(されている)かどうか
SEAL …… 暗号化される(されている)かどうか
SUMMARY …… ビューに表示できるかどうか
READ-ACCESS …… 読者名アイテムかどうか
READ/WRITE-ACCESS …… 作成者アイテムかどうか
NAMES …… 名前アイテムかどうか
PLACEHOLDER …… プレースホルダかどうか
PROTECTED …… 編集者以上しか編集できないかどうか

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

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...

トラックバックURL :

Navigation

前の記事(カテゴリ内):

次の記事(カテゴリ内):

前の記事(日付順):

次の記事(日付順):

トラックバック

トラックバックはありません

コメント

コメントはありません

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





(以下のタグが使えます)
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

For spam filtering purposes, please copy the number 6492 to the field below: