Toggle FullScreen
More Info

VBAからドキュワークスのアノテーション属性を調べる

概要

ドキュワークスに貼られているアノテーションを走査します。

サンプルスクリプトでは、XDW_GetAnnotationInformation関数で、指定したドキュワークスファイルの1ページ目のアノテーション情報を取得します。

さらに、そのアノテーションがテキストアノテーションだったら、XDW_GetAnnotationUserAttribute関数で、テキストアノテーションの属性を取得します。

これで、大枠はできているので、例えば「付箋アノテーションだけ非表示にする」とか、「特定の文字が書かれたテキストアノテーションを削除する」なんて使い方ができます。

アノテーションを非表示にするときは、XDW_ShowOrHideAnnotations関数、アノテーションを削除するときは、XDW_RemoveAnnotation関数を使うことになります。

もっと細かく制御したい場合は、XDW_SetAnnotationUserAttribute関数を使って、アノテーションにユーザー定義属性を設定して、XDW_GetAnnotationUserAttributeを使ってユーザー定義属性を取得することになるのでしょう。


基礎資料

動作確認環境

WindowsXP

Excel 2002 SP3

Fuji Xerox DocuWorks Desk 6.2.4

Fuji Xerox DocuWorks API DLL xdwapi.dll 6.2.0.35



参考資料

DocuWorksTM Development Tool Kit 6.2.5 リリースノート
(http://www.fujixerox.co.jp/download/soft/DocuWorks/pop/dwsdk625/Readme.html)
DocuWorks 6以前のSDKは(http://www.fujixerox.co.jp/download/soft/DocuWorks/download.html)からダウンロード。

DocuWorks 7のSDKは(http://www.fujixerox.co.jp/product/software/DocuWorks/download.html)からダウンロード。

実際にXDWAPIを利用する際には、DocuWorks API (XDWAPI)仕様書(XDWAPI.XDW)で、詳細を確認してください。

各種定数やエラーコードなどは、XDWAPIを利用するためのヘッダファイル(xdw_api.h xdwapian.h)に記載されています。



サンプルスクリプト

Option Explicit

'バイト配列と長整数形を相互変換するAPI
Private Declare Sub CopyMemory Lib "Kernel32" Alias "RtlMoveMemory" ( _
        ByRef Destination As Any, _
        ByRef Source As Any, _
        ByVal numbytes As Long)

'動作環境 WindowsXP Excel2002 DocuWorks6.2

'2.34 XDW_GetDocumentInformation   DocuWorksファイル全体に関わる情報を得る。
Private Declare Function XDW_GetDocumentInformation Lib "D:\dwsdk625\XDWAPI\DLL\xdwapi.dll" (ByVal handle As Long, ByRef pDocumentInfo As XDW_DOCUMENT_INFO) As Long
Private Type XDW_DOCUMENT_INFO
   nSize As Long                   '構造体XDW_DOCUMENT_INFOのバイト数を設定する。
   nPages As Long                  '総ページ数。
   nVersion As Long                'DocuWorksファイルのファイルフォーマットのバージョン。
   nOriginalData As Long           'オリジナルデータの数。
   nDocType As Long                'ファイルの種類。
   nPermission As Long             '認可情報。
   nShowAnnotations As Long        'アノテーションの表示状態。
   nDocuments As Long              'nDocTypeがバインダーである場合はバインダーの内部DocuWorks文書数を示す。
   nBinderColor As Long            'nDocTypeがバインダーである場合はバインダーの色を示す。
   nBinderSize As Long             'nDocTypeがバインダーである場合はバインダーのサイズを示す。
End Type

'2.6 XDW_CloseDocumentHandle  DocuWorksファイルにアクセスするためのハンドルを解放する。
Private Declare Function XDW_CloseDocumentHandle Lib "D:\dwsdk625\XDWAPI\DLL\xdwapi.dll" (ByVal handle As Long, ByVal reserved As String) As Long

'2.64 XDW_OpenDocumentHandle  DocuWorksファイルにアクセスするためのハンドルを得る。
Private Declare Function XDW_OpenDocumentHandle Lib "D:\dwsdk625\XDWAPI\DLL\xdwapi.dll" (ByVal lpszFilePath As String, ByRef pHandle As Long, ByRef pMode As XDW_OPEN_MODE) As Long
Private Type XDW_OPEN_MODE
      nSize As Long
      nOption As Long
End Type

'2.23 XDW_GetAnnotationAttribute    指定したアノテーションの属性を取得する。
Private Declare Function XDW_GetAnnotationAttribute Lib "D:\dwsdk625\XDWAPI\DLL\xdwapi.dll" _
(ByVal hAnnotation As Long, ByVal lpszAttributeName As String, ByVal pAttributeValue As Any, ByVal nDataSize As Long, ByVal reserved As String) As Long

'2.24 XDW_GetAnnotationInformation  DocuWorksファイルの、指定ページのアノテーションの情報を取得する。
Private Declare Function XDW_GetAnnotationInformation Lib "D:\dwsdk625\XDWAPI\DLL\xdwapi.dll" _
(ByVal handle As Long, ByVal nPage As Long, ByVal hAnnotation As String, ByVal nIndex As Long, ByRef pAnnotationInfo As XDW_ANNOTATION_INFO, ByVal reserved As String) As Long
Private Type XDW_ANNOTATION_INFO
   nSize As Long           '構造体XDW_ANNOTATION_INFOのバイト数を設定。
   handle As Long          'アノテーションへのハンドル。
   nHorPos As Long         'アノテーションのx座標。単位は1/100mm。
   nVerPos As Long         'アノテーションのy座標。単位は1/100mm。
   nWidth As Long          'アノテーションの幅。単位は1/100mm。
   nHeight As Long         'アノテーションの高さ。単位は1/100mm。
   nAnnotationType As Long 'アノテーションの種類。次の値のいずれかになる。
   nChildAnnotations As Long   '貼られているアノテーションの数。
End Type

Private Enum XDW_AID    'アノテーションの種類
   XDW_AID_TEXT = 32785
   XDW_AID_FUSEN = 32794
   XDW_AID_STRAIGHTLINE = 32828
   XDW_AID_RECTANGLE = 32829
   XDW_AID_ARC = 32830
   XDW_AID_LINK = 49199
   XDW_AID_BITMAP = 32831
   XDW_AID_STAMP = 32819
   XDW_AID_MARKER = 32795
   XDW_AID_POLYGON = 32834
End Enum

Private Enum XDW_ATYPE      '属性値の型情報
   XDW_ATYPE_INT = 0
   XDW_ATYPE_STRING = 1
'    XDW_ATYPE_DATE = 2
'    XDW_ATYPE_BOOL = 3
'    XDW_ATYPE_OCTS = 4
'    XDW_ATYPE_OTHER = 999
End Enum

Private Const XDW_ATN_Text = "%Text"
Private Const XDW_ATN_FontName = "%FontName"
Private Const XDW_ATN_FontSize = "%FontSize"
Private Const XDW_ATN_FontStyle = "%FontStyle"
Private Const XDW_ATN_FontPitchAndFamily = "%FontPitchAndFamily"
Private Const XDW_ATN_ForeColor = "%ForeColor"
Private Const XDW_ATN_FontCharSet = "%FontCharSet"
Private Const XDW_ATN_BackColor = "%BackColor"
Private Const XDW_ATN_FillColor = "%FillColor"
Private Const XDW_ATN_BorderStyle = "%BorderStyle"

Sub Serch_Annotation()
'アノテーションを走査する。
   Dim strFileName1 As String    'ファイル名

   'Docworksを使うための前処理(ここから)
   Dim lngHandle, lngHandleAnnotation As Long
   Dim myMode As XDW_OPEN_MODE
   Dim myInfo As XDW_DOCUMENT_INFO

   With myMode         'XDW_OpenDocumentHandleを実行する際のmyModeに値を設定
      .nOption = 1
'                        #define XDW_OPEN_READONLY       0
'                        #define XDW_OPEN_UPDATE         1

      .nSize = LenB(myMode)
   End With

   With myInfo         'XDW_GetDocumentInformationを実行する際のmyInfoに値を設定
      .nSize = LenB(myInfo)
   End With

   'Docworksを使うための前処理(ここまで)

      strFileName1 = "D:\test001.xdw"

      'DocuWorksファイルにアクセスするためのハンドルを得る。関数が正常に終了したら0を返す。異常終了したときは、エラーコードを返す。
      XDW_OpenDocumentHandle strFileName1, lngHandle, myMode

      'DocuWorksファイル全体に関わる情報を得る。
      XDW_GetDocumentInformation lngHandle, myInfo

   Dim nError, nIndex As Long
   Dim strMsg As String
   Dim myAnnotationInfo As XDW_ANNOTATION_INFO
   Dim myAttributeType As XDW_ATYPE

      nIndex = 0
   Do
      nIndex = nIndex + 1
         myAnnotationInfo.nSize = LenB(myAnnotationInfo)
         '指定ページのアノテーションの情報を取得する
         nError = XDW_GetAnnotationInformation(lngHandle, 1, vbNullString, nIndex, myAnnotationInfo, vbNullString)

   If nError <> 0 Then Exit Do     '返値がエラーなら、Loopを抜ける。

      lngHandleAnnotation = myAnnotationInfo.handle

      strMsg = "Error=" & nError
      strMsg = strMsg & vbCrLf & "nIndex = " & nIndex
      strMsg = strMsg & vbCrLf & "myAnnotationInfo = " & GetAnnottationType(myAnnotationInfo.nAnnotationType)
      strMsg = strMsg & vbCrLf & "nHorPos = " & myAnnotationInfo.nHorPos
      strMsg = strMsg & vbCrLf & "nVerPos = " & myAnnotationInfo.nVerPos

      MsgBox strMsg

      'アノテーションがテキストアノテーションの場合、属性値を調べる
      If myAnnotationInfo.nAnnotationType = 32785 Then
         myAttributeType = XDW_ATYPE_STRING  '属性値の型情報を文字列型に設定
            strMsg = "FontName = " & myGetAnnottationType(lngHandleAnnotation, XDW_ATN_FontName, myAttributeType)
            strMsg = strMsg & vbCrLf & "Text = " & myGetAnnottationType(lngHandleAnnotation, XDW_ATN_Text, myAttributeType)
         myAttributeType = XDW_ATYPE_INT     '属性値の型情報を整数値型に設定
            strMsg = strMsg & vbCrLf & "FontSize = " & myGetAnnottationType(lngHandleAnnotation, XDW_ATN_FontSize, myAttributeType)
            strMsg = strMsg & vbCrLf & "BackColor = " & myGetAnnottationType(lngHandleAnnotation, XDW_ATN_BackColor, myAttributeType)
            strMsg = strMsg & vbCrLf & "FontCharSet = " & myGetAnnottationType(lngHandleAnnotation, XDW_ATN_FontCharSet, myAttributeType)
            strMsg = strMsg & vbCrLf & "FontPitchAndFamily = " & myGetAnnottationType(lngHandleAnnotation, XDW_ATN_FontPitchAndFamily, myAttributeType)
            MsgBox strMsg

      End If

   Loop Until nError <> 0

      'DocuWorksファイルにアクセスするためのハンドルを解放する。関数が正常に終了したら0を返す。異常終了したときは、エラーコードを返す。
      XDW_CloseDocumentHandle lngHandle, vbNullString

End Sub

Public Function BytesToLong(TheArray() As Byte) As Long
'バイト配列を長整数形に変換
   Dim TempLong As Long

      Call CopyMemory(TempLong, TheArray(LBound(TheArray)), 4)
      BytesToLong = TempLong

End Function

Private Function myGetAnnottationType(lngHandleAnnotation As Long, lpszAttributeName As String, nAttributeType As Long) As Variant
'XDW_GetAnnotationAttribute関数を使って、アノテーションの属性値を返す関数
'第1引数:対象のアノテーションのハンドル
'第2引数:属性の名称
'第3引数:得られる属性値の型情報
   Dim lngDataSize As Long     'APIから渡されるデータサイズ。
   Dim myAttribute() As Byte
   Dim strAttribute As String

      '第3引数にNull、第4引数に0を渡すと、必要なデータサイズが返される。
      lngDataSize = XDW_GetAnnotationAttribute(lngHandleAnnotation, lpszAttributeName, StrPtr(vbNullString), lngDataSize, vbNullString)
   ReDim myAttribute(0)
        myAttribute(0) = 0
   ReDim myAttribute(lngDataSize - 1)  '得られたデータサイズを元に、バッファサイズを調整。

      XDW_GetAnnotationAttribute lngHandleAnnotation, lpszAttributeName, VarPtr(myAttribute(0)), lngDataSize, vbNullString

   Select Case nAttributeType
   Case XDW_ATYPE.XDW_ATYPE_STRING     '属性値が文字列のとき
      strAttribute = StrConv(myAttribute, vbUnicode)  '文字コードをASCIIからUnicodeに変換

      '最後にNullがあるので、Nullを削除。
      strAttribute = Left(strAttribute, InStr(strAttribute, vbNullChar) - 1)
      myGetAnnottationType = strAttribute
   Case XDW_ATYPE.XDW_ATYPE_INT        '属性値が数値型の場合
      '数値型の場合は、"Kernel32"の"RtlMoveMemory"(CopyMemory)を使って、バイト配列から長整数形に変換

      myGetAnnottationType = BytesToLong(myAttribute)

   End Select

End Function

Private Function GetAnnottationType(nAnnotationType As Long) As String

Dim strAnnotationType As String

   Select Case nAnnotationType
      Case 32785
         strAnnotationType = "Text"
      Case 32794
         strAnnotationType = "FUSEN"
      Case 32828
         strAnnotationType = "STRAIGHTLINE"
      Case 32829
         strAnnotationType = "RECTANGLE"
      Case 32830
         strAnnotationType = "ARC"
      Case 49199
         strAnnotationType = "LINK"
      Case 32831
         strAnnotationType = "BITMAP"
      Case 32819
         strAnnotationType = "STAMP"
      Case 32795
         strAnnotationType = "MARKER"
      Case 32834
         strAnnotationType = "POLYGON"
      Case Else
         strAnnotationType = "ERROR"
   End Select
   GetAnnottationType = strAnnotationType
End Function



関数の解説

XDW_GetAnnotationInformation

DocuWorksファイルの、指定ページのアノテーションの情報を取得する関数です。

形式

int XDW_GetAnnotationInformation(XDW_DOCUMENT_HANDLE handle, int nPage, XDW_ANNOTATION_HANDLE hAnnotation,int nIndex, XDW_ANNOTATION_INFO* pAnnotationInfo, void* reserved);

パラメータ

  • handle : DocuWorksファイルのハンドル。
  • nPage : 情報を得たいアノテーションのあるページを指定する。1から始まる。
  • hAnnotation : 情報を得たいアノテーションの親アノテーションへのハンドル。ページに直接貼られているアノテーションの情報を得たいときは、NULLを指定する。
  • nIndex : 情報を得たいアノテーションの順番を指定する。1から始まる。
  • pAnnotationInfo : 返される情報へのポインタ。
  • reserved : 予約引数。NULLでなければならない。



XDW_GetAnnotationUserAttribute

アノテーションに設定されたユーザー定義属性を取得する関数です。

形式

int XDW_GetAnnotationAttribute(XDW_ANNOTATION_HANDLE hAnnotation, const char* lpszAttributeName, char* pAttributeValue, int nDataSize, void *reserved);

パラメータ

  • hAnnotation : アノテーションのハンドル
  • lpszAttributeName : 属性名を指定する。NULLターミネートする。属性名の文字列の長さは255バイトまでとする。
  • pAttributeValue : 属性のバイト列のアドレス。
  • nDataSize : pAttributeValueに割り当てられた領域のバイト数。
  • reserved : 予約引数。NULLでなければならない。



バイト配列を長整数型に変換する方法

今回初の試みは、バイト配列でAPIから受け取った属性値を長整数形に変換すること。バイト配列を文字列型に変換するのは、StrConv関数に直接バイト配列を引数に渡して、

        strAttribute = StrConv(myAttribute, vbUnicode)  '文字コードをASCIIからUnicodeに変換

        '最後にNullがあるので、Nullを削除。
        strAttribute = Left(strAttribute, InStr(strAttribute, vbNullChar) - 1)

のようにすればよいのですが、バイト配列を長整数形に変換するには、また別の関数が必要なようです。

参考にしたのは、次の資料

「Visual Basic での種類を Multi-Byte から個々 のバイト数を取得する方法」(http://support.microsoft.com/kb/171652/ja)

相変わらず、機械翻訳は読みづらい。

原文は、

「How To Retrieve Individual Bytes from a Multi-Byte Type in VB」(http://support.microsoft.com/kb/171652/en-us)

で、意訳すると、「VBで、どうやったらマルチバイト型の変数から個々のバイト値を取り出せるか」といったところでしょうか。

このドキュメントでは、長整数型や単精度浮動小数点数型といったマルチバイト型のデータをバイト配列に変換する方法や、その逆にバイト配列を特定のデータ型に変換する方法について説明されています。

ここで提示されているサンプルでは、Kernel32にある、RtlMoveMemory関数を使います。世の中では、Alias(別名)でCopyMemoryとされているようです。

CopyMemory Function(http://msdn.microsoft.com/en-us/library/aa366535(v=vs.85).aspx)
引数としてバイト配列と、値を受け取る長整数型の変数、あと、長整数型のバイト数(4)を渡せばいいだけのようですね。

いろいろな場面で使えそうですが、今回は深く考えずにMSDNのサンプルをそのまま拝借しました。あっさり動きました。


lfPitchAndFamilyの値を設定するときはバイト型で

なぜ、わざわざこんなスクリプトを書いたかというと、理由があります。

テキストアノテーションのフォントをTimes New Romanにしたかったので、XDW_ATN_FontName属性を「Times New Roman」、XDW_ATN_FontCharSet属性を「0」、XDW_ATN_FontPitchAndFamilyを「16」(0 DEFAULT_PITCH | 16 FF_ROMAN)にしたのですが、上手くいかなくて困っていました。

DocuWorks Viewer上では、多分フォントを選択するとcharacter setやPitchAndFamilyは自動で設定されるので、スクリプトから設定値を確認してみようと思ったわけです。

結果的には設定値は上記で問題なかったので、属性の設定方法に問題があることが分かりました。

DocuWorks API(XDWAPI)仕様書によると、XDW_ATN_FontPitchAndFamilyには、「Win32 APIのLOGFONT構造体のlfPitchAndFamilyに設定する値」を設定するように指示があります。
調べてみると、ピッチを指定する値とフォントファミリを指定する値をビット演算して組み合わせるのです。

初めは変数を長整数型にしていましたが、バイト型にすることで上手くいきました。

こんな感じです。

        myXDW_ATN = XDW_ATN_FontPitchAndFamily    'フォントピッチ、ファミリを設定
        Dim bValue As Byte
        bValue = 16

        myXDW_ATN = XDW_ATN_FontPitchAndFamily
        XDW_SetAnnotationAttribute lngHandle, lngHandleAnnotation, myXDW_ATN, 0, VarPtr(bValue), 0, vbNullString

一応FontPitchAndFamilyの値は16にしていますが、0でも大丈夫なようです。


文字コードの解説書

今回LOGFONT構造体について調べたり、また、これまで文字列型の変数をDLLに渡す際に文字コードを変換したりで、文字コード周りのことを考えることが多くなっていました。
以前から文字コードについてもう少し概括的に把握しておきたいと思っていたので、参考図書を購入。



現段階では、まだ途中までしか読んでいませんが、なかなかいい感じです。
まず、入手しやすい書籍で、ここまでまとまっているものが見当たらないので、貴重です。
常々思うことですが、まとめてもらうだけでも書籍を買う価値がある分野があるので、ありがたいものです。

通読したら、追記します。



Twitter from tokidokidokin
アーカイブ
Portfolio Categories
  • カテゴリーなし
Portfolio Tags