LoginSignup
0
2

More than 3 years have passed since last update.

【powershell】 pywin32 経由で現在開いている Word 文書を操作する

Last updated at Posted at 2020-02-02

powershell では python の標準出力を受け取ることができるので(過去記事) pywin32 で処理します。

コード

powershell

とりあえず今回は現在開いている Word 文書のテキスト情報を取得します。

activeWord.ps1
function Get-ActiveWordDocumentTextContent {
    <#
        .SYNOPSIS
        pywin32 を利用して現在開いている Word 文書からテキストを抽出する
    #>
    if ((Get-Process | Where-Object ProcessName -EQ "winword").Count -lt 1) {
        # Word が開かれていた場合にのみ起動する
        return
    }
    $pyCodePath = "{0}\activeword2text.py" -f $PSScriptRoot
    $command = 'python -B "{0}"' -f $pyCodePath
    $result = (Invoke-Expression -Command $command)
    return $result
}

python

pip で pywin32 を取り込んでおきます。

pip install pywin32

メイン処理としては呼び出し側の .ps1 スクリプトと同じディレクトリに下記スクリプトを配置します。

activeword2text.py
"""
pywin32を使用して現在開いている Microsoft Word 文書からテキスト情報を抽出する
"""
import win32com.client
import codecs

def main():
    wdApp = win32com.client.Dispatch("Word.Application")

    if wdApp.Documents.Count < 1:
        if not wdApp.Visible:
            # 不可視のゾンビプロセスを捕まえてしまった場合は終了させる
            wdApp.Quit()
        return 0

    lines_list = []
    content = str(wdApp.ActiveDocument.Content.Text).replace(chr(12),"\r") # 改ページ/改セクションの処理
    content_without_BEL = content.replace(chr(7), "") # 表のセル区切りがBEL文字になるので削除
    for para in content_without_BEL.split("\r"):
        line = str(para).replace(chr(11), "") # 改行(≠改段落)処理
        lines_list.append(line)

    lines = "\n".join(lines_list)

    # コンソール出力時に windows の文字コード(cp932)に変換できない文字を無視しておく
    byte = lines.encode("cp932", "ignore")
    decoded = byte.decode("cp932")
    return decoded

if __name__ == '__main__': 
    print(main(), end="")

実行

powershell 側から呼び出します。

PS > Get-ActiveWordDocumentTextContent

寿限無寿限無
五劫の擦り切れ
海砂利水魚の
水行末雲来末風来末
……

PS > Get-ActiveWordDocumentTextContent | sv t
PS > $t | where {$_ -match "[ぁ-ん]"}

五劫の擦り切れ
海砂利水魚の


powershell 6 では基盤の .Net Core に [System.Runtime.InteropServices.Marshal]::GetActiveObject() のメソッドが含まれていないようで困っていました。今回の内容で対処できて一安心です。

(WindowsPowerShell では上記のメソッドで現在開いている Office ソフトを捕まえて処理することができていました→過去記事

以下、今回の学び:

  • pywin32 で Word インスタンスを作成するとき、その時点ですでに文書が開いている場合はその文書がインスタンスとして割り当てられる。
    • なので、 ActiveDocument で捕まえて VBA 文法でアレコレ操作できる。
    • スクリプト経由で一通り操作してから手動で Word のウィンドウを閉じるだけでプロセスは解放される。
    • New-Object で COM オブジェクトを操作する場合とは対照的。この場合は、インスタンス作成のたびに各インスタンスに対して新たに ActiveDocument が生まれるので「現在開いている文書」の処理は困難。
  • powershell から外部コマンドを Invoke-Expression で呼び出すと、powershell はそのプロセスが終了するのを待ってから次の処理を行う。
    • いわゆる同期処理というシロモノ?
  • powershell は外部プロセスからの標準出力を改行区切りの文字列配列として受け取る。
    • python 側で return None としても None という文字列が出力されたと powershell は解釈する。

Excel に関してはプロセスの解放などが少し異なるようで使いこなせていません。今後の課題です。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2