2017年3月18日

【PowerShell】新規にExcelファイルを作成して値を入力するスクリプト


新規にExcelファイルを作成して値を入力するスクリプトを作ってみました。


ExcelWorkBookCreate.ps1
# ファイル名
$file = "C:\work\Excel\test15.xlsx"

# Excelオブジェクトの作成
$xl = New-Object -ComObject Excel.Application

# Excelの画面を表示する
$xl.Visible = $true

# 新しいワークブックを作成する
$wb = $xl.Application.Workbooks.Add()

# 1番目のシートのセルA1に書き込む
$wb.Worksheets(1).Range("A1").Value = "Hello Excel !"

# 名前を付けて保存
$wb.SaveAs($file)

# ワークブックを閉じる
$wb.Close

# Excelを終了
$xl.Quit()

# COMオブジェクトの破棄
# 参照カウントが0になるまで繰り返す
do
{
    $cnt = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($xl)
}
while ($cnt -gt 0)

# ガベージコレクションの強制実行
[System.GC]::Collect()
最初このスクリプトを実行してみたところ、スクリプトが終了してExcelファイルも閉じているのにプロセスがなぜか残ってしまいます。

あれっ、なんで!?と思ったのですが、ネットで調べてみるとどうやら結構有名な問題のようです。

で、いろいろ調べたところExcelの場合、明示的にCOMオブジェクトを破棄してあげないといけないようで、具体的には[System.Runtime.Interopservices.Marshal]::ReleaseComObjectメソッドを使い参照カウンタをデクリメントさせればいいようです。

ただ今回の場合、このメソッドを1回呼び出しただけではカウンタが0にならず、プロセスは終了しませんでした。

これは、最初にNew-ObjectでExcelオブジェクトを作成したときにカウントが1になり、次にワークブックを作成した際ににまたカウントされているので、上のスクリプトでは最終的にカウンタが2になっているためのようです。

したがって、[System.Runtime.Interopservices.Marshal]::ReleaseComObjectメソッドを2回呼び出せばカウンタは0になり、プロセスが終了します。

一応、今回はdo...while()でカウンタが0になるまで回すようにしました。


<参考サイト>
PowerShellでExcelの読み書き・ファイル作成
http://mtgpowershell.blogspot.jp/2010/06/excel.html
Powershell Excel Cookbook Ver 2
Marshal.ReleaseComObject メソッド (Object) (System.Runtime.InteropServices)



スポンサーリンク