この記事では、マクロから複数渡された値を元に実行されたバッチファイルが返す複数の値をマクロ側が個別に受け取る方法についてご説明します。
【動画】マクロから複数渡された値を元に実行されたバッチファイルが返す複数の値をマクロ側が個別に受け取る実際の動き
本題に入る前に、まずは次の動画をご覧ください。
まずはマクロからバッチファイルが呼び出されてバッチファイルが実行されます。
バッチファイルを呼び出す際、バッチファイル側に値を渡します。
バッチファイルが実行されると、その実行結果をマクロ側が受け取って実行結果格納用の変数に格納されます。
次に、格納された実行結果を1行ずつ分割して配列に格納します。
配列に格納された配列から、何回目に実行されたコマンド結果なのか判定し、今回用意したテキストボックスに出力しています。
マクロ作成の流れ
取得した実行結果は、今回テキストボックスに出力しています。
バッチファイルとExcelファイルの例
バッチファイル
@echo off echo (1)pingの実行1 ping %1 echo (2)pingの実行2 ping %2 echo (3)pingの実行3 ping %3
バッチファイルには、pingコマンドを実行するコードが3つ記述されています。
このpingコマンドには、バッチファイルの引数が3つ使われており、pingコマンドそれぞれに「%1」「%2」「%3」の3つの引数が指定されています。
マクロ側から渡された値がそれぞれ「%1」「%2」「%3」に格納されます。
マクロ側から渡された値が渡された後に「%1」「%2」「%3」に格納されて、pingコマンドが実行されます。
Excelファイル
今回は下のExcelファイルを用意しました。
実行ボタンをクリックするとマクロ側からバッチファイルに値が渡されてバッチファイルが実行されます。
バッチファイルが実行されて処理が終了すると、マクロ側がバッチファイルの結果を受け取り、設置されたテキストボックスの実行結果が出力されます。
出力イメージは下のとおりです。
先ほどのバッチファイルで実行されたコマンドごとに、実行結果がそれぞれのテキストボックスに出力されています。
コードの例
Option Explicit Private Sub btn_exec_Click() Dim wsh As Object 'WshShellインスタンス用変数 Dim exec As Object 'バッチファイル実行用変数 Dim batchFilePath As String '呼び出すバッチファイルの格納先 Dim outputVal As String 'バッチファイルが実行した結果格納用変数 Dim AryLines As Variant '1行ごとに分割した実行結果を格納する配列 Dim cmdNumber As Integer 'どのコマンドの実行結果なのかを識別するための変数 Dim cnt As Integer 'カウンタ用変数 Dim arg1 As String 'バッチファイル側に渡す引数用変数1 Dim arg2 As String 'バッチファイル側に渡す引数用変数2 Dim arg3 As String 'バッチファイル側に渡す引数用変数3 'バッチファイル側に渡す引数を取得する(今回は3つ用意) arg1 = "192.168.11.97" arg2 = "192.168.11.98" arg3 = "192.168.11.99" '呼び出すバッチファイルの格納先を取得する batchFilePath = ThisWorkbook.Path & "\0322.bat" 'WshShellオブジェクトからインスタンスを生成する Set wsh = CreateObject("WScript.Shell") 'バッチファイルを実行する Set exec = wsh.exec("cmd /c " & batchFilePath & " " & arg1 & " " & arg2 & " " & arg3) 'バッチファイルで実行されたコマンドの実行結果すべてをテキストボックスに出力する outputVal = exec.StdOut.ReadAll '実行結果を1行ごとに分割してlinesに格納する AryLines = Split(outputVal, vbCrLf) '配列AryLinesの要素数分処理を繰り返すFor文 For cnt = LBound(AryLines) To UBound(AryLines) If InStr(AryLines(cnt), "(1)pingの実行1") > 0 Then '行に「(1)pingの実行1」の文字列が含まれている場合 '1つ目に実行されたコマンドを示す1の値を変数cmdNumberに格納する cmdNumber = 1 ElseIf InStr(AryLines(cnt), "(2)pingの実行2") > 0 Then '行に「(2)pingの実行2」の文字列が含まれている場合 '2つ目に実行されたコマンドを示す2の値を変数cmdNumberに格納する cmdNumber = 2 ElseIf InStr(AryLines(cnt), "(3)pingの実行3") > 0 Then '行に「(3)pingの実行3」の文字列が含まれている場合 '3つ目に実行されたコマンドを示す3の値を変数cmdNumberに格納する cmdNumber = 3 Else '行に「(1)pingの実行1」「(2)pingの実行2」「(3)pingの実行3」のいずれも含まれていない場合 Select Case cmdNumber Case 1 'cmdNumberが1の場合(1つ目に実行されたコマンドの実行結果) '1つ目に実行されたコマンドの実行結果をTextBox1に出力する TextBox1.Text = TextBox1.Text & AryLines(cnt) & vbCrLf Case 2 'cmdNumberが2の場合(2つ目に実行されたコマンドの実行結果) '2つ目に実行されたコマンドの実行結果をTextBox1に出力する TextBox2.Text = TextBox2.Text & AryLines(cnt) & vbCrLf Case 3 'cmdNumberが3の場合(3つ目に実行されたコマンドの実行結果) '1つ目に実行されたコマンドの実行結果をTextBox1に出力する TextBox3.Text = TextBox3.Text & AryLines(cnt) & vbCrLf End Select End If Next cnt End Sub
注目すべきコード①
最初に見て頂きたいのは17行目から19行目です。
'バッチファイル側に渡す引数を取得する(今回は3つ用意) arg1 = "192.168.11.97" arg2 = "192.168.11.98" arg3 = "192.168.11.99"
コードの説明
以上のコードは、バッチ側に渡したい値を取得しているコードです。
今回はバッチファイル側に渡す3つの値を用意しました。
この3つの値がバッチファイル側に渡されます。
注目すべきコード②
次に見て頂きたいのは25行目から28行目です。
'WshShellオブジェクトからインスタンスを生成する Set wsh = CreateObject("WScript.Shell") 'バッチファイルを実行する Set exec = wsh.exec("cmd /c " & batchFilePath & " " & arg1 & " " & arg2 & " " & arg3)
コードの説明
以上のコードは、WshShellオブジェクト用インスタンスを生成し、値をバッチファイルに渡して実行する処理のコードです。
WshShellオブジェクトからインスタンスを生成したら、execメソッドでコマンドプロンプトを開き、コマンドプロンプト上で実行するバッチファイル(batchFilePath)に値を渡して実行します。
実行し終わったら、コマンドプロンプトを閉じます。
「cmd」はコマンドプロンプトの実行ファイル「cmd.exe」を開くコマンドで、「/c」はコマンドを実行した後にコマンドプロンプトを閉じるようにするオプションです。
バッチファイルに値を渡したい場合は、バッチファイルの後ろに半角スペースを挟んで値を指定します。
バッチファイルの後ろに半角スペースを挟んで値を指定することで、バッチファイルを実行する際に値を渡して実行することができます。
今回は3つの値をバッチファイルに渡したいので、半角スペースと値の指定を3回繰り返しています。
注目すべきコード③
次に見て頂きたいのは31行目から34行目です。
'バッチファイルで実行されたコマンドの実行結果すべてをテキストボックスに出力する outputVal = exec.StdOut.ReadAll '実行結果を1行ごとに分割してlinesに格納する AryLines = Split(outputVal, vbCrLf)
コードの説明
以上のコードは、バッチファイルで実行されたコマンドの実行結果すべてをテキストボックスに出力する処理のコードです。
StdOutプロパティからReadAllメソッドを呼び出し、バッチファイルの実行結果をすべて取得します。
今回は取得したバッチファイルの実行結果を個別に受け取ることが目的なので、一旦変数outputValに格納した後、格納された変数outputValの値を1行ずつ分割して配列AryLinesに格納します。
注目すべきコード④
次に見て頂きたいのは37行目です。
'配列AryLinesの要素数分処理を繰り返すFor文 For cnt = LBound(AryLines) To UBound(AryLines)
コードの説明
以上のコードは、配列AryLinesの要素数分処理を繰り返すFor文です。
取得したバッチファイルの実行結果の行数分処理を繰り返します。
注目すべきコード⑤
次に見て頂きたいのは39行目から58行目です。
If InStr(AryLines(cnt), "(1)pingの実行1") > 0 Then '行に「(1)pingの実行1」の文字列が含まれている場合 '1つ目に実行されたコマンドを示す1の値を変数cmdNumberに格納する cmdNumber = 1 ElseIf InStr(AryLines(cnt), "(2)pingの実行2") > 0 Then '行に「(2)pingの実行2」の文字列が含まれている場合 '2つ目に実行されたコマンドを示す2の値を変数cmdNumberに格納する cmdNumber = 2 ElseIf InStr(AryLines(cnt), "(3)pingの実行3") > 0 Then '行に「(3)pingの実行3」の文字列が含まれている場合 '3つ目に実行されたコマンドを示す3の値を変数cmdNumberに格納する cmdNumber = 3
コードの説明
以上のコードは、取得したバッチファイルの実行結果の中からどのコマンドの実行結果なのかを判定し、識別するための変数に値を設定する処理のコードです。
今回はバッチファイルで3つのコマンドを実行しています。(「%1」「%2」「%3」は、マクロ側から渡された値が格納されている引数です)
バッチファイルで記述されたコマンドを複数実行された場合に、マクロ側はそれぞれのコマンドが何番目に実行されたか特定することはできません。
そこで、それぞれのコマンドが何番目に実行されたかを特定するために、バッチファイル側で「何番目に実行されたコマンド」であることが分かるよう補足情報を追記しておきます。
その補足情報は下の赤枠の1文です。
以上の赤枠の情報をマクロ側が拾い、コマンドの実行情報が何番目に実行されたコマンドなのかを特定します。
「コマンドの実行情報が何番目に実行されたコマンドなのかを特定」するのが、39行目、46行目、53行目のIF文です。
1番目に実行されたコマンドの場合は43行目で、どのコマンドの実行結果なのかを識別するための変数cmdNumberに1を格納します。
2番目に実行されたコマンドの場合は51行目でcmdNumberに2を、3番目に実行されたコマンドの場合は58行目でcmdNumberに3を格納します。
なお、39行目、46行目、53行目のIF文の「(1)pingの実行1」「(2)pingの実行2」「(3)pingの実行3」の文字列はバッチファイル側と同じにする必要があるので、違いが無いよう気を付けてください。(IF文の条件に合致しない)
注目すべきコード⑥
次に見て頂きたいのは60行目から89行目です。
Else '行に「(1)pingの実行1」「(2)pingの実行2」「(3)pingの実行3」のいずれも含まれていない場合 Select Case cmdNumber Case 1 'cmdNumberが1の場合(1つ目に実行されたコマンドの実行結果) '1つ目に実行されたコマンドの実行結果をTextBox1に出力する TextBox1.Text = TextBox1.Text & AryLines(cnt) & vbCrLf Case 2 'cmdNumberが2の場合(2つ目に実行されたコマンドの実行結果) '2つ目に実行されたコマンドの実行結果をTextBox1に出力する TextBox2.Text = TextBox2.Text & AryLines(cnt) & vbCrLf Case 3 'cmdNumberが3の場合(3つ目に実行されたコマンドの実行結果) '1つ目に実行されたコマンドの実行結果をTextBox1に出力する TextBox3.Text = TextBox3.Text & AryLines(cnt) & vbCrLf End Select End If
コードの説明
以上のコードは、バッチファイルの実行結果の行に「(1)pingの実行1」「(2)pingの実行2」「(3)pingの実行3」の文字列のいずれも含まれていない場合に、コマンドごとにバッチファイルの実行結果をテキストボックスに出力するコードです。
cmdNumberの値が1の場合は71行目で1つ目に実行されたコマンドの実行結果をTextBox1(1つ目のコマンドの実行結果表示用)に出力します。
cmdNumberの値が2の場合は78行目で2つ目に実行されたコマンドの実行結果をTextBox2(2つ目のコマンドの実行結果表示用)に出力します。
cmdNumberの値が3の場合は85行目で3つ目に実行されたコマンドの実行結果をTextBox3(3つ目のコマンドの実行結果表示用)に出力します。
動作確認
「バッチファイルとExcelファイルの例」をご覧ください。
最後に
この記事では、マクロから複数渡された値を元に実行されたバッチファイルが返す複数の値をマクロ側が個別に受け取る方法についてご説明しました。
マクロから複数渡された値を元に実行されたバッチファイルが返す複数の値をマクロ側が個別に受け取りたい場合は本記事を参考にして頂けたら幸いです。
プログラミングのスキルを習得するなら
プログラミングのスキルを習得したい、今のスキルをもっと高めたい、そう考えているなら「プログラミングスクール」がおすすめです。
プログラミングのスキルの基礎を身につけるなら「TechAcademy」で1週間の無料体験があるので、これで「プログラミングの基礎」を学ぶのにおすすめですよ。