====== HOW-TO ====== インストール ============ xdwlib は DocuWorks 7.0+ がインストールされた Windows 上の Python 3.7+ で利用できます。 Zip 形式のアーカイブを入手した場合は、それを展開してセットアップ スクリプトを実行します。 :: unzip xdwlib-VERSION.zip cd xdwlib python setup.py install Git をお使いの方は、直接リポジトリから取得することもできます。 :: git clone https://github.com/hayasix/xdwlib.git master cd xdwlib python setup.py install ドキュメントを開く ================== DocuWorks ドキュメントを開くには、次のようにします。 :: from xdwlib import xdwopen doc = xdwopen(PATHNAME) ``doc`` は Document オブジェクトになります。 ここで利用している ``xdwopen()`` は、ユーティリティ関数です。 与えられたパス名の拡張子を見てオープンすべきファイルのタイプ (ドキュメントか バインダーか) を判断し、適切なクラスのオブジェクトを返します。 ``xdwopen()`` を利用しないでドキュメントを開く場合は、次のようにします。 :: from xdwlib.document import Document doc = Document(PATHNAME) doc.open() 開いたドキュメントは、使い終わったら閉じなければなりません。 途中で内容を変更した場合は、必要に応じて保存も行ってください。 自動的に保存されるわけではありません。 :: doc.save() # 変更後のドキュメントを上書き保存します。 doc.close() ドキュメントの属性 ================== ドキュメントには、次の属性があります。show_annotations を除いて、いずれも 読み取り専用属性です。値を設定しても、ドキュメントには反映されません。 ``version`` DocuWorks のバージョン。 ``type`` ドキュメントタイプ。 ドキュメントの場合は ``'DOCUMENT'`` です。 バインダーを開いたときは ``'BINDER'`` になります。 ``dir`` ファイル (``.xdw``) が存在するディレクトリ。 ``name`` ファイル (``.xdw``) のファイル名 (拡張子を含みません)。 これを DocuWorks では文書名と呼んでいます。 ``pages`` ドキュメントのページ数。 ``attachments`` オリジナルデータ (添付ファイル) のリスト (ただし、AttachmentList クラスのインスタンスです)。 ``editable`` ``True`` ならば、ドキュメントは編集できます。 ``annotatable`` ``True`` ならば、ドキュメントのアノテーションを編集できます。 ``printable`` ``True`` ならば、ドキュメントは印刷できます。 ``copyable`` ``True`` ならば、ドキュメントをコピーできます。 ``show_annotations`` ``True`` ならば、アノテーションを表示します。 ``properties`` 文書属性の個数。 ``signatures`` 署名の個数。 ``status`` 署名後の変更等の状態。 電子印鑑の場合、 ``'NONE'`` =未検証, ``'NOEDIT'`` =変更なし, ``'EDIT'`` =変更あり, ``'BAD'`` =異常 を意味します。 電子証明書の場合、 ``'UNKNOWN'`` =未検証, ``'GOOD'`` =変更なし/証明書の信頼なし, 'MODIFIED'`` =変更あり/証明書の信頼なし, ``'BAD'`` =異常, ``'GOOD_TRUSTED'`` =変更なし/証明書の信頼あり, ``'MODIFIED_TRUSTED'`` =変更あり/証明書の信頼あり, をそれぞれ意味します。 以下の属性は、バインダーの場合のみ有効です。こちらも読み取り専用属性です。 ``documents`` バインダーに格納されているドキュメントの数。 ``binder_color`` バインダーの色。 ``binder_size`` バインダーのサイズ。 ページにアクセスする ==================== Document オブジェクトに含まれるページにアクセスするには、 ``page()`` メソッドを使用します。このメソッドは Page オブジェクトを返します。 ``page()`` メソッドの代わりに、インデックスでのアクセスもできます。 いずれの場合も、ページ番号は Python 風に 0 から始まり、また負数を指定すると 末尾からのページ数を指定したことになります。 :: firstpage = doc.page(0) # doc[0] と書いても同じです。 lastpage = doc[-1] Document クラスは、イテレータプロトコルをサポートしています。 そこで、すべてのページにアクセスしたいときは、次のように書けます。 :: # 全ページを OCR 処理します。 for pg in doc: pg.ocr() (注) DocuWorks 9 以上で ocr() するには DocuWorks OCR License for Development Tool Kit をあらかじめ登録しておく必要があります。ただし、環境変数を適切に 設定すれば、 Microsoft Azure Cognitive Services の Computer Vision (OCR) も利用できます。 ページコレクション ================== PageCollection クラスを利用すると、ページ群をひとまとめにして取り扱うことが できます。PageCollection オブジェクトを生成するには、 ``PageCollection()`` とするか、あるいは Document オブジェクトにスライス表記を用いてページ群を 切り出します。 :: # 3-5 ページ目を取り出します。 pc = doc[2:5] # 次のようにしても同じです。 pc = PageCollection() # インスタンスの生成のみ行います。 pc += doc.page(2) # Page オブジェクトを追加できます。 pc += doc[3:5] # PageCollection オブジェクトも追加できます。 PageCollection クラスは、Python が標準で持つ ``list`` を拡張したものです。 ページの順序を入れ替えるような処理には、 ``list`` クラスのメソッドや ``list`` を扱う関数を利用できます。ただし、関数を利用する場合は、 戻り値が ``list`` インスタンスとなるため、再度 PageCollection インスタンスへ 変換しておいた方がよいでしょう。 :: # doc1 は奇数ページだけのドキュメント、doc2 は偶数ページだけのドキュメントとします。 pc = PageCollection(zip(doc1, doc2)) # 奇数ページ・偶数ページを交互に並べてひとつにまとめます。 pc.reverse() # ページ順を逆順に並べ替えます。なお、reversed(pc) では結果は PageCollection ではなく list になります。 pc.export(PATH, flat=True) # 新たなドキュメントとして保存します。バインダーとして保存するには pc.export(PATH, flat=False) とします。 アノテーションにアクセスする ============================ アノテーションは、ページに格納されています。Page オブジェクトから ``annotation()`` メソッドを利用して、アノテーションへアクセスできます。 ここでもまた、配列風の表現も使用できます。 :: ann = pg.annotation(0) # pg[0] と書いても同じです。 ``ann`` は Annotation オブジェクトになります。 Page クラスも、Document クラスと同様に、イテレータプロトコルをサポート しています。 :: # ページ内のすべてのアノテーションの貼り付け位置を表示します。 for ann in pg: print ann.position() ただしこの例では、他のアノテーションの上に貼り付けられている アノテーション (子アノテーション) については扱っていません。 DocuWorks では、アノテーションにアノテーションを貼り付けることもできます。 テキスト付きの付箋などがこれにあたります。 また、グループ化されたアノテーションでは、全体をまとめるアノテーションが ひとつ作られ、元のアノテーション群はその子アノテーションとなっています。 そこで、アノテーションから子アノテーションへ、まったく同様にアクセスする ことができます。 Annotation クラスもまた、イテレータプロトコルをサポートしています。 :: child_ann = ann.annotation(2) # ann[2] でも同じです。 # すべての子アノテーションについて、アノテーションタイプを表示します。 for child_ann in ann: print child_ann.type # ドキュメント 2 ページ目の 4 番目のアノテーションの 3 番目の子アノテーションのアノテーションタイプを表示します。 print doc.page(1).annotation(3).annotation(2).type print doc[1][3][2].type # こう書いても同じです。 アノテーションを追加するには、Page オブジェクトまたは Annotation オブジェクトの ``add_*()`` メソッドを利用します (* には、 ``text``, ``stickey``, ``line/straightline``, ``rectangle``, ``arc``, ``bitmap``, ``stamp``, ``receivedstamp``, ``custom``, ``marker``, ``polygon`` のいずれかが入ります)。 アノテーションの属性 ==================== 各アノテーションには、位置やサイズ、テキスト、色など、 アノテーションタイプに合わせてさまざまな属性 (アトリビュート) があります。 それらは、Annotation オブジェクトの属性として読み取ることができます。 アノテーションの属性を変更するには、単に値を Annotation オブジェクトの属性へ 設定してください。 :: from xdwlib.struct import Point : (中略) pg = doc.page(0) ann = pg.add_text("変更前の文字列") # 既定の位置にテキストアノテーションを貼り付けます。 ann.text = "変更後の文字列" ann.font_size = 10.5 # ポイント ann.font_style = "bold,italic" ann.fore_color = "red" ann.back_color = "none" ann.position = Point(pg.size.x - 200, 75) # 右から 200mm, 上から 75mm の位置へ移動します。 ただし、最終的に ``doc.save()`` を行わなければファイルの内容は変更されない ことに注意してください。 バインダーを開く ================ バインダーを開くには、ドキュメントと同様に ``xdwopen()`` を利用します。 :: from xdwlib import xdwopen xbd = xdwopen(PATHNAME) ``xdwopen()`` はユーティリティ関数でした。与えるパス名の拡張子が ``'.xdw'`` だとドキュメントを開くことになり、 ``'.xbd'`` だとバインダーを開くことに なります。 バインダーを開いた場合は、戻り値が Binder オブジェクトになります。 ``xdwopen()`` を利用せずにバインダーを開くには、次のようにします。 :: from xdwlib.binder import Binder xbd = Binder(PATHNAME) xbd.open() Binder オブジェクトは、0 個以上のドキュメントを含むことができます。 ただし、ここでいうドキュメントは「バインダー内のドキュメント」ですので、 Document オブジェクトとは別の DocumentInBinder オブジェクトになります。 DocumentInBinder オブジェクトにアクセスするには、Binder オブジェクトから ``document()`` メソッドを用います。インデックスでのアクセスもできます。 :: inner_doc = xbd.document(3) # xbd[3] と書いても同じです。 Binder オブジェクトもまたイテレータプロトコルをサポートしています。 :: # すべてのバインダー内ドキュメントについて、文書名を表示します。 for inner_doc in xbd: print inner_doc.name バインダーの中でページを直接指定する (DocumentInBinder オブジェクトを 経由しない) ときは、Binder オブジェクトから直接 ``page()`` メソッドを 用いることもできます。 :: # バインダーの30ページ目 (4 つ目のドキュメントの 5 ページ目) を指定します。 pg = xbd.page(29) equiv_pg = xbd.document(3).page(4) # xbd[3][4] とも書けます。 新たにバインダーを作成するには、 ``create_binder()`` 関数を利用します。 これは作成だけ行いますので、続けてそのバインダーを利用する場合は、 ``xdwopen()`` で開く必要があります。 :: from xdwlib import xdwopen from xdwlib.binder import Binder, create_binder create_binder(PATHNAME, color="red", size="free") xbd = xdwopen(PATHNAME) 開いたバインダーは、使い終わったら閉じなければなりません。 途中で内容を変更した場合は、必要に応じて保存も行ってください。 自動的に保存されるわけではありません。 :: xbd.save() # 変更後のバインダーを上書き保存します。 xbd.close() いくつかの便利なメソッド ======================== view() ------ Document/DocumentInBinder/Binder/Page オブジェクトには ``view()`` メソッドが用意されています。Document/Binder オブジェクトを ``save()`` していなくても、ページを DocuWorks Viewer (Light) で見ることが できます。デバッグ時など、Python の対話モードで利用するのに便利です。 いじってみた結果を ``view()`` で確認し、気に入らなければ ``save()`` しなければよいからです。 :: doc_or_pg.view(light=False, wait=True) ``light`` 真ならば DocuWorks Viewer Light を使用してページを表示します (DocuWorks Viewer Light が使用できなければ、DocuWorks Viewer を 使用します)。 ``False`` ならば DocuWorks Viewer を使用してページを 表示します (DocuWorks Viewer が使用できなければ、DocuWorks Viewer Light を使用します)。 ``wait`` 真ならば DocuWorks Viewer (Light) が終了されるまで処理を停止 します。 ``False`` ならば DocuWorks Viewer (Light) を起動後すぐに 処理を続行します。 ``wait=False`` で呼び出すと、戻り値として各ページのアノテーションの情報 を返します。これを利用すると、ページを表示してアノテーションで追記して もらい、追記した内容を取得する、という対話処理が可能になります。 rasterize() ----------- Document/DocumentInBinder オブジェクトには、 ``rasterize()`` メソッドが 用意されています。アプリケーションページを強制的にイメージページへ 変換します。 このメソッドを使用すると、そのページの元のデータ (アプリケーションテキストや アノテーションのデータ) は失われることに注意してください (アノテーションは 画像としては反映されます)。 解像度・色数は、元のページのものを引き継ぎます。変更したい場合は、 ``export_image()`` と ``insert_image()`` を組み合わせて使用してください。 :: doc.rasterize(pos) ``pos`` ページ位置 (0 から始まります) を指定します。 re_regions() ------------ Page オブジェクトには、 ``re_regions()`` メソッドが用意されています。 ページ内で正規表現に従ってテキストを検索し、発見した箇所の矩形領域 (Rect) のリストを返します。 :: pg.re_regions(pattern) ``pattern`` 正規表現 (Python 標準ライブラリの re モジュールで使用できるもの)。 正規表現でなく文字列を検索する ``text_regions()`` メソッドもあります。 :: pg.text_regions(pattern, ignore_case=False, ignore_width=False, ignore_hirakata=False) ``pattern`` 検索するテキスト。 ``ignore_case`` 真ならば大文字・小文字を区別しません。偽ならば区別します。 ``ignore_width`` 真ならば全角・半角を区別しません。偽ならば区別します。 ``ignore_hirakata`` 真ならばひらがなとカタカナを区別しません。偽ならば区別します。 実際の利用例については、サンプルプログラムの「検索してマーク」をご覧ください。 find_annotations() ------------------ Page オブジェクトおよび Annotation オブジェクトには、 ``find_annotations()`` メソッドが用意されています。 ページ内で指定した条件に従ってアノテーションを検索し、 発見したアノテーションのリストを返します。 :: pg_or_ann.find_annotations(handles=None, types=None, rect=None, half_open=True, recursive=False) ``handles`` 検索対象とするアノテーションハンドルのシーケンス。 ``None`` ならば 限定しません。 ``types`` 検索対象とするアノテーションタイプのシーケンス。 ``None`` ならば限定しません。 アノテーションタイプは、 ``'STICKEY'``, ``'TEXT'``, ``'STAMP'``, ``'STRAIGHTLINE'``, ``'RECTANGLE'``, ``'ARC'``, ``'POLYGON'``, ``'MARKER'``, ``'LINK'``, ``'PAGEFORM'``, ``'OLE'``, ``'BITMAP'``, ``'RECEIVEDSTAMP'``, ``'CUSTOM'``, ``'TITLE'``, ``'GROUP'`` から 指定します (小文字でもかまいません)。 ``rect`` この矩形範囲内に収まっているアノテーションを検索対象とします。 Annotation オブジェクトに対して使用する場合は、ページに直接 貼り付けられたアノテーションならばページ左上が、他のアノテーションに 貼り付けられたアノテーションならば貼り付け先 (親アノテーション) の 左上が、それぞれ原点となります。単位は mm です。 ``half_open`` 真ならば ``rect`` が半開矩形領域であるものと解釈します。 ``recursive`` 真ならばアノテーションに貼り付けられたアノテーション (子アノテーション) も検索対象とします。