前回までの取り組みで、CSVデータから棒グラフのPNG画像を生成するPowerShellスクリプトを作成した。これで、汎用的なPowerShellスクリプトとして使う上で必要となる最低限の機能は実装したことになる。今回はこのスクリプトから、入力するデータをタブ区切り形式(TSV:Tab-Separated Values)に対応させる方法を取り上げる。
→連載「PowerShell Core入門 - 基本コマンドの使い方」の過去回はこちらを参照。
CSVデータからグラフを書くPowerShellスクリプト
前回の成果物「csv2barchart.ps1」は次の通りだ。
#!/usr/bin/env pwsh
#========================================================================
# 引数を処理
# -CSVFile パス グラフのCSVデータファイルパス
# -PNGFile パス 生成するPNG画像のファイルパス
# -OutFile パス 中間生成されるHTMLファイルパス
# -GraphTitle タイトル グラフのタイトル
# -Width 幅 生成するPNG画像の幅
# -Height 高さ 生成するPNG画像の高さ
#========================================================================
Param(
[Parameter(Mandatory=$true)][String]$CSVFile,
[String]$PNGFile = (Get-Location).ToString() + '\out.png',
[String]$OutFile = (Get-Location).ToString() + '\out.html',
[String]$GraphTitle = 'グラフ',
[Int]$Width = 2000,
[Int]$Height = 1200
)
#========================================================================
# 気温データを取得
#========================================================================
$CsvData = Import-Csv $CSVFile -Header 1,2
# ヘッダを変数に格納
foreach ($Row in $CsvData) {
$CsvHeader1 = $Row.1
$CsvHeader2 = $Row.2
break
}
#========================================================================
# Google Charts用HTMLの用意
#========================================================================
$GoogleChartsHTML1 = @"
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
// Google Visualization APIおよびコアチャートパッケージを読み込み
google.charts.load('current', {'packages':['corechart']});
// Google Visualization API読み込み完了後に実行
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
// データテーブルを作成
var data = new google.visualization.DataTable();
data.addColumn('string', '');
data.addColumn('number', '$CsvHeader2');
data.addRows([
"@
$GoogleChartsHTML2 = @"
]);
// チャートオプションを設定
var options = {'title':'$GraphTitle',
'width':'$Width',
'height':'$Height'};
// 初期化およびチャートの生成
var chart = new google.visualization.BarChart(document.getElementById('chart_div'));
// チャートイメージをbase64エンコードされたPNG画像データとして出力
google.visualization.events.addListener(chart, 'ready', function () {
document.getElementById('chart_base64').innerHTML = chart.getImageURI();
});
// チャートを描画
chart.draw(data, options);
}
</script>
</head>
<body>
<div id="chart_div"></div>
<div id="chart_base64"></div>
</body>
</html>
"@
#========================================================================
# CSVデータをGoogle Chartsで使える形式へ加工
#========================================================================
$GraphData = ""
$FirstLineIs = $true
foreach ($Row in $CsvData) {
if ($FirstLineIs) {
$FirstLineIs = $false
continue
}
$GraphData = $GraphData + "['" + $Row.1 + "'," + $Row.2 + "],"
}
$GraphData = $GraphData.trim(",")
#========================================================================
# Google Charts用のHTMLを出力
#========================================================================
$GoogleChartsHTML1 > $OutFile
$GraphData >>$OutFile
$GoogleChartsHTML2 >>$OutFile
#========================================================================
# WebDriver起動
#========================================================================
webdriver_edge_start.ps1
#========================================================================
# Microsoft EdgeでGoogle Charts用のHTMLをオープン
#========================================================================
$FileURL = "file:///" + $OutFile.Replace('\','/')
'Microsoft Edgeでグラフを描画します。'
Set-SeUrl -Url $FileURL
#========================================================================
# 描画されたグラフをBase64エンコードされたPNGデータとして取得
#========================================================================
'描画したグラフをBase64エンコードされたPNGデータとして取得します。'
$Element = Get-SeElement -By XPath -Value '//*[@id="chart_base64"]'
$Base64 = $Element.Text -replace 'data:image/png;base64,',''
#========================================================================
# Base64エンコードデータをデコードしてファイルへ保存
#========================================================================
'Base64エンコードされたPNGデータをデコードして保存します。'
$Bytes = [Convert]::FromBase64String($Base64)
[IO.File]::WriteAllBytes($PNGFile, $Bytes)
#========================================================================
# WebDriverを終了
#========================================================================
webdriver_edge_stop.ps1
#========================================================================
# 作業用の一時ファイルを削除
#========================================================================
Remove-Item $OutFile
次のようなCSV形式のファイル(data.csv)を指定することで、そのデータに対応したグラフ画像データを生成してくれる。
"場所","気温"
"小河内","17.6"
"青梅","20.8"
"練馬","21.4"
"八王子","20.2"
"府中","20.7"
"東京","21.3"
"江戸川臨海","19.6"
"羽田","18.7"
"大島","19.8"
"大島北ノ山","19.2"
"新島","18.8"
"神津島","17.9"
"三宅島","19.0"
"三宅坪田","20.6"
"八重見ヶ原","21.2"
"八丈島","20.5"
"父島","24.2"
今回は、指定するデータにTSVを指定できるように拡張する。
なぜTSVに対応させるのか
CSVは、データ交換用のフォーマットとして広く普及している。シンプルでわかりやすいため、PowerShellスクリプトに渡すデータ形式としてCSVを採用するのは自然な流れだ。
TSVは、CSVとよく似ているが、こちらはデータの区切りにカンマではなくタブを採用している。TSVもCSV同様、よく使われるフォーマットの一つだ。
特に、TSVはアプリケーション間のコピー&ペーストによく使われている。スプレッドシートでデータをコピーした場合や、Webブラウザでテーブルデータをコピーした場合は、TSVになっていることが多い。データをTSVで保存しておくのもよくあることなので、PowerShellスクリプトとしてもTSVに対応しておくと何かと便利だ。
TSVデータを処理するtsv2barchart.ps1
例えば、先ほどのCSVのファイルをTSVに変換すると次のようになる(data.tsv)。データがタブで区切られていることがわかる。
場所 気温
小河内 17.6
青梅 20.8
練馬 21.4
八王子 20.2
府中 20.7
東京 21.3
江戸川臨海 19.6
羽田 18.7
大島 19.8
大島北ノ山 19.2
新島 18.8
神津島 17.9
三宅島 19.0
三宅坪田 20.6
八重見ヶ原 21.2
八丈島 20.5
父島 24.2
TSVに対応させる方法はいくつかある。コードが重複して存在するとメンテナンスや書き換えが面倒になるので、csv2barchart.ps1を処理の本体とし、tsv2barchart.ps1はTSVデータをCSVデータに変換してからcsv2barchart.ps1を呼び出すスクリプトとして実装するというのが1つの方法になる。
PowerShellにはCSVのデータを読み込むコマンドレットとしてImport-Csvが、CSVとしてデータをファイルに出力するコマンドレットとしてExport-Csvが用意されている。このコマンドレットは区切り文字(デリミタ)を指定するパラメータを持っており、TSVも扱うことができるようになっている。Import-CsvとExport-Csvを使うと、CSVファイルからTSVファイルを生成することができる。
先に、書き換えたものを示しておこう。以下が今回の成果物「tsv2barchart.ps1」だ。