LoginSignup
5
4

More than 3 years have passed since last update.

powershell で Office を捕まえてターミナルとして操作する

Last updated at Posted at 2019-10-03

背景

COM オブジェクトを利用して Office 操作しようとすると変数のガベージコレクトが大変です。何より背後で一度アプリケーション自体が立ち上がっているので遅くてやっていられません。
そこで、 現在開いているファイルを powershell から操作する ようにしてみたらとても便利だったので情報共有です。

アクティブな Office を捕まえる

事前準備として、下記コードを $profile に書いておくかドットソースで読み込んでおきます。

function Get-ActiveOffice {
    <#
        .SYNOPSIS
        現在アクティブなOfficeアプリケーションを捕まえる
        .PARAMETER app
        Office ソフトウェア
    #>
    param (
        [ValidateSet("Word.Application","Excel.Application", "PowerPoint.Application")][string]$app
    )
    try {
        $office = [System.Runtime.InteropServices.Marshal]::GetActiveObject($app)
        if ($app -eq "Word.Application") {
            if ($office.Documents.Count -lt 1) {
                return $null
            }
        }
        elseif ($app -eq "Excel.Application") {
            if ($office.Sheets.Count -lt 1) {
                return $null
            }
        }
        elseif ($app -eq "PowerPoint.Application") {
            if ($office.Presentations.Count -lt 1) {
                return $null
            }
        }
        return $office
    }
    catch {
        return $null
    }
}

Excel を開いていてもすべてのシートが閉じられているなどの状態では何も返さないように、適宜ソフトの種類に応じて条件分岐させています。
そして以下のようにして変数に格納してしまえば、あとは開いているファイルを powershell から操作できるようになります。 文法的には VBA と同一です。 また、 ガベージコレクトが不要です。

# Excel を操作してみる
PS > $e = Get-ActiveOffice "Excel.Application"

PS > $e.Selection.Cells.Value = "hogehoge" # 選択しているセルに「hogehoge」と入力される

powershell が文字通りコンソール(操作盤)となるわけです。
なお、VBA と同様に Excel を操作した場合は Ctrl+Z で元に戻すことができませんが、 Word と PowerPoint ならやり直しが効きます

# Word を操作してみる
PS > $w = Get-ActiveOffice "Word.Application"

PS > $w.Selection.Font.Bold = $true # 選択している文字が太字になる(Ctrl+Zでアンドゥ可能!)

# PowerPoint を操作してみる
PS > $p = Get-ActiveOffice "PowerPoint.Application"

PS > $p.ActivePresentation.Slides.Add(1, 12) # 空白のスライドが追加される

そのままファイルを保存して閉じればプロセスも残りません。マクロの知識を組み合わせれば無限の可能性が開けてきます。また、よく使うマクロを PERSONAL.xlsb に保存しておく代わりに .ps1 に書いておいて powershell から実行できるようになるため、 git などによるバージョン管理なども容易になります

もっと操作しやすくする

上記コマンドレットをラップして、直接 ActiveDocumentActiveSheet を取得できるようにしました。VBA でのおなじみの書き方に近づきます。

function Get-ActiveDocument {
    <#
        .SYNOPSIS
        現在アクティブなWord文書を捕まえるコマンドレット
    #>
    $word = Get-ActiveOffice "Word.Application"
    if (-not $word) {
        return $null
    }
    return $word.ActiveDocument
}
function Get-ActiveSheet {
    <#
        .SYNOPSIS
        現在アクティブなExcelのシートを捕まえるコマンドレット
    #>

    $excel = Get-ActiveOffice "Excel.Application"
    if (-not $excel) {
        return $null
    }
    return $excel.ActiveWorkbook.ActiveSheet
}

PowerPoint は力尽きました……

組み込み定数

VBA の組み込み定数は使用できません。各定数の値を数値として指定する必要があります。毎度ググって入力するのも手間なので記事にまとめました。

5
4
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
5
4