Toggle FullScreen
More Info

VBAでDocuWorksの全てのアノテーションを作る

全種類のアノテーションを作ってみる

DocuWorksのアノテーション操作シリーズ、第3回です。
今回は、全種類のアノテーションを作ります。

いままで使ったこともないアノテーションもありますが、いつか使うかもしれないので、全部使ってみます。




基礎資料

動作確認環境

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)に記載されています。



サンプルスクリプト

Dドライブ直下のtest001.xdwファイルの1ページ目に、下記のアノテーションを順番に作成します。

付箋アノテーションの属性だけ、黄色に変更しましたが、そのほかのアノテーションの属性は初期値のままです。

ビットマップアノテーションは、「C:\WINDOWS\シャボン.bmp」を使いました。

  • 付箋アノテーション
  • 直線アノテーション
  • 矩形アノテーション
  • 楕円アノテーション
  • マーカーアノテーション
  • 多角形アノテーション
  • テキストアノテーション
  • リンクアノテーション
  • 日付印アノテーション
  • ビットマップアノテーション

ではサンプルスクリプトです。

Option Explicit

'動作環境 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.73 XDW_SaveDocument   変更を DocuWorks ファイルに反映させる。
Private Declare Function XDW_SaveDocument Lib "D:\dwsdk625\XDWAPI\DLL\xdwapi.dll" (ByVal handle As Long, ByVal reserved As String) As Long

'2.1 XDW_AddAnnotation   アノテーションを貼り付ける
Private Declare Function XDW_AddAnnotation Lib "D:\dwsdk625\XDWAPI\DLL\xdwapi.dll" _
(ByVal handle As Long, ByVal nAnnotationType As Long, ByVal nPage As Long, ByVal nHorPos As Long, ByVal nVerPos As Long, ByVal pInitialData As Long, ByRef phNewAnnotation As Long, ByVal reserved As String) As Long

'XDW_AddAnnotation用の構造体定義
Private Type XDW_AA_INITIAL_DATA
    nSize As Long   '構造体のバイト数。
    nAnnotationType As Long     'アノテーションの種類。
    nReserved1 As Long      '予約メンバ。0でなければならない。
    nReserved2 As Long      '予約メンバ。0でなければならない。
End Type

'配列の一点目は、親となるオブジェクトの左上からの絶対座標。二点目以降は、一点目を原点とした相対座標
'(移動量)を格納した配列。単位は1/100mm。
Private Type XDW_POINT
    x As Long
    y As Long
End Type

Private Type XDW_AA_FUSEN_INITIAL_DATA
    common As XDW_AA_INITIAL_DATA   '共通情報。構造体のバイト数とアノテーションの種類を指定する。
    nWidth As Long  '付箋アノテーションの幅。単位は1/100mm。
    nHeight As Long  '付箋アノテーションの高さ。単位は1/100mm。
End Type

Private Type XDW_AA_STRAIGHTLINE_INITIAL_DATA
    common As XDW_AA_INITIAL_DATA   '共通情報。構造体のバイト数とアノテーションの種類を指定する。
    nHorVec As Long  '直線アノテーションの始点から終点までのx座標上の移動量。単位は1/100mm。
    nVerVec As Long  '直線アノテーションの始点から終点までのy座標上の移動量。単位は1/100mm。
End Type

Private Type XDW_AA_RECT_INITIAL_DATA
    common As XDW_AA_INITIAL_DATA   '共通情報。構造体のバイト数とアノテーションの種類を指定する。
    nWidth As Long  '矩形アノテーションの幅。単位は1/100mm。
    nHeight As Long  '矩形アノテーションの高さ。単位は1/100mm。
End Type

Private Type XDW_AA_ARC_INITIAL_DATA
    common As XDW_AA_INITIAL_DATA   '共通情報。構造体のバイト数とアノテーションの種類を指定する。
    nWidth As Long  '楕円アノテーションの幅(円の直径に相当)。単位は1/100mm。
    nHeight As Long  '楕円アノテーションの高さ(円の直径に相当)。単位は1/100mm。
End Type

Private Type XDW_AA_BITMAP_INITIAL_DATA
    common As XDW_AA_INITIAL_DATA   '共通情報。構造体のバイト数とアノテーションの種類を指定する。
    szImagePath As String * 128 'BMPファイルへのパス名を絶対パスで指定する。
End Type

Private Type XDW_AA_MARKER_INITIAL_DATA
    common As XDW_AA_INITIAL_DATA   '共通情報。構造体のバイト数とアノテーションの種類を指定する。
    nCounts As Long  'pPointsで指定する座標の数。
    '!!!配列を渡す(アドレス・ポインタ渡し)ので、長整数形で宣言する!!!
    pPoints As Long
End Type

Private Type XDW_AA_POLYGON_INITIAL_DATA
    common As XDW_AA_INITIAL_DATA   '共通情報。構造体のバイト数とアノテーションの種類を指定する。
    nCounts As Long  'pPointsで指定する座標の数。
    '!!!配列を渡す(アドレス・ポインタ渡し)ので、長整数形で宣言する!!!
    pPoints As Long
End Type

Private Type XDW_AA_STAMP_INITIAL_DATA
    common As XDW_AA_INITIAL_DATA   '共通情報。構造体のバイト数とアノテーションの種類を指定する。
    nWidth As Long  '日付印アノテーションの幅。単位は1/100mm。
End Type

'2.74 XDW_SetAnnotationAttribute    指定したアノテーションの属性を設定する。
'テキスト、リンク、日付印アノテーションの場合
Private Declare Function XDW_S_SetAnnotationAttribute Lib "D:\dwsdk625\XDWAPI\DLL\xdwapi.dll" Alias "XDW_SetAnnotationAttribute" _
(ByVal handle As Long, ByVal hAnnotation As Long, ByVal lpszAttributeName As String, ByVal nAttributeType As Long, ByVal pAttributeValue As String, ByVal nReserved As Long, ByVal pReserved As String) As Long
'上記以外のアノテーションの場合
Private Declare Function XDW_L_SetAnnotationAttribute Lib "D:\dwsdk625\XDWAPI\DLL\xdwapi.dll" Alias "XDW_SetAnnotationAttribute" _
(ByVal handle As Long, ByVal hAnnotation As Long, ByVal lpszAttributeName As String, ByVal nAttributeType As Long, ByRef pAttributeValue As Long, ByVal nReserved As Long, ByVal pReserved As String) As Long

'2.86 XDW_StarchAnnotation      指定されたアノテーションを固定する、もしくは解除する
Private Declare Function XDW_StarchAnnotation Lib "D:\dwsdk625\XDWAPI\DLL\xdwapi.dll" (ByVal handle As Long, ByVal hAnnotation As Long, ByVal nStarch As Long, ByVal reserved As String) As Long

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_Color  'カラーの種類(16進数を10進数に変換)
    XDW_COLOR_NONE = CLng("&H" & "010101")
    XDW_COLOR_BLACK = CLng("&H" & "000000")
    XDW_COLOR_MAROON = CLng("&H" & "000080")
    XDW_COLOR_GREEN = CLng("&H" & "008000")
    XDW_COLOR_OLIVE = CLng("&H" & "008080")
    XDW_COLOR_NAVY = CLng("&H" & "800000")
    XDW_COLOR_PURPLE = CLng("&H" & "800080")
    XDW_COLOR_TEAL = CLng("&H" & "808000")
    XDW_COLOR_GRAY = CLng("&H" & "808080")
    XDW_COLOR_SILVER = CLng("&H" & "C0C0C0")
    XDW_COLOR_RED = CLng("&H" & "0000FF")
    XDW_COLOR_LIME = CLng("&H" & "00FF00")
    XDW_COLOR_YELLOW = CLng("&H" & "00FFFF")
    XDW_COLOR_BLUE = CLng("&H" & "FF0000")
    XDW_COLOR_FUCHIA = CLng("&H" & "FF00FF")
    XDW_COLOR_WHITE = CLng("&H" & "FFFFFF")
    XDW_COLOR_FUSEN_RED = CLng("&H" & "FFC2FF")
    XDW_COLOR_FUSEN_BLUE = CLng("&H" & "FFBF9D")
    XDW_COLOR_FUSEN_YELLOW = CLng("&H" & "64FFFF")
    XDW_COLOR_FUSEN_LIME = CLng("&H" & "C2FF9D")
End Enum

Private Enum XDW_STARCH_def     'アノテーションの固定もしくは解除を指定
    XDW_STARCH = 1
    XDW_STARCH_OFF = 0
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_BackColor = "%BackColor"
Private Const XDW_ATN_FillColor = "%FillColor"

Sub AddAnnotation_ALL()
'多様なアノテーションを貼り付ける。
    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 myXDW_AID As XDW_AID    '貼り付けるアノテーションの種類
    Dim myXDW_ATN As String    'アノテーションの属性名
    Dim myAaInitialData As XDW_AA_INITIAL_DATA
    Dim lngPage, lngHorPos, lngVerPos As Long   'アノテーションを貼るページ、アノテーションのx座標、y座標(単位は1/100mm)
    Dim myPoint() As XDW_POINT                  '座標配列

    '=======付箋アノテーションの貼り付け ここから=======
    Dim myAaFusenInitialData As XDW_AA_FUSEN_INITIAL_DATA
    Dim lngWidth, lngHeight As Long     'アノテーションの幅,高さ

        myXDW_AID = XDW_AID_FUSEN      '貼り付けるアノテーションの種類を指定。
        lngPage = 1                     '1ページ目に貼り付ける
        lngHorPos = 1000                '1cm
        lngVerPos = 1000                '1cm
        lngWidth = 19000                 'アノテーションの幅。単位は1/100mm。
        lngHeight = 1000                 'アノテーションの高さ。単位は1/100mm。

        With myAaInitialData
            .nAnnotationType = myXDW_AID    'アノテーションの種類。
            .nReserved1 = 0             '予約メンバ。0でなければならない。
            .nReserved2 = 0             '予約メンバ。0でなければならない。
        End With

        With myAaFusenInitialData   '付箋用の構造体XDW_AA_FUSEN_INITIAL_DATAに値を設定
            .common = myAaInitialData   '共通情報。構造体のバイト数とアノテーションの種類を指定する。
            .nWidth = lngWidth          '付箋アノテーションの幅。単位は1/100mm。最小値: 500(=5mm)、最大値: 50000(=50cm)
            .nHeight = lngHeight         '付箋アノテーションの高さ。単位は1/100mm。最小値: 500(=5mm)、最大値: 50000(=50cm)
        End With

        myAaFusenInitialData.common.nSize = LenB(myAaFusenInitialData)  '構造体のバイト数。

        'ふせんアノテーションを貼り付ける
        XDW_AddAnnotation lngHandle, myXDW_AID, lngPage, lngHorPos, lngVerPos, VarPtr(myAaFusenInitialData), lngHandleAnnotation, vbNullString

        'ふせんアノテーションの属性を設定する。
    Dim myXDW_ATN_Color As XDW_Color
    Dim strTxt, strAttributeName As String
    Dim lngFValue As Long

        myXDW_ATN = XDW_ATN_FillColor    '付箋内の色を設定
        myXDW_ATN_Color = XDW_COLOR_FUSEN_YELLOW   '付箋黄色
        XDW_L_SetAnnotationAttribute lngHandle, lngHandleAnnotation, myXDW_ATN, 0, myXDW_ATN_Color, 0, vbNullString

    '=======付箋アノテーションの貼り付け ここまで=======

    '=======直線アノテーションの貼り付け ここから=======
    Dim lngHorVec, lngVerVec As Long   'アノテーションのx座標上の移動量、y座標上の移動量(単位は1/100mm)
    Dim myAaSTRAIGHTLINEData As XDW_AA_STRAIGHTLINE_INITIAL_DATA

        myXDW_AID = XDW_AID_STRAIGHTLINE      '貼り付けるアノテーションの種類を指定。
        lngPage = 1                     '1ページ目に貼り付ける
        lngHorPos = 1000                'アノテーションのx座標1cm
        lngVerPos = 3000                'アノテーションのy座標3cm
        lngHorVec = 2500                'x座標上の移動量25cm
        lngVerVec = 3000                'y座標上の移動量30cm

        With myAaInitialData
            .nAnnotationType = myXDW_AID    'アノテーションの種類。
            .nReserved1 = 0             '予約メンバ。0でなければならない。
            .nReserved2 = 0             '予約メンバ。0でなければならない。
        End With

        With myAaSTRAIGHTLINEData   '構造体XDW_AA_STRAIGHTLINE_INITIAL_DATAに値を設定
            .common = myAaInitialData   '共通情報。構造体のバイト数とアノテーションの種類を指定する。
            .nHorVec = lngHorVec          '直線アノテーションのx座標上の移動量
            .nVerVec = lngVerVec         '直線アノテーションのy座標上の移動量
        End With

        myAaSTRAIGHTLINEData.common.nSize = LenB(myAaSTRAIGHTLINEData)  '構造体のバイト数。

        '直線アノテーションを貼り付ける
        XDW_AddAnnotation lngHandle, myXDW_AID, lngPage, lngHorPos, lngVerPos, VarPtr(myAaSTRAIGHTLINEData), lngHandleAnnotation, vbNullString

    '=======直線アノテーションの貼り付け ここまで=======

    '=======矩形アノテーションの貼り付け ここから=======
    Dim myAaRECTData As XDW_AA_RECT_INITIAL_DATA

        myXDW_AID = XDW_AID_RECTANGLE      '貼り付けるアノテーションの種類を指定。
        lngPage = 1                     '1ページ目に貼り付ける
        lngHorPos = 1000                'アノテーションのx座標1cm
        lngVerPos = 8000                'アノテーションのy座標8cm
        lngWidth = 2500                '矩形アノテーションの幅。単位は1/100mm。
        lngHeight = 3000                '矩形アノテーションの高さ。単位は1/100mm。

        With myAaInitialData
            .nAnnotationType = myXDW_AID    'アノテーションの種類。
            .nReserved1 = 0             '予約メンバ。0でなければならない。
            .nReserved2 = 0             '予約メンバ。0でなければならない。
        End With

        With myAaRECTData   '構造体XDW_AA_RECT_INITIAL_DATAに値を設定
            .common = myAaInitialData   '共通情報。構造体のバイト数とアノテーションの種類を指定する。
            .nHeight = lngHeight          '直線アノテーションのx座標上の移動量
            .nWidth = lngWidth         '直線アノテーションのy座標上の移動量
        End With

        myAaRECTData.common.nSize = LenB(myAaRECTData)  '構造体のバイト数。

        '矩形アノテーションを貼り付ける
        XDW_AddAnnotation lngHandle, myXDW_AID, lngPage, lngHorPos, lngVerPos, VarPtr(myAaRECTData), lngHandleAnnotation, vbNullString

    '=======矩形アノテーションの貼り付け ここまで=======

    '=======楕円アノテーションの貼り付け ここから=======
    Dim myAaARCData As XDW_AA_ARC_INITIAL_DATA

        myXDW_AID = XDW_AID_ARC      '貼り付けるアノテーションの種類を指定。
        lngPage = 1                     '1ページ目に貼り付ける
        lngHorPos = 1000                'アノテーションのx座標1cm
        lngVerPos = 12000                'アノテーションのy座標12cm
        lngWidth = 4000                '楕円アノテーションの幅(円の直径に相当)。単位は1/100mm。
        lngHeight = 3000                '楕円アノテーションの高さ(円の直径に相当)。単位は1/100mm。

        With myAaInitialData
            .nAnnotationType = myXDW_AID    'アノテーションの種類。
            .nReserved1 = 0             '予約メンバ。0でなければならない。
            .nReserved2 = 0             '予約メンバ。0でなければならない。
        End With

        With myAaARCData   '構造体XDW_AA_ARC_INITIAL_DATAに値を設定
            .common = myAaInitialData   '共通情報。構造体のバイト数とアノテーションの種類を指定する。
            .nHeight = lngHeight          '楕円アノテーションのx座標上の移動量
            .nWidth = lngWidth         '楕円アノテーションのy座標上の移動量
        End With

        myAaARCData.common.nSize = LenB(myAaARCData)  '構造体のバイト数。

        '楕円アノテーションを貼り付ける
        XDW_AddAnnotation lngHandle, myXDW_AID, lngPage, lngHorPos, lngVerPos, VarPtr(myAaARCData), lngHandleAnnotation, vbNullString

    '=======楕円アノテーションの貼り付け ここまで=======

    '=======マーカーアノテーションの貼り付け ここから=======
    Dim myAaMARKERData As XDW_AA_MARKER_INITIAL_DATA
    ReDim myPoint(4)

        myXDW_AID = XDW_AID_MARKER      '貼り付けるアノテーションの種類を指定。
        lngPage = 1                     '1ページ目に貼り付ける
        lngHorPos = 1000                'アノテーションのx座標(マーカーアノテーションの場合は無視される)
        lngVerPos = 1000                'アノテーションのy座標(マーカーアノテーションの場合は無視される)
        myPoint(0).x = 7000             '以下、座標
        myPoint(0).y = 4000
        myPoint(1).x = 2000
        myPoint(1).y = 1000
        myPoint(2).x = 4000
        myPoint(2).y = 0
        myPoint(3).x = 6000
        myPoint(3).y = 1000
        myPoint(4).x = 8000
        myPoint(4).y = 0

        With myAaInitialData
            .nAnnotationType = myXDW_AID    'アノテーションの種類。
            .nReserved1 = 0             '予約メンバ。0でなければならない。
            .nReserved2 = 0             '予約メンバ。0でなければならない。
        End With

        With myAaMARKERData   '構造体XDW_AA_ARC_INITIAL_DATAに値を設定
            .common = myAaInitialData   '共通情報。構造体のバイト数とアノテーションの種類を指定する。
            .nCounts = UBound(myPoint) + 1      '座標の数

            '!!!構造体に配列を渡すときは、VarPtr関数を使って、配列の先頭要素のアドレスを渡す。!!!
            .pPoints = VarPtr(myPoint(0))
        End With

        myAaMARKERData.common.nSize = LenB(myAaMARKERData)  '構造体のバイト数。

        'マーカーアノテーションを貼り付ける
        XDW_AddAnnotation lngHandle, myXDW_AID, lngPage, lngHorPos, lngVerPos, VarPtr(myAaMARKERData), lngHandleAnnotation, vbNullString

    '=======マーカーアノテーションの貼り付け ここまで=======

    '=======多角形アノテーションの貼り付け ここから=======
    Dim myAaPOLYGONData As XDW_AA_POLYGON_INITIAL_DATA
    ReDim myPoint(2)

        myXDW_AID = XDW_AID_POLYGON      '貼り付けるアノテーションの種類を指定。
        lngPage = 1                     '1ページ目に貼り付ける
        lngHorPos = 10000                'アノテーションのx座標(多角形アノテーションの場合、無視される)
        lngVerPos = 10000                'アノテーションのy座標(多角形アノテーションの場合、無視される)
        myPoint(0).x = 10000            '以下、座標
        myPoint(0).y = 10000
        myPoint(1).x = 2000
        myPoint(1).y = 0
        myPoint(2).x = 1000
        myPoint(2).y = -2000

        With myAaInitialData
            .nAnnotationType = myXDW_AID    'アノテーションの種類。
            .nReserved1 = 0             '予約メンバ。0でなければならない。
            .nReserved2 = 0             '予約メンバ。0でなければならない。
        End With

        With myAaPOLYGONData   '構造体XDW_AA_ARC_INITIAL_DATAに値を設定
            .common = myAaInitialData   '共通情報。構造体のバイト数とアノテーションの種類を指定する。
            .nCounts = UBound(myPoint) + 1      '座標の数

            '!!!構造体に配列を渡すときは、VarPtr関数を使って、配列の先頭要素のアドレスを渡す。!!!
            .pPoints = VarPtr(myPoint(0))
        End With

        myAaPOLYGONData.common.nSize = LenB(myAaPOLYGONData)  '構造体のバイト数。

        '多角形アノテーションを貼り付ける
        XDW_AddAnnotation lngHandle, myXDW_AID, lngPage, lngHorPos, lngVerPos, VarPtr(myAaPOLYGONData), lngHandleAnnotation, vbNullString

    '=======多角形アノテーションの貼り付け ここまで=======

    '=======テキストアノテーションの貼り付け ここから=======

        myXDW_AID = XDW_AID_TEXT      '貼り付けるアノテーションの種類を指定。
        lngPage = 1                     '1ページ目に貼り付ける
        lngHorPos = 11000                'アノテーションのx座標11cm
        lngVerPos = 11000                'アノテーションのy座標11cm

        'テキストアノテーションを貼り付ける
        XDW_AddAnnotation lngHandle, myXDW_AID, lngPage, lngHorPos, lngVerPos, StrPtr(vbNullString), lngHandleAnnotation, vbNullString

    '=======テキストアノテーションの貼り付け ここまで=======

    '=======リンクアノテーションの貼り付け ここから=======

        myXDW_AID = XDW_AID_LINK      '貼り付けるアノテーションの種類を指定。
        lngPage = 1                     '1ページ目に貼り付ける
        lngHorPos = 10000                'アノテーションのx座標10cm
        lngVerPos = 12000                'アノテーションのy座標10cm

        'リンクアノテーションを貼り付ける
        XDW_AddAnnotation lngHandle, myXDW_AID, lngPage, lngHorPos, lngVerPos, StrPtr(vbNullString), lngHandleAnnotation, vbNullString

    '=======リンクアノテーションの貼り付け ここまで=======

    '=======日付印アノテーションの貼り付け ここから=======

    Dim myAaSTAMPData As XDW_AA_STAMP_INITIAL_DATA

        myXDW_AID = XDW_AID_STAMP      '貼り付けるアノテーションの種類を指定。
        lngPage = 1                     '1ページ目に貼り付ける
        lngHorPos = 10000                'アノテーションのx座標10cm
        lngVerPos = 14000                'アノテーションのy座標10cm
        lngWidth = 3000                '日付印アノテーションの幅(円の直径に相当)。単位は1/100mm。

        With myAaInitialData
            .nAnnotationType = myXDW_AID    'アノテーションの種類。
            .nReserved1 = 0             '予約メンバ。0でなければならない。
            .nReserved2 = 0             '予約メンバ。0でなければならない。
        End With

        With myAaSTAMPData   '構造体XDW_AA_STAMP_INITIAL_DATAに値を設定
            .common = myAaInitialData   '共通情報。構造体のバイト数とアノテーションの種類を指定する。
            .nWidth = lngWidth         '日付印アノテーションの幅
        End With

        myAaSTAMPData.common.nSize = LenB(myAaSTAMPData)  '構造体のバイト数。

        '楕円アノテーションを貼り付ける
        XDW_AddAnnotation lngHandle, myXDW_AID, lngPage, lngHorPos, lngVerPos, VarPtr(myAaSTAMPData), lngHandleAnnotation, vbNullString

    '=======日付印アノテーションの貼り付け ここまで=======

    '=======ビットマップアノテーションの貼り付け ここから=======
    Dim myAaBMPData As XDW_AA_BITMAP_INITIAL_DATA
    Dim strBMPPass As String * 128

        strBMPPass = "C:\WINDOWS\シャボン.bmp"
        strBMPPass = StrConv(strBMPPass, vbFromUnicode)

        myXDW_AID = XDW_AID_BITMAP      '貼り付けるアノテーションの種類を指定。
        lngPage = 1                     '1ページ目に貼り付ける
        lngHorPos = 10000                'アノテーションのx座標10cm
        lngVerPos = 18000                'アノテーションのy座標18cm

        With myAaInitialData
            .nAnnotationType = myXDW_AID    'アノテーションの種類。
            .nReserved1 = 0             '予約メンバ。0でなければならない。
            .nReserved2 = 0             '予約メンバ。0でなければならない。
        End With

        With myAaBMPData   '構造体XDW_AA_BITMAP_INITIAL_DATAに値を設定
            .common = myAaInitialData   '共通情報。構造体のバイト数とアノテーションの種類を指定する。
            .szImagePath = strBMPPass
        End With

        myAaBMPData.common.nSize = LenB(myAaBMPData)  '構造体のバイト数。

        'ビットマップアノテーションを貼り付ける
        MsgBox XDW_AddAnnotation(lngHandle, myXDW_AID, lngPage, lngHorPos, lngVerPos, VarPtr(myAaBMPData), lngHandleAnnotation, vbNullString)

    '=======ビットマップアノテーションの貼り付け ここまで=======

        '変更を DocuWorks ファイルに反映させる。関数が正常に終了したら0を返す。異常終了したときは、エラーコードを返す。
        XDW_SaveDocument lngHandle, vbNullString

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



スクリーンショット

処理済のページをJPEGに変換しました。
一番上が付箋アノテーションで、左上部から下部、中央上部から下部へアノテーションが並びます。

fusen



引数にNullと構造体をとるときの処理方法

構造体とNullのポインタを渡す

前回も解説した、アノテーションを貼り付けるXDW_AddAnnotation関数ですが、この関数は第6引数に、pInitialData(初期値情報)をとります。

XDW_AddAnnotationの形式は、次のようになっています。



int XDW_AddAnnotation(XDW_DOCUMENT_HANDLE handle, int nAnnotationType, int nPage, int nHorPos, int nVerPos,XDW_AA_INITIAL_DATA* pInitialData, XDW_ANNOTATION_HANDLE* phNewAnnotation, void* reserved);



pInitialDataには、基本はNULLを渡すのですが、

  • 付箋アノテーション : XDW_AA_FUSEN_INITIAL_DATA
  • 直線アノテーション : XDW_AA_STRAIGHTLINE_INITIAL_DATA
  • 矩形アノテーション : XDW_AA_RECT_INITIAL_DATA
  • 楕円アノテーション : XDW_AA_ARC_INITIAL_DATA
  • ビットマップアノテーション : XDW_AA_BITMAP_INITIAL_DATA
  • マーカーアノテーション : XDW_AA_MARKER_INITIAL_DATA
  • 多角形アノテーション : XDW_AA_POLYGON_INITIAL_DATA

の場合は、それぞれの構造体へのポインタを渡します。

たとえば、付箋アノテーションを作る際、pInitialDataに渡す構造体XDW_AA_FUSEN_INITIAL_DATAは次のようになっています。

struct XDW_AA_FUSEN_INITIAL_DATA {
  XDW_AA_INITIAL_DATA common;   共通情報。構造体のバイト数とアノテーションの種類を指定する。
  int nWidth;                   付箋アノテーションの幅。単位は1/100mm。
  int nHeight;                  付箋アノテーションの高さ。単位は1/100mm。
};

struct XDW_AA_INITIAL_DATA {
   int nSize; 構造体のバイト数。
   int nAnnotationType ;          アノテーションの種類。
   int nReserved1 ;               予約メンバ。0でなければならない。
   int nReserved2 ;               予約メンバ。0でなければならない。
};




関数にNullを渡すときは、「ByVal pInitialData As String」と宣言し、vbNullstringを渡します。

関数に構造体へのポインタを渡すときは、「ByRef pInitialData As Any」と宣言し、VBAで定義したユーザー定義型で定義された変数を渡します。

関数を別名(Alias)で宣言して使い分けてもいいのですが、一つにまとめるときには、ちょっと工夫が必要です。

Nullを渡すときも構造体を渡すときも、実態として、dllにはポインタを渡すので「ByVal pInitialData As Long」と、長整数形で値渡しします。

その上で、関数に引数を渡す際、
Nullを渡すときは、StrPtr(vbNullString)として、Nullへのポインタを渡し、
構造体を渡すときは、VarPtr(myAaFusenInitialData)のように、構造体へのポインタを渡します。

これで、すっきりしました。


StrPtr関数とVarPtr関数

StrPtr関数と、VarPtr関数については、いろいろなところに説明がありますが、この記事の後半で紹介している「Visual Basic 6.0 を使用して、Visual Basic と C 関数の間または Visual Basic とC++ 関数の間で配列や文字列を受け渡す方法」の「Unicode から ANSI への変換を行わずに文字列を渡す」の章(http://support.microsoft.com/kb/205277/ja#19)」で、次のように説明されています。

ヘルパ関数

通常、Visual Basic に用意されている組み込みのヘルパ関数を使用することで、Unicode から ANSI への変換を回避できます。

VarPtr 関数は変数のアドレスを返します。しかし、VarPtr 関数を使用して、配列のアドレスを返すことはできません。

StrPtr 関数は、Unicode 文字列のアドレスを返します。StrPtr 関数は、空の文字列 (“”) と NULL 文字列 (vbNullString) を判別するために使用されます。関数 StrPtr(“”) は、空の文字列が格納されているメモリ位置のアドレスを返します。これに対して、StrPtr(vbNullString) 関数はゼロを返します。

VarPtr 関数と StrPtr 関数との違いは、これらの関数に渡される変数が文字列の場合、特に重要です。変数が文字列である場合、これらの関数は以下の値を返します。

  • StrPtr 関数は、BSTR 変数の一部である Unicode 文字列のアドレスを返します。
  • VarPtr 関数は、BSTR 変数のアドレスを返します。

このため、StrPtr 関数は Unicode 文字列へのポインタを返し、VarPtr 関数は StrPtr 関数が返すポインタへのポインタを返します。

文字列の配列のアドレスや文字列を含んだユーザー定義型の配列のアドレスを返す Visual Basic の組み込み関数はありません。ただし、Msvbvm60.dll ファイルで定義されている VarPtr 関数を使用してこれを行うことができます。

原文には、この後にStrPtr関数とVarPtr関数を使ったいくつかのサンプルが提示されています。VB6を対象にした解説ですが、VBAでも参考になる部分が多いと思います。



構造体の要素に文字列をとる場合の処理方法

今回、一番苦労したところが、ビットマップアノテーションの処理。

ビットマップアノテーションを作るときに引数「pInitialData」に渡す構造体は、XDW_AA_MARKER_INITIAL_DATAで、定義は次のようになっています。

struct XDW_AA_BITMAP_INITIAL_DATA {
   XDW_AA_INITIAL_DATA common ;   共通情報。構造体のバイト数とアノテーションの種類を指定する。
   char szImagePath[256] ;        BMPファイルへのパス名を絶対パスで指定する。
};

struct XDW_AA_INITIAL_DATA {
   int nSize; 構造体のバイト数。
   int nAnnotationType ;          アノテーションの種類。
   int nReserved1 ;               予約メンバ。0でなければならない。
   int nReserved2 ;               予約メンバ。0でなければならない。
};




構造体XDW_AA_BITMAP_INITIAL_DATAは、BMPファイルへの絶対パスを要素に持つのです。いろいろ試行錯誤したものの、結局、構造体の定義を以下のようにすることで、解決。

Private Type XDW_AA_BITMAP_INITIAL_DATA
    common As XDW_AA_INITIAL_DATA   '共通情報。構造体のバイト数とアノテーションの種類を指定する。
    szImagePath As String * 128 'BMPファイルへのパス名を絶対パスで指定する。
End Type




構造体の定義で、szImagePath[256]のように256バイトなので、VBAでは、「szImagePath As String * 128」となります。VBAでは、文字コードはUnicodeで、1文字2バイトだから、固定長文字列128文字分のメモリを確保すればよいことになります。

また、上に書いたように、関数の宣言を「ByVal pInitialData As Long」として、メモリアドレスを値渡しするときには、VBAで文字コードの変換をしてくれないようなので、

        strBMPPass = "C:\WINDOWS\シャボン.bmp"
        strBMPPass = StrConv(strBMPPass, vbFromUnicode)

のように、文字列をUnicodeからANSI形式に変換する必要があるようです。

最初は、文字列をバイト配列に入れなおさないといけないかと思っていましたが、そんな必要はありませんでした。


参考資料

試行錯誤する中で見つけた資料。

Visual Basic 6.0 を使用して、Visual Basic と C 関数の間または Visual Basic と C++ 関数の間で配列や文字列を受け渡す方法(http://support.microsoft.com/kb/205277/ja)

なかなかよい、まとまった資料を見つけました。
この資料にめぐり合わなければ、今回のスクリプトを完成できなかったでしょう。

VBでDLLの関数を使うときによく困るのが、引数に文字列や配列をとるとき。

どうやって宣言するのかと、どうやって渡すのか。
ByVal? ByRef? 変数をそのまま渡すのか、StrPtrやVarPtrなどの隠し関数を使うのか。

とても長いドキュメントなので、要約できませんが、一部抜粋してみます。

例えば、

タイプ ライブラリを使用せずに文字列を渡す

文字列とは、文字が連続して並んだものです。BSTR は、基本文字列またはバイナリ文字列とも呼ばれます。

String

Visual Basic と C の間、および Visual Basic と C++ の間で文字列を受け渡すには、これらのプログラミング言語が文字を表すために使用する各種の方法を理解することが重要です。また、これらのプログラミング言語が文字列を格納する方法についても理解することが重要です。

ANSI (American National Standards Institute) 体系および Unicode 体系 (Unicode) は、文字を表現する 2 つの体系です。ANSI では、1 バイトを使用して文字を格納します。Unicode では、2 バイトを使用して文字を格納します。

Visual Basic は内部的には Unicode を使用していますが、文字列を C や C++ に渡すときは Unicode 文字を等価な ANSI 文字に変換し、C や C++ から文字列を受け取るときは ANSI 文字を等価な Unicode 文字に変換します。

ただし、タイプ ライブラリを使用して Visual Basic と C との間、または Visual Basic と C++ との間で文字列を受け渡す場合は、タイプ ライブラリは OLE に基づいているため、Visual Basic は文字を変換しません。OLE では Unicode のみを使用します。

Visual Basic は文字列を BSTR として格納します。基本的に、BSTR は Unicode 文字列へのポインタです。ただし、この文字列は文字列の長さが先頭に付き、末尾に NULL 文字が付きます。

C や C++ では、文字列を文字の配列として格納します。C や C++ では、文字列を格納するために使用される文字配列の名前が、メモリ位置へのポインタになります。このメモリ位置には、文字列の最初の文字が格納されています。

あと、見出しだけですが、「Unicode から ANSI への変換を行わずに文字列を渡す」という章には、次のような事柄について記述されています。

  • ヘルパ関数
  • Unicode 文字へのポインタを受け取る C 関数や C++ 関数に文字列を渡す
  • BSTR を受け取る C 関数や C++ 関数に文字列を渡す
  • BSTR へのポインタを受け取る C 関数や C++ 関数に文字列を渡す
  • SAFEARRAY を受け取る C 関数や C++ 関数に文字列の配列を渡す
  • 構造体へのポインタを受け取る C 関数や C++ 関数に、文字列を含むユーザー定義型のデータを渡す
  • 構造体へのポインタを受け取る C 関数や C++ 関数に、文字列を含むユーザー定義型のデータの配列を渡す

上記の項目について、StrPtr関数とVarPtr関数を駆使して、どのようにすればパラメーターを渡せるのかについて述べられていますので、興味のあればリンク先をご覧ください。



何に使おうか

スクリプトを書いた後で、何に使おうかってところがエンジニアの性ですね。

まず思いつくのは、マスキング。よくある作業で、マスキングしてから印刷ってのがありますが、そのときに使うのが矩形アノテーション。

ヘルプやDocuWorks Viewerでは四角形と表現されていますが、XDWAPIでは矩形アノテーションと呼ばれます。たくさんのドキュワークス文書の特定の部分をマスキングするには、もってこいですね。

多角形アノテーションも使えるので、複雑なマスキングをするなら、こちらの方がいいかも。

DocuWorks Viewerでフリーハンドと名づけられているアノテーションは、XDWAPIではマーカーアノテーションと呼ばれています。こちらも多角形アノテーションと同様、座標を指定することで、精細な描画ができます。なんと、1/100mm単位。

実際にあまり使ったことがない、ビットマップアノテーションですが、写真を使う帳票には利用できそうですね。DocuWorks Viewerとは違って、位置を正確に決められます。

惜しいのは、どうやらこのXDWAPIでは、ビットマップアノテーションの大きさが変更できないらしいということ。ビットマップアノテーションについての説明に、以下の記述があります。

ビットマップアノテーションを作成するときは、szImagePathに指定されたBMPファイルの内容が作成されるビットマップアノテーションの内容になる。ビットマップアノテーションの幅と高さは、BMPファイル内に含まれる解像度情報と縦横のピクセル数で決まる。解像度情報が含まれない場合は、200dpiとして扱う。

他に、ビットマップアノテーションの大きさを変更できそうな関数も見当たらないので、ドキュワークスに取り込む前に画像処理をしないといけないのかな。



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