この記事は、Powershell Advent Calendar 2018 12/20 の記事です(書いたのは21日ですが気にしないでください)。
要点
- 日々の事務作業の中で作成しなくてはいけない大量の Excelファイルに嫌気がさしていた。
- 社内で新しいソフトの導入とかはご法度である中、Powershell はユーザー権限で使ってよしという許可を得た。
- 最初はスクリプト作成で満足していたが、作業同士の依存関係を記述できるようなツールとして Invoke-Build を導入。
本文
事務屋さんとして主に「PowerShell で Excel をどうのこうのすることに興味を持ってくれると嬉しい」を参考にして xlsxファイルを量産していたわけですが、月次資料の作成とか同じデータからいろんな種類のレポートを作成していて、
「ファイルAを作成するときは、元データとしてBを参照する。もしBが無ければ作る。Aが作成済でもBのタイムスタンプがAより新しければAを更新」
とかいった作業も自動化したくなってきました。
当初は、psake をいじくりましていたのですが、psake では、作業同士の依存関係を記述できない模様。
ほかに手段はと探していたところ、Invoke-Build に行きあたりました。
公式サイトはこちら。
https://github.com/nightroman/Invoke-Build
導入方法
Install-Module InvokeBuild
で一発!! ……と言いたいところだったんですが、当初は社内PCのPowershellが2.0だったため、メインとなる Invoke-Build.ps1 だけをコピーしてきて使ってました。(今は社内PCもWin10になりましたが、Install-Module を動かすには一手間必要だった)
使い方
.build.ps1 というスクリプトに、
task 'レポート作成' {
New-SugoiReport -Path (Convert-Path .)
}
といった感じでタスクを書き連ねていき
Invoke-Build レポート作成
でタスクを実行できます。
入力ファイルと出力ファイルは、
$dir = (Convert-Path .)
$input = Join-Path $dir 元データ.csv
$output = Join-Path $dir レポート.xlsx
# Synopsis: 月次レポートを作成します。
task 'レポート作成' -Inputs $input -Outputs $output {
New-SugoiReport -Inputs $input -Outputs $output
}
といった感じで記述します。
- タスク名がそのまま出力ファイル名、といった仕組みはありません。Inputs は配列でも可ですが、Outputs を配列にすることはできません。
- 出力ファイルが存在しないか、入力ファイルが出力ファイルより新しければタスクが動きます(タイムスタンプで判断)。
タスク同士の依存関係は
task '元データ作成' {
New-MotoData
}
$dir = (Convert-Path .)
$input = Join-Path $dir 元データ.csv
$output = Join-Path $dir レポート.xlsx
task 'レポート作成' -Inputs $input -Outputs $output '元データ作成', {
New-SugoiReport -Inputs $input -Outputs $output
}
こんな感じです。これで「レポート作成」を実行すると「元データ作成」も呼び出されます。
タスクの記法は
$dir = (Convert-Path .)
$input = Join-Path $dir 元データ.csv
$output = Join-Path $dir レポート.xlsx
task 'レポート作成' @{
Inputs = $input
Outputs = $output
Jobs = { New-SugoiReport -Inputs $input -Outputs $output }
}
とかでも可です(splattingというやつですね)。
.build.ps1 のあるフォルダで
Invoke-Build ?
とすれば定義されているタスクが全て表示されます(Synopsisが定義してあればいっしょに出力されます)。
その他
- MSBuild との連携機能とかもあるみたいなんですが、事務作業にしか使っていないのでその辺のことはよく分かりません。
タスクの中からInputsとOutputsを取得することができない(と思う)。これができればビルドスクリプトがもう少しスッキリすると思うんだけど。- 追記 2019/2/6 すいませんードキュメント改めて読んでみたら、タスクの中から $inputs と $outputs で依存ファイル名と出力ファイル名取得できたわー。ずっと気付かんかったー。何でできないと思いこんだんだろ……。