Python(pywin32)でWordを操作する[10] - Word文書をgrepする(ページ数表示, 行数表示, ワイルドカード展開)


# 概要
[前回](https://qiita.com/int_main_void/items/18fd401a627409be5d49)のdocgrep.pyに以下を追加します。

- ワイルドカード展開
- ページ数、行数の表示

#使い方

```console
python docgrep.py [-o] <expr> files... 
```

| 引数 | 省略可否 | 説明 |
|:-:|:-:|:-:|
| `-o`  | 省略可能 | ヒットしたWord文書を表示する。省略した場合はprint出力。  |
| `<expr>`| 必須     | 検索文字列(正規表現) |
| `files...` | 必須  | ファイル名(ワイルドカード指定可能(e.g.*.docx)) |

##出力イメージ

```console
> python docgrep.py "test.*" *.docx
file: C:\xxxx\yyy.docx
page=6, line=56 : testA
...
file: C:\xxxx\zzz.docx
page=10, line=44 : testB
...
```

# コード

```python:docgrep.py
# -*- coding: utf-8 -*-
import argparse
import pathlib
import glob

import win32com.client
import re

def docgrep(expr="", files=[], args_o=False):

    pattern = re.compile(expr)
    wd=win32com.client.DispatchEx("Word.Application")

    quit =True
    for doc in files:
        print(f"file: {doc}")
        found = False
        wdoc = wd.Documents.Open(FileName=doc, ConfirmConversions=None, ReadOnly=True)
        wdoc.ActiveWindow.View.Type=3   # wdPrintView 3

        for sentence in wdoc.Sentences:
            txt = sentence.Text
            m = pattern.search(txt)
            if m:
                found = True
                quit = False
                if not args_o:
                    page = sentence.Information(1) # wdActiveEndAdjustedPageNumber 1 or wdActiveEndPageNumber 3
                    line = sentence.Information(10)  # wdFirstCharacterLineNumber 10
                    print(f"page={page}, line={line} : {txt}")
                else:
                    sentence.Select()
                    break
        if not found or not args_o:
            wdoc.Close(SaveChanges=0)

    if quit or not args_o:
        wd.Quit()
    else:
        wd.Visible = True

if __name__ == "__main__":
    parser = argparse.ArgumentParser(usage="%(prog)s [-o] <expr> files...")
    parser.add_argument("-o", action="store_true")
    parser.add_argument("expr",  type=str)
    parser.add_argument("files", type=str, nargs="*")
    
    args = parser.parse_args()

    fset=set()
    for f in args.files:
        glob_result = glob.glob(f)
        for f in glob_result:
            fset.add(str(pathlib.Path(f).resolve()))

    docgrep(expr=args.expr, files=list(fset), args_o=args.o)
```


#前回と今回利用したWordオブジェクト

＊別途記載



#関連
[Python(pywin32)でWordを操作する[1] - Wordオブジェクトモデル](https://qiita.com/int_main_void/items/16cede139bd64514b810)
[Python(pywin32)でWordを操作する[2] - Wordを起動／終了する](https://qiita.com/int_main_void/items/8776cc4b9b05478273b3)
[Python(pywin32)でWordを操作する[3] - 新規ドキュメント作成](https://qiita.com/int_main_void/items/a36cf348d6eedb31246f)
[Python(pywin32)でWordを操作する[4] - 文字列を入力/取得/削除する](https://qiita.com/int_main_void/items/f135d321262d9de05efc)
[Python(pywin32)でWordを操作する[5] - ドキュメントをファイルに保存する、Wordのオプション変更](https://qiita.com/int_main_void/items/b8549c92b33ea0f7d63b)
[Python(pywin32)でWordを操作する[6] - 特定のタイトルが付いているウィンドウの操作](https://qiita.com/int_main_void/items/6c3569dc242f843ca946)
[Python(pywin32)でWordを操作する[7] - 既存文書を開く/閉じる(Documents.Open(), Document.Close())](https://qiita.com/int_main_void/items/af46e7fe40f528b0b5cd)
[Python(pywin32)でWordを操作する[8] - 段落単位の文字列取得, 統計(ページ数, 段落数,etc)取得](https://qiita.com/int_main_void/items/7c5bc0aab52d8bfadd6e)
[Python(pywin32)でWordを操作する[9] - Word文書をgrepする(docgrep.rb移植)](https://qiita.com/int_main_void/items/18fd401a627409be5d49)
[Python(pywin32)でWordを操作する[10] - Word文書をgrepする(ページ数表示, 行数表示, ワイルドカード展開)](https://qiita.com/int_main_void/items/21df991ce7ae66002d46)

# 参考
- [コマンドライン引数のワイルドカードを展開する-blog.PanicBlanket.com](http://blog.panicblanket.com/archives/1736)
- [カーソル位置を取得するWordマクロワードマクロ-インストラクターのネタ帳](https://www.relief.jp/docs/word-vba-cursor-position.html)
- [WdInformation 列挙 (Word) - msdn](https://msdn.microsoft.com/ja-jp/vba/word-vba/articles/wdinformation-enumeration-word)