PowerShell で Excel に設定したフォルダを作成する方法
この記事では、PowerShell のスクリプトを使用して Excel を読み込み、Excel で設定された内容にしたがってフォルダを作成する方法をご紹介します。
ソースを一気に掲載してもよいのですが、それだとはまりどころが分からないので部分的にですが先に解説をしておきます。
なお、Excel の設定は以下のように、ドライブ-フォルダ-サブフォルダ…となります。サンプルプログラムでは行数、フォルダ階層を自由に設定できるようになっています。
まずは、処理を実行するか確認するメッセージを表示します。Y が入力された場合のみ処理を実行します。画面には以下のように表示されます。
処理を実行しますか?
[はい(Y)] [いいえ(N)] 既定(N):
この部分のソースは以下のようになります。ユーザーの入力を行うサンプルとして考えることができます。
Write-Host "処理を実行しますか?" $confirm = Read-Host "[はい(Y)] [いいえ(N)] 既定(N)" if ($confirm -ne "Y") { exit }
次にスクリプトのカレントフォルダにあるファイルパスの取得方法です。PowerShell はなぜか相対パスのファイルを読み込めないので絶対パスに変更する必要があります。なお、Convert-Path で相対パスから絶対パスを取得できるのですが、ファイル名を変数にするとうまく動作しなかったため下記のような処理を行っています。
# Excel ファイル名を指定 $fileName = "test.xlsx" $filePath = Split-Path $MyInvocation.MyCommand.Path -Parent #カレントフォルダとファイル名を結合する $filePath = Join-Path $filePath $fileName
Excel は COM 参照を行っているのですがクセがあり、書籍に載っている方法ではうまく Excel を解放してくれませんでした。いろいろ試したところ、以下のようにワークシート、Excelファイル、Excel という順番に COM オブジェクトを解放するとうまくいったので参考にしてみてください。
# COM 参照を解放する [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($ws) [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($wb) [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($xl)
さて、全部の処理のソースコードは以下のようになります。
# # Excel ファイルの指定からフォルダを作成するスクリプト # #処理実行前に確認を行う Write-Host "処理を実行しますか?" $confirm = Read-Host "[はい(Y)] [いいえ(N)] 既定(N)" if ($confirm -ne "Y") { exit } # Excel ファイル名を指定 $fileName = "test.xlsx" #スクリプトのパスからフォルダパスを取得 $filePath = Split-Path $MyInvocation.MyCommand.Path -Parent #カレントフォルダとファイル名を結合する $filePath = Join-Path $filePath $fileName # Excel ファイルの存在チェック if (!(Test-Path $filePath)) { Write-Host "$fileName が存在しません。" exit } #Excel COM 呼び出し $xl = New-Object -ComObject Excel.Application # Excel ファイルを開く $wb = $xl.Workbooks.Open($filePath) # Sheet1 を選択 $ws = $wb.WorkSheets.Item("Sheet1") #変数初期化 $i = 1 $j = 1 $path = $null while ($true) { #ドライブだけ先に取得する $path = $ws.Cells.Item($i, $j).Text $j++ #ディレクトリの指定がなくなるまでパスを取得 while ($true) { if ($ws.Cells.Item($i, $j).Text -eq "") { break } else { $path = Join-Path $path $ws.Cells.Item($i, $j).Text $j++ } } #行がブランクか判定する if ($ws.Cells.Item($i, 1).Text -eq "") { #ブランクの場合は処理を終了する break } else { #パスが存在しない場合のみフォルダを作成する if (!(Test-Path $path)) { #フォルダを作成する # mkdir の処理結果が表示されないように Out-Null を指定している mkdir $path | Out-Null } #一行進む、変数初期化 $i++ $j = 1 } } # Excel ファイルを閉じる $wb.Close() # Excel を終了する $xl.Quit() # COM 参照を解放する [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($ws) [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($wb) [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($xl) #終了メッセージを表示する Write-Host "処理が終了しました。" Pause
企業内の環境では PowerShell の実行ポリシーの関係で外部スクリプトを実行できないようになっているかもしれません。その場合は下記記事を参考にしてください。
スポンサーリンク
Twitter ではブログにはない、いろんな情報を発信しています。
@fnyaさんをフォロー
コメント